I wrote a small script to analyse spam messages that are spam false negative; meaning that they are spam messages in nature but that happened to be in your INBOX folder because your spam filter failed to detect it correctly (I personally use SpamAssassin and unfortunately it rarely happens).

The goal is to have a chance to analyse spam messages that are put in spam folder manually by running a script in cron jobs.

Obviously, all spam messages will be analysed regardless of which email client you're using (Thunderbird, Kaiten Mail or Roundcube), because all you need is to have a message moved in spam folder.

Example of my well working PHP script:

// Check if there is messages in SPAM folder that don't have [SPAM] lable (e.g.: manually moved from INBOX)
exec("grep -L '\[SPAM\]' /home/domainexample.ru/Maildir/.Junk/cur/* 2> /dev/null", $spam_messages);

if (!empty($spam_messages)) {

    $sa_learn = '/usr/bin/sa-learn --spam';
    foreach ($spam_messages as $spam_message) {
        //Learn a message that we believe is spam
        $sa_learn .= ' ' . $spam_message;
        $marked_as_spam = file_get_contents($spam_message);
        // Adding [SPAM] flag to message's subject of analyzed message
        $marked_as_spam = str_replace("Subject:", "Subject: [SPAM] ", $marked_as_spam);
        file_put_contents($spam_message, utf8_encode($marked_as_spam));
    // Logging the results
    $sa_learn .= ' > ' . '/home/domainexample.ru/.spamassassin/logs/' . date('d.m.Y-G:i') . '_analyzer.log';
    //Executing analyzer in background 
    shell_exec("nohup $sa_learn 2> /dev/null & echo $!");
    // Cleaning cached messages in Dovecot
    shell_exec("rm -f /var/lib/dovecot/index/domainexample.ru/.Junk/*");

I would like to have (in case there are) few ideas for improving this already working PHP script but most importantly, I would like to learn of how to write the same script using PERL or/and BASH scripting.

Could you please suggest some ideas for improving current PHP script, along with providing pure and fully working examples of the same scenarios in PERL or/and BASH?

  • \$\begingroup\$ Interesting script, but it's a bit of a tall order to do all of these things. If you focus on either a single language (and show us the code if it's not PHP), you probably have a better chance at getting an answer. Judging by the use of exec and shell_exec it should be easy to convert this to a Bash script. \$\endgroup\$
    – l0b0
    Jun 7, 2013 at 6:52
  • \$\begingroup\$ It wouldn't be that easy for me to do it, as I'm not familiar with Perl, for instance. If I do it, it will take much time for me and only few minutes for an expert in either Bash or Perl. I have just proposed to provide any example Bash or/and Perl. \$\endgroup\$
    – Ilia Ross
    Jun 8, 2013 at 6:57

1 Answer 1


Here's an untested Bash version:

#!/usr/bin/env bash
set -o errexit -o noclobber -o nounset

while IFS= read -r -u 9 path
    /usr/bin/sa-learn --spam "$path" \
        > "/home/domainexample.ru/.spamassassin/logs/$(date +%d.%m.%Y-%G:%S)_analyzer.log" \
        2>&1 &
    sed -i -e 's/^Subject:/Subject: [SPAM] /' "$path"
    rm "$path"
done 9< <(grep -FL '[SPAM]' /home/domainexample.ru/Maildir/.Junk/cur/* 2> /dev/null)

Some changes from the original:

  • Uses grep's -F option to speed up search.
  • Runs sa-learn repeatedly instead of once to avoid having to accumulate the data. Shouldn't slow down the execution since the processes are backgrounded.
  • Deletes files as soon as they are processed, to avoid reprocessing if the previous run failed.
  • \$\begingroup\$ Based on the logic above, it's so different from PHP and I don't see how the $path is created / looped. Your example unfortunately is not working. I checked it on the test server and nothing is happening - logs are not created, messages are not processed, clean up is not deleting anything. What is wrong? \$\endgroup\$
    – Ilia Ross
    Jun 11, 2013 at 7:44
  • \$\begingroup\$ As logs are empty, I can't tell what is going on there. The script execution I just hanging.. Until you click CTRL+C \$\endgroup\$
    – Ilia Ross
    Jun 12, 2013 at 8:16
  • \$\begingroup\$ Yes. It print's out everything in console. \$\endgroup\$
    – Ilia Ross
    Jun 12, 2013 at 8:30
  • \$\begingroup\$ Yes, correct, logs are created every-time and it's just empty.. \$\endgroup\$
    – Ilia Ross
    Jun 12, 2013 at 8:36
  • \$\begingroup\$ let us continue this discussion in chat \$\endgroup\$
    – l0b0
    Jun 12, 2013 at 8:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.