top image
home  /  pages  /  tech tips  /  contact about

Prevent spam with Mail Avenger, exim, SpamAssassin, bogofilter, procmail, and DNS


You receive too much spam.


spam, mailavenger, Mail Avenger, exim, DNS, procmail, SpamAssassin, bogofilter, Ubuntu, Debian.


It's not really a solution. It's a half-hearted attempt.

The attempt breaks down into several categories: making it hard to find you, making it hard to mail you, and then using the obvious tools to flag mail as spam.

Obviously, I'm not the first one to take a crack at this problem. Pretty much everything you read here I stole from other places.

Making it hard to find you: DNS

This is taken from the Spamassassin / OtherTricks wiki page. Instead of configuring a single MX, configure many, most of them fake:   28800   IN      MX   10   28800   IN      MX   20   28800   IN      MX   30   28800   IN      MX   40   28800   IN      MX   50   28800   IN      MX   60   28800   IN      MX   70   28800   IN      MX   80   28800   IN      MX   90
Most spam / zombie software will give up after trying (and failing) on the first MX ( However, RFC compatible mail servers will move on to Also, zombies that pick an MX at random have a reduced chance of picking the correct MX.

I strongly advise you to configure the lowest numbered MX to immediately reject TCP connections (by letting the operating system send a TCP RST packet, for example using an iptables REJECT rule) rather than having clients time out.

Preparation: configuring exim to work with Mail Avenger

First, it is likely you'll want to support virtual domains. This document assumes you followed the instructions for handling mail for multiple virtual domains with exim4.

The changes you need to make to exim are to (among other things) allow emails with a '+' in them to work properly, which is one of the neat things you can do with Mail Avenger.

Create an avenger transport file /etc/exim4/conf.d/transport/30_exim4-config_avenger_pipe.

# /etc/exim4/conf.d/transport/30_exim4-config_avenger_pipe
  debug_print = "T: avenger_pipe for $local_part@$domain"
  driver = pipe
  path = "/bin:/usr/bin:/usr/local/bin"
  command = "/usr/local/libexec/avenger.local -D $local_part@$domain -d $local_part"
Secondly, create an avenger router /etc/exim4/conf.d/router/650_exim4-config_avenger.
# /etc/exim4/conf.d/router/650_exim4-config_avenger
  debug_print = "R: avenger for $local_part@$domain"
  driver = accept
  domains = +local_domains
  transport = avenger_pipe
  require_files = /usr/local/libexec/avenger.local
Finally, modify /etc/exim4/conf.d/router/350_exim4-config_vdom_aliases to accept '+' in email addresses.
# /etc/exim4/conf.d/router/350_exim4-config_vdom_aliases
  driver = redirect
  local_part_suffix = +*
  domains = dsearch;/etc/exim4/conf.d/virtual
  data = ${expand:${lookup{$local_part}lsearch*@{/etc/exim4/conf.d/virtual/$domain}}}
  pipe_transport   = address_pipe
  file_transport   = address_file
Finally, you need to make sure exim only listens on localhost port 25. On Debian and Ubuntu, edit /etc/exim4/update-exim4.conf.conf and make sure that:
This frees up port 25 for Mail Avenger. Restart exim.
sudo /etc/init.d/exim4 restart
It is a good idea to keep an eye on /var/log/exim4/mainlog and /var/log/exim4/paniclog.

Making it hard to mail you: Mail Avenger

Mail Avenger is an elegant SMTP server that allows intended recipients to verify mail even before the mail has been accepted. Simply put, Mail Avenger picks up the phone, asks who's talking, puts the caller on hold, then talks to you, and hangs up on the caller should you decide you're not interested. You can decide this based on the sender address, based on the actual body of the message, and even on things like the TCP SYN fingerprint of the client SMTP server.

Mail Avenger does a number of standard checks for you. First, it verifies that the sender can receive bounce messages (without actually sending one), which weeds out bogus senders. Secondly, it performs SPF checks on the sender, and, optionally, it can perform greylisting: deferring the sender, telling it to try again in a few minutes. This will, in some cases, slow down email a little bit, but it discourages most spammers, while RFC compliant senders will keep trying to deliver the message every few minutes.

There is no Ubuntu / Debian package for Mail Avenger (yet), so you have to compile and install it by hand. Follow the steps outlined in the Mail Avenger installation instructions. I remember having to install quite a few packages before being able to compile and build Mail Avenger. I configured and installed Mail Avenger as follows.

sudo ./configure --enable-sasl --enable-ssl
sudo make install
After step 5 from the Mail Avenger installation instructions (when you create /etc/avenger), make sure the directory is readable to the newly created avenger user:
sudo chmod 755 /etc/avenger/
Here is my /etc/avenger/asmtpd.conf.
# /etc/avenger/asmtpd.conf

# replace with your real IP

Separator +
Sendmail /usr/sbin/rmail

AvengerUser Debian-exim


MaxClients 60
MaxConPerIP 10
MaxRcpts 5
MaxMsgSize 104857600
SMTPTimeout 300

# see the smtpd.conf man page
# SMTPFilter /etc/avenger/smtp-filter

MXLocalRcpt 1


DebugSMTP 1
DebugSMTPc 1
DebugAvenger 1

NoCheck postmaster
NoCheck abuse
Obviously, you need to set the BindAddr variable. See also the asmtpd.conf(5) man page.

Make sure you fill the /etc/domains file with domains that you want Mail Avenger to accept mail for, or make sure MXLocalRcpt is set to 1 (and the BindAddr is the same IP as the MX for the domain(s) you want Mail Avenger to receive mail for). Here is an example /etc/avenger/domains file:

# /etc/avenger/domains
Here is my /etc/avenger/default file (which happens to be also my /etc/avenger/unknown through a symbolic link: I am relying on exim to discard email to non-existent addresses).
# /etc/avenger/default and /etc/avenger/unknown
case "$SPF0" in
        defer "Temporary error in SPF record processing"
        accept "SPF sender PASS"


bodytest /etc/avenger/clam

See also the avenger(1) manual page.

This default file discards email that Mail Avenger has flagged as coming from a non-existent sender (errcheck). Then it immediately accepts email that comes from a SPF-verified sender (accept "SPF sender PASS"). Otherwise it greylists the sender's IP address (in fact, the /24) by telling it to send the email again in 10 minutes (greylist "${CLIENT_IP%.*} $RECIPIENT $SENDER"). Then (when the email comes a few minutes later), it gets scanned on viruses (bodytest) and, finally, provided it is clean, gets accepted and handed to exim (which is responsible for delivering it to the user).

Here is the /etc/avenger/clam file (which should probably be executable).


# this is /etc/avenger/clam

out="`/usr/bin/clamdscan --no-summary - 2>&1`"
if test "$?" = 1; then
    echo This message appears to be infected with a virus
    printf "%s\n" "$out" \
        | sed -e '/Warning:/d' -e 's/^[^:]*: //' | sort -u
    exit 100
exit 0
Notice that this relies on the clamav-daemon package being installed.

Make sure asmtpd starts on reboot by adding a @reboot root crontab entry or by adding it to rc.local! I opted for the former.

sudo crontab -e
Add a @reboot entry:
@reboot         /usr/local/sbin/asmtpd
Fire up Mail Avenger.
sudo /usr/local/sbin/asmtpd
You can follow Mail Avenger's output by tailing /var/log/ It's probably a good idea to do that for a while.
sudo tail -f /var/log/

Train bogofilter

Plenty has been written about bogofilter already.

My ~/ file.

spamicity_tags = Yes, No, Unsure
header_format = %h: %c, spamicity=%p
ham_cutoff = 0.10
spam_cutoff= 0.90
I train bogofilter on my email as follows (this assumes you created a file, ~/ham with non-spam, and a file, ~/spam with spam). Make sure the files contain roughly the same number of messages.
perl /usr/share/doc/bogofilter-common/examples/contrib/ -fnv \
    ~/.bogofilter ~/ham ~/spam '-o 0.99,0.01'
One thing I always get confused about is the following.

To tell bogofilter that a piece of mail is spam, where it wasn't sure yet:

/usr/bin/bogofilter -s
To tell bogofilter that a piece of mail is ham, where it wasn't sure yet:
/usr/bin/bogofilter -n
To tell bogofilter that a piece of mail is spam, where it wrongly classified and registered it as ham:
/usr/bin/bogofilter -N -s
To tell bogofilter that a piece of mail is ham, where it wrongly classified and registered it as spam:
/usr/bin/bogofilter -n -S

Configure SpamAssassin

Plenty has been written about SpamAssassin already.

My ~/.spamassassin/user_prefs file, generated using the SpamAssassin Configuration Generator. (This file assumes you're OK with Dutch, English, German, and Hebrew mail!)

required_score    5.0
report_safe       0
use_bayes         0
bayes_auto_learn  1
skip_rbl_checks   0
use_razor2        1
use_dcc           1
use_pyzor         1

# OK with Dutch, English, German, and Hebrew
ok_languages             nl en de he

ok_locales               en 
add_header all Status  _YESNO_, _HITS_, _TESTS(,)_
Notice that, first of all, I disabled bayes learning because bogofilter does that already. One might argue that I should also disable RBL checks since Mail Avenger is doing it already. Secondly, this config relies on several Debian / Ubuntu packages being installed: razor, pyzor, and dcc-client.

I had to add the following lines to /etc/spamassassin/v320.pre.

loadplugin Mail::SpamAssassin::Plugin::TextCat
loadplugin Mail::SpamAssassin::Plugin::DCC
Now verify your configuration.
spamassassin --lint

Configure procmail

Plenty has been written about procmail already.

Here are the relevant parts from my ~/.procmailrc file. This procmailrc assumes you're using Maildir and it assumes you have a spam/ folder and an unsure/ folder.


# Uncomment for debugging; set to no if you want minimal logging


# ...

# score it with bogofilter
| /usr/bin/bogofilter -e -p -u -c ~/

# bogofilter says it's spam
* ^X-Bogosity: Yes

# bogofilter says it's not spam.  see what SpamAssassin thinks.

# If bogofilter isn't sure, but SpamAssassin is really sure, train
# bogofilter and mark it as spam.
* ^X-Spam-Status: Yes
* ^X-Bogosity: Unsure
    | /usr/bin/bogofilter -e -s -c ~/


# bogofilter isn't sure, and SpamAssassin didn't say an outright yes
* ^X-Bogosity: Unsure

# ...
It's a good idea to keep an eye on ~/.procmail/log while you're debugging this.


Many thanks to David Mazières for writing Mail Avenger and for helping me understand it.
Copyright © 1994-2011 by Thomer M. Gil
Updated: 2007/06/20