Spam has become a pain for every mailadministrator. It's flooding mailboxes and messing up message queues.Spam at its finest

In order to prevent Spam from reaching my mailboxes which reside on a Courier-IMAP I combined several anti-spam measures into a maildropfilter rule set. The server is running on Debian Etch and provides mail service through the Courier-Suite which in my case consists of the following packages:

  • courier-authdaemon
  • courier-authlib
  • courier-authlib-ldap
  • courier-authlib-userdb
  • courier-base
  • courier-imap
  • courier-imap-ssl
  • courier-ldap
  • courier-maildrop
  • courier-mta
  • courier-mta-ssl
  • courier-ssl

The MTA delivers incoming mails into the users maildir ($HOME/Maildir) using "/usr/bin/maildrop". Filtering Spam takes place inside maildrop which reads it's global configuration from "/etc/courier/maildroprc".

Attention: Debian has two maildrop-packages, maildrop and couier-maildrop! Both work well, but they were build in different ways. maildrop reads its config from /etc/maildroprc while courier-maildrops expects it to reside in /etc/courier/maildroprc.

The filters used to sort out Spam are consulted in this order (using their Debian package names):

I'm thinking about adding other filters such as DCC or Razor too but for now the above combination works pretty well for me. Each Email-account represents a real POSIX-user with it's home directory on a big storage device. That's because each filter saves user-dependant settings and data in the user's home directory e.g. Bogofilter stores it's bayesian database in '~/.bogofilter/wordlist.db'.

To pass the incoming mail through all of the filters maildrop uses the global configuration file which calls the filters in the appropriate order.

# Maildropfilter for uni.fladi.at # Default actions to take for incoming mails # Check if Junk folder exists. # Otherwise create new one and subscribe to it. `test -d $DEFAULT/.Junk` if( $RETURNCODE == 1 ) { `/usr/bin/maildirmake -f Junk $DEFAULT` `echo INBOX.Junk >> $DEFAULT/courierimapsubscribed` } # Check for whitelist. # If none found create an empty file, otherwise lookup would fail # later on. `test -r $DEFAULT/whitelist` if( $RETURNCODE == 1 ) { `/usr/bin/touch $DEFAULT/whitelist` } # Lookup sender in whitelist. # If no occurance is found in the file the mail is passed to a # sequence of anti spam tools. import SENDER if (!lookup($SENDER, "$DEFAULT/whitelist")) { # Initialise SPAM marker. # 0 ... no spam # 1 ... spam SPAM=0 # Pass mail to bogofilter and update the users bogofilter-db. # Bogofilter adds an extra header indication its suggestion whether # the mailis spam or ham. exception { xfilter "/usr/bin/bogofilter -u -e -p" if (/^X-Bogosity: Spam/) { # Spam detected. Set marker to 1. SPAM=1 } } # Pass mail to spamassassin. # Spamassassin adds an extra header indication its suggestion # whether the mailis spam or ham. exception { xfilter "/usr/bin/spamc" if (/^X-Spam-Flag: YES/) { # Spam detected. Set marker to 1. SPAM=1 } } # Pass mail to razor. # Razor is deactivated due to errors in MIME handling. #exception { # cc "|/usr/bin/razor-check" # if ($EXITCODE == 0) # { # xfilter "/usr/bin/reformail -A'X-Razor: Spam'" # EXITCODE=0 # # Spam detected. Set marker to 1. # SPAM=1 # } # else # { # xfilter "/usr/bin/reformail -A'X-Razor: Ham'" # EXITCODE=0 # } #} # Pass mail to pyzor. # Pyzor indicates its result by passing a return value of 0 which # indicates spam. exception { cc "|/usr/bin/pyzor check" if ($EXITCODE == 0) { xfilter "/usr/bin/reformail -A'X-Pyzor: Spam'" EXITCODE=0 # Spam detected. Set marker to 1. SPAM=1 } else { xfilter "/usr/bin/reformail -A'X-Pyzor: Ham'" EXITCODE=0 } } # Pass mail to DCC. # DCC is deactivated because it indicates too much false positives. #exception { # cc "|/usr/bin/dccproc -Rw whiteclnt -c CMN,25 >/dev/null" # if ($EXITCODE == 67) # { # EXITCODE=0 # xfilter "/usr/bin/reformail -A'X-DCC: Spam'" # SPAM=1 # } # else # { # xfilter "/usr/bin/reformail -A'X-DCC: Ham'" # EXITCODE=0 # } #} # If SPAM marker has been set to 1 by any of the above tests push # the mail into the appropriate folder. # To track detected Spam there's an "echo" statement which writes # to syslog. if ($SPAM == 1) { echo "Spam detected!" to "$DEFAULT/.Junk" } } # Check if vacation has been set for this user. `test -f .vacation.msg` if ($RETURNCODE == 0) { # Vacation file found. # Answer mail with /usr/bin/vacation. cc "|/usr/bin/vacation $LOGNAME" xfilter "/usr/bin/reformail -A'X-Vacation: Sent'" } # All done. If mail has not been deliverd yet, drop it into the # regular inbox.

To instruct Couier-MTA to deliver mails through maildrop the DEFAULTDELIVERY in /etc/courier/courier has to be changed:

DEFAULTDELIVERY="| /usr/bin/maildrop"

Incoming should now be dropped into the "Junk" folder.

Download /etc/courier/maildroprc