Table of Contents

Ubuntu - SpamAssassin - Stopping Spam

Install Mail::Audit

SpamAssassin needs the Mail::Audit module for Perl. Install Mail::Audit (via CPAN)

perl -MCPAN -e shell
cpan> install Mail::Audit
cpan> quit

Install Spam Assassin Modules

Install SpamAssassin from CPAN, which will also install all other required modules too.

perl -MCPAN -e shell
cpan> install Mail::SpamAssassin

It maybe will ask you for some needed modules that aren't installed yet - Answer yes and Perl will fetch and install them, too.

cpan> quit

First look if the install succeded by running:

which spamassassin
/usr/local/bin/spamassassin

If you don't get a right answer something failed… or your PATH-variable isn't set right…

Now lets scan a no spam mail with

spamassassin -t <sample-nonspam.txt |less

Look for a line like this in the output:

X-Spam-Status: No, hits=0 required=5 tests=

Okay fine - now try a bad spam message:

spamassassin -t <sample-spam.txt |less

which should produce some lines like that:

X-Spam-Status: Yes, hits=12 required=5 tests=NO_REAL_NAME,UNDISC_RECIPS,INVALID_DATE,MSGID_HAS_NO_AT,REMOVE_SUBJ,RCVD_IN_OSIRUSOFT_COM
X-Spam-Flag: YES

Okay everything seems working… that was the easy part :-)

The wrapper script

For use with Exim here is a small Perl script which implements the Mail::Audit and the Mail:SpamAssassin module. It will do the actual scanning and will feed a good message back to the Exim MTA with the protocol “spam-scanned”. Install the attached spamcheck.pl to /usr/local/bin.

#!/usr/bin/perl
# This is an small wrapper script around Mail::SpamAssassin for the use
# with the exim MTA.
# Modified to eliminate the buggy Mail::Audit use.
# This modification also eliminates the need to re-submit the message
# to Exim for delivery to the mail spool. Requires localuser director
# to use the spamcheck transport so it knows where to append to.
# It is released under the Terms of GNU General Public License (GPL) so
# use at your own risk!
 
use Mail::SpamAssassin;
use Mail::SpamAssassin::NoMailAudit;
 
$savespam = 1;                      #1/0 should spam be saved centrally?
$spamfile = '/var/mail/spam';       #If you said 1 above - where to put
                                    #that nasty spam? Be sure this mailbox
                                    #is writable by the user who runs this
                                    #script (e.g. mail)
#These are given as command line arguments by exim:
$sender = shift(@ARGV);
$sender = '<>' if $sender eq '';
$recpt = '';
while (@ARGV){
  $recpt = $recpt.' '.shift(@ARGV);
}
 
####### Main script ###########################################################
 
$mail = Mail::SpamAssassin::NoMailAudit->new();
 
$spamtest = Mail::SpamAssassin->new();
$status = $spamtest->check ($mail);
 
#Add the X-Spam Headers:
$status->rewrite_mail ();
#Auto Report to Vipul's Razor:
$status->handle_auto_report ();
 
if ($status->is_spam ()) {
  if ($savespam) {
    $mail->accept($spamfile); # Deliver to spamfile
  } else {
    $mail->accept();          # Deliver to user's mailbox
  }
} else {
  $mail->accept();            # to default incoming mailbox
}

NOTE: Ensure the path to exim is correct and if you want to store detected spam in a mailbox - be sure this mailbox exists and is writeable by the user 'mail'. If not simply create one like this:

touch /var/spool/spam
chmod 660 /var/spool/spam
chown mail:mail /var/spool/spam 

Exim Transport Section

At the end of Exim's transport section add the following:

#Spam Assassin
spamcheck:
   driver = pipe
   command = "/usr/local/bin/spamcheck.pl ${sender_address} ${pipe_addresses}"
   prefix =
   suffix =
   check_string =
   escape_string =
   # for debugging change return_output to true
   return_output = false
   return_path_add = false
   user = mail
   group = mail
   path = "/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin"
   current_directory = "/tmp"

NOTE: Consider improving this for security reasons as required. Make sure that the user you use is entered in the trusted_users option of exim!

Exim Directors Section

If you've installed the Amavis virus scanner you have to modify the condition statement in its director entry like followed:

  #  condition = "${if eq {$received_protocol}{scanned-ok} {0}{1}}"
  # I changed the above to the one below because I have a second check
  # for spam after the antivirus. This is needed to avoid an infinite
  # loop - do not virus scan again when the mail comes back from the
  # spam checker:
  condition = "${if or{ {eq {$received_protocol}{scanned-ok}} {eq {$received_protocol}{spam-scanned}} } {0}{1}}"

This ensures that a mail coming from the spam scan will not be scanned again for viruses. Be sure to change that or you will get an infinite mail loop!

Now add a new director at the top of the Directors section (but right after the Amavis director if installed!!):

#Spam Assassin
spamcheck_director:
   condition = "${if eq {$received_protocol}{spam-scanned} {0}{1}}"
   driver = smartuser
   transport = spamcheck

Okay that's it. We will not add a router entry as we don't want to check our own mails for spam :-). Now open a console with

tail -f /var/log/exim/mainlog

And send some mail to your local users. If you get any errors in the log - well fix them :-). If everything works you can reenable the fetchmail demon again.

What else?

Copy the spamassasin.cf to /etc if you want to adjust the scores of the used spam tests.

NOTE: The spamcheck.pl is just a small hack. It should be much more better…

References

http://web.archive.org/web/20041116091629/http://bogmog.sourceforge.net/document_show.php3?doc_id=28

http://web.archive.org/web/20041025034458/http://www.sbicomputing.com/scripts/spamcheck.pl

http://dman13.dyndns.org/~dman/config_docs/exim-spamassassin/