Adding spam filtering and anti-virus to your Postfix server

This is a follow-up to my post about setting up IMAP and SMTP on CentOS 7. In this article, we'll add spam filtering with Amavisd-new and Spamassassin, anti-virus with ClamAV, and we'll do server-side email filtering with sieve and Dovecot.

Enable EPEL

If you haven't done so already, you'll need to enable the EPEL repository to provide for some required packages that exist outside of the main CentOS repos:

[root@host /]# yum install epel-release
[root@host /]# yum update

Spam filtering and anti-virus

For spam filtering and anti-virus you'll need to add a few more packages:

[root@host /]# yum install amavisd-new clamav clamav-update dovecot-pigeonhole

Edit /etc/freshclam.conf and comment out the line that reads "Example":


Then update the ClamAV database:

[root@host /]# freshclam

To enable auto-update of the ClamAV database, edit /etc/sysconfig/freshclam and remove these four lines:

### !!!!! REMOVE ME !!!!!!
### REMOVE ME: By default, the freshclam update is disabled to avoid
### REMOVE ME: network access without prior activation

Next we need to configure Amavisd. Edit /etc/amavisd/amavisd.conf and add your domain name and fully-qualified hostname:

$mydomain = 'yourdomain.com';
$myhostname = 'host.yourdomain.com';

Check your /etc/postfix/master.cf configuration. The amavisd-new package should have added some configuration. The smtp service should have been modified with the following:

# ==========================================================================
# service type  private unpriv  chroot  wakeup  maxproc command + args
#               (yes)   (yes)   (no)    (never) (100)
# ==========================================================================
smtp      inet  n       -       n       -       -       smtpd
   -o receive_override_options=no_address_mappings
   -o content_filter=smtp-amavis:

At the bottom of /etc/postfix/master.cf, the following should be added:

smtp-amavis  unix  -    -       y       -       2       smtp
 -o smtp_data_done_timeout=1200
 -o disable_dns_lookups=yes
 -o smtp_send_xforward_command=yes inet n  -       y       -       -       smtpd
 -o content_filter=
 -o smtpd_helo_restrictions=
 -o smtpd_sender_restrictions=
 -o smtpd_recipient_restrictions=permit_mynetworks,reject
 -o mynetworks=
 -o smtpd_error_sleep_time=0
 -o smtpd_soft_error_limit=1001
 -o smtpd_hard_error_limit=1000
 -o receive_override_options=no_header_body_checks
 -o smtpd_helo_required=no
 -o smtpd_client_restrictions=
 -o smtpd_restriction_classes=
 -o disable_vrfy_command=no
 -o strict_rfc821_envelopes=yes

Assuming that all looks good, we're ready to enable Spamassassin and Amavisd. First, stop Postfix:

[root@host /]# systemctl stop postfix

Then enable and start Spamassassin and Amavisd, and finally restart Postfix:

[root@host /]# systemctl enable spamassassin amavisd
[root@host /]# systemctl start spamassassin amavisd postfix

Check to ensure that the services are running and listening on TCP port 25, and on localhost TCP ports 10024 and 10025:

[root@host /]# netstat -an | more
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp        0      0    *               LISTEN
tcp        0      0*               LISTEN
tcp        0      0*               LISTEN

Two cron jobs should have been added by the clamav and spamassassin packages, in /etc/cron.d/clamav-update and /etc/cron.d/sa-update. As a last step for these two, check those files and ensure that the cron line isn't commented out. You want to be sure to get your updates properly.


Finally, let's enable sieve filtering to sort spam and virus-infected emails on the server side, rather than relying on our email client to do it. You'll need to edit two Dovecot configuration files:

# /etc/dovecot/conf.d/90-sieve.conf

# enable the sieve plugin
plugin {
  sieve = file:~/sieve;active=~/.dovecot.sieve

# /etc/dovecot/conf.d/15-lda.conf

# ensure the global $mail_plugins is enabled
protocol lda {
  mail_plugins = $mail_plugins

Then restart Dovecot:

[root@host /]# systemctl restart dovecot

Now you can either create a default sieve config at /var/lib/dovecot/sieve/default.sieve or you can create a ~/.dovecot.sieve file for each user. The default sieve config is only used if a user does not have an existing ~/.dovecot.sieve script. In either case, you will need to pre-compile your sieve script using the sievec command:

[root@host sieve]# sievec default.sieve

You can do a lot of advanced filtering and sorting with sieve. As a starting point, you can find some examples here. This example script sorts emails marked as spam or virus-infected into the user's Junk folder and marks them as read:

require ["envelope", "fileinto", "imap4flags", "regex"];

if anyof (header :contains "X-Spam-Level" "*****",
      header :contains "X-Virus-Status" "Infected") {
if header :contains "X-Spam-Level" "*****" {
    fileinto "Junk";
    setflag "\\Seen";
else {
    fileinto "Infected";

That's it! Your Postfix server should now be filtering spam and email viruses. If you want to test it, send yourself a message from an external account with the EICAR virus in the body:


Then check your /var/log/maillog. You should see a log entry that says something like:

Blocked INFECTED (Eicar-Test-Signature) {DiscardedOpenRelay,Quarantined}

If so, Amavisd is working. There is also a similar test for UBE (Unsolicited Bulk Email, AKA spam), called GTUBE.

Anyway, I hope you've found this tutorial useful. Thanks for reading.