Integrate DSPAM into postfix + dovecot + any mail client

Recently I figured that my spamasassin setup stopped working correctly for some reason. At first I didn't see that, then I didn't care immediately as Thunderbird ist still 99% right, but when using Roundcube while "Thunderbird at home" is shut down, it became more and more annoying. I rechecked my setup twice, started all over, re-trained it for almost a week, to no dice.

So I watched out for alternatives. DSPAM. There is nothing else, really. To say one thing upfront: it works from the start, even while being in training phase still.

The benefits:

  • Mail client agnostic for retraining. I use dovecot2-antispam for that.
  • Instant retrain. No cronjobs.
  • Low system resource consumption
  • Near-to-perfect detection rates
  • Better insight through dspam_stats and syslog features 

After half a day of struggeling, here goes my setup. Big thanks to http://www.owlfish.com/thoughts/dovecot-antispam-2011-03-21.html - it just needed some minor adjustments on a recent Arch Linux box.

1 . Install required packages

This pulls in dovecot2-antispam-plugin-hg from the AUR. Be aware that dovecot-antispam-git does NOT work with dovecot-2.x!

yaourt -S dspam dovecot2-antispam-hg

2 . Setup dspam

Setup the database

As user postgres:

createuser -P -S -R -E -D dspam
createdb -O dspam dspam
psql -U dspam -d dspam < /usr/share/dspam/pgsql/pgsql_objects.sql
psql -U dspam -d dspam < /usr/share/dspam/pgsql/virtual_users.sql

Configure dspam

Edit /etc/dspam/dspam.conf. The important stuff is:

...
StorageDriver /usr/lib/dspam/libpgsql_drv.so
TrustedDeliveryAgent "/usr/sbin/sendmail"
UntrustedDeliveryAgent "/usr/lib/dovecot/deliver -d %u"
...
TrainingMode toe
...
Tokenizer osb
...
Preference "trainingMode=TOE"           # { TOE | TUM | TEFT | NOTRAIN } -> default:teft
Preference "spamAction=deliver"         # { quarantine | tag | deliver } -> default:quarantine
Preference "statisticalSedation=5"      # { 0 - 10 } -> default:0
Preference "enableBNR=on"               # { on | off } -> default:off
Preference "signatureLocation=headers" # { message | headers } -> default:message 
...
PgSQLServer /run/postgresql/
PgSQLUser dspam
PgSQLPass secret
PgSQLDb dspam
...
IgnoreHeader DKIM-Signature
IgnoreHeader X-Bogosity
IgnoreHeader X-Spam-Checker-Version
IgnoreHeader X-Spam-Flag
IgnoreHeader X-Spam-Level
IgnoreHeader X-Spam-Status
IgnoreHeader X-GMX-Antispam
IgnoreHeader X-GMX-Antivirus
IgnoreHeader X-UI-Filterresults
...
ParseToHeaders on
ChangeModeOnParse off
ChangeUserOnParse full
...
ServerPID /run/dspam/dspam.pid
...
ServerDomainSocketPath "/run/dspam/dspam.sock"
...
ClientHost /run/dspam/dspam.sock

I didn't touch the rest.

Now start dspam daemon with 
systemctl enable dspam
systemctl start dspam

3 . Setup postfix

  • Edit /etc/postfix/master.cf and add the required transports.
dspam     unix  -       n       n       -       10      pipe
  flags=Ru user=dspam argv=/usr/bin/dspam --deliver=innocent,spam --user $recipient -i -f $sender -- $recipient

dovecot   unix  -       n       n       -       -       pipe
  flags=DRhu user=mail:mail argv=/usr/lib/dovecot/deliver -f ${sender} -d ${recipient}

Note that the ArchLinux package for dspam in [community] installs dspam with dspam:dspam permissions on all folders involved, so user=dspam matters!

  • Create /etc/postfix/dspam_filter_access with following filter definition
​/./   FILTER dspam:unix:/run/dspam/dspam.sock
  • Edit /etc/postfix/main.cf and configure postfix to use the dovecot mail transport and require the above filter rule for any smtp client.
# edit this one, has been "dovecot-spamasassin" before here
virtual_transport = dovecot

# new settings for dspam
dspam_destination_recipient_limit = 1
smtpd_client_restrictions =
   permit_sasl_authenticated
   check_client_access pcre:/etc/postfix/dspam_filter_access

4 . Setup dovecot

  • Edit /etc/dovecot/dovecot.conf and enable the antispam plugin
...
mail_plugins = $mail_plugins imap_quota antispam
...
  • Edit /etc/dovecot/conf.d/90-plugin.conf
plugin {
...
   # Antispam (DSPAM)
   antispam_backend = dspam
   antispam_allow_append_to_spam = YES
   antispam_spam = Spam;Junk
   antispam_trash = trash;Trash;Gelöschte*;Papierkorb
   antispam_signature = X-DSPAM-Signature
   antispam_signature_missing = error
   antispam_dspam_binary = /usr/bin/dspamc
   antispam_dspam_args = --user;%Lu;--deliver=spam,innocent;--source=error;--signature=%%s
   antispam_dspam_spam = --class=spam
   antispam_dspam_notspam = --class=innocent
   antispam_dspam_result_header = X-DSPAM-Result
}