Integrate Spamassassin as antispam solution between postfix and dovecot on Debian 8 Jessie

System environment:

  • debian jessie (8.x)
  • postfix (2.11.3-1)
  • dovecot with sieve and antispam plugin (1:2.2.13-12~deb8u)
  • spamassassin (3.4.0-6)

When everything is finished, we have the following setup:

  • postfix receives the mail
  • postfix sends to spamassassin
    • spamassassin only uses content classificaton stuff and does NO dns-blacklist lookups as configured in /etc/spamassassin/local.conf
  • spamassassin sends mail to dovecot for delivery
  • dovecot triggers a sieve filter to look for spam-header-flag=yes and moves mail into Spam folder
  • if mail is moved within dovecot (via imap user action), dovecot-antispam plugin triggers train/retrain stuff in SA for that particular email

Installation / Setup

First install needed stuff on our fully functioning mailserver:

apt-get install spamassassin spamc dovecot-antispam dovecot-sieve

vim /etc/default/spamassassin

# /etc/default/spamassassin
# Duncan Findlay

# WARNING: please read README.spamd before using.
# There may be security risks.

# If you're using systemd (default for jessie), the ENABLED setting is
# not used. Instead, enable spamd by issuing:
# systemctl enable spamassassin.service
# Change to "1" to enable spamd on systems using sysvinit:

# Options
# See man spamd for possible options. The -d option is automatically added.

# SpamAssassin uses a preforking model, so be careful! You need to
# make sure --max-children is not set to anything higher than 5,
# unless you know what you're doing.
OPTIONS="--create-prefs --max-children 5 --helper-home-dir --allow-tell --timeout-child 30 --username debian-spamd"

# Pid file
# Where should spamd write its PID to file? If you use the -u or
# --username option above, this needs to be writable by that user.
# Otherwise, the init script will not be able to shut spamd down.

# Set nice level of spamd
#NICE="--nicelevel 15"

# Cronjob
# Set to anything but 0 to enable the cron job to automatically update
# spamassassin's rules on a nightly basis

vim /etc/spamassassin/

# alter the mails subject
#rewrite_header Subject [***SPAM***]

# do not alter the body (0=do nothing, 1=add as attachment, 2=...)
report_safe 0

# the required spam score is 2.0 points... lets start with that
required_score 2.0

# Enable the Bayes system
use_bayes               1
use_bayes_rules         1
bayes_auto_learn        1

# Disable network checks
skip_rbl_checks         1
skip_uribl_checks       1
use_razor2              0
#use_dcc                0
use_pyzor               0

# Set headers which may provide inappropriate cues to the Bayesian classifier
bayes_ignore_header X-Bogosity
bayes_ignore_header X-Spam-Flag
bayes_ignore_header X-Spam-Stat

vim /etc/postfix/

# Transport: Postfix -> Spamassassin -> Dovecot
spamass-dovecot unix -     n       n       -       -       pipe
  flags=DRhu user=vmail:vmail argv=/usr/bin/spamc -u debian-spamd -e /usr/lib/dovecot/deliver -d ${recipient}

vim /etc/postfix/

virtual_transport = spamass-dovecot

vim /etc/dovecot/conf.d/99-custom.conf

listen = *
protocols = imap sieve
log_timestamp = "%Y-%m-%d %H:%M:%S "
disable_plaintext_auth = yes

# Outlook Express and Windows Mail works only with LOGIN mechanism, not the standard PLAIN
auth_mechanisms = plain login

mail_access_groups = vmail
default_login_user = vmail
mail_privileged_group = vmail
mail_location = maildir:/home/vmail/%d/%n/Maildir
postmaster_address =

passdb {
    driver = passwd-file
    args = scheme=SHA1 /etc/dovecot/users.conf
userdb {
    driver = static
    args = uid=5000 gid=5000 home=/home/vmail/%d/%n/Maildir allow_all_users=yes
service auth {
    # places the Dovecot SASL socket in the given path
    unix_listener /var/spool/postfix/private/auth {
        mode = 0660
        # Assuming the default Postfix user and group
        user = postfix
        group = postfix
    user = root
service imap-login {
    process_min_avail = 1
    user = vmail
protocol imap {
    mail_max_userip_connections = 512
    imap_idle_notify_interval = 24 mins
    mail_plugins = $mail_plugins antispam
protocol lda {
    log_path = syslog
    mail_plugins = $mail_plugins sieve
    mail_fsync = optimized
plugin {
    sieve = ~/.dovecot.sieve
    sieve_dir = ~/sieve
    sieve_global_dir = /etc/sieve/
    sieve_global_path = /etc/sieve/default.sieve
plugin {
    antispam_backend = pipe
    antispam_signature = X-Spam-Flag
    antispam_signature_missing = move

    antispam_trash = trash;Trash;Deleted Items;Deleted Messages
    antispam_trash_pattern = trash;Trash;Deleted *
    antispam_trash_pattern_ignorecase = TRASH

    antispam_spam = Spam;Junk
    antispam_spam_pattern = spam;Spam;junk;Junk
    antispam_spam_pattern_ignorecase = SPAM;JUNK

    antispam_pipe_tmpdir = /var/tmp
    antispam_pipe_program = /usr/bin/spamc
    antispam_pipe_program_args = --username;debian-spamd
    antispam_pipe_program_spam_arg = --learntype=spam
    antispam_pipe_program_notspam_arg = --learntype=ham

    #antispam_debug_target = syslog
    #antispam_verbose_debug = 1

# begin of ssl configuration
ssl = yes
ssl_cert = </etc/postfix/ssl/postfix.cert
ssl_key = </etc/postfix/ssl/postfix.key
# end of ssl configuration

Create sieve filter that puts mails with X-Spam-Flag=YES header into spam folder

Create sieve folder

mkdir -p /etc/sieve

Create and edit Sieve filter file:

vim /etc/sieve/default.sieve

require ["fileinto", "mailbox"];
# fileinto: for putting mail into a imap folder
# mailbox: for creating imap folder if not exists
if header :contains "X-Spam-Flag" "YES" {
    # move mail into Folder Spam, create folder if not exists
    fileinto :create "Spam";

Compile that sieve filter and fix owner:

sievec -D /etc/sieve/default.sieve
chown -R vmail:vmail /etc/sieve

Train spamassassin

Train with existing mails in your inbox, archive, etc as HAM (good mail) and with mails in your existing junk folder as SPAM (bad mail).

### train for SPAM
su debian-spamd
sa-learn --spam -u debian-spamd --showdots --dir /home/vmail/*

### train for HAM
su debian-spamd
sa-learn --ham -u debian-spamd --showdots --dir /home/vmail/*
sa-learn --ham -u debian-spamd --showdots --dir /home/vmail/*
sa-learn --ham -u debian-spamd --showdots --dir /home/vmail/*
sa-learn --ham -u debian-spamd --showdots --dir /home/vmail/*
sa-learn --ham -u debian-spamd --showdots --dir /home/vmail/*
sa-learn --ham -u debian-spamd --showdots --dir /home/vmail/*
sa-learn --ham -u debian-spamd --showdots --dir /home/vmail/*
sa-learn --ham -u debian-spamd --showdots --dir /home/vmail/*
sa-learn --ham -u debian-spamd --showdots --dir /home/vmail/*
sa-learn --ham -u debian-spamd --showdots --dir /home/vmail/*
sa-learn --ham -u debian-spamd --showdots --dir /home/vmail/*
sa-learn --ham -u debian-spamd --showdots --dir /home/vmail/*

Spamassassing maintenance

su debian-spamd
sa-update --verbose

My Spamassassin bayes Database after a few months:

root@xxx:~$ ls -lah /var/lib/spamassassin/.spamassassin
total 5.7M
drwx------ 3 debian-spamd debian-spamd 4.0K Dec 29 19:47 .
drwxr-xr-x 6 debian-spamd debian-spamd 4.0K May 18  2015 ..
-rw------- 1 debian-spamd debian-spamd  29K Dec 29 21:44 bayes_journal
-rw------- 1 debian-spamd debian-spamd 2.4M Dec 29 19:47 bayes_seen
-rw------- 1 debian-spamd debian-spamd 5.2M Dec 29 19:47 bayes_toks
drwxr-xr-x 2 debian-spamd debian-spamd 4.0K May 18  2015 sa-compile.cache
-rw-r--r-- 1 debian-spamd debian-spamd 1.9K May 18  2015 user_prefs