ACPI administration advocacy advocacy advocacy opinion alsa amarok apache apple apt aptitude audio audo authentication automount avi awk bash BIOS boot business cache calendar calibre cdr cdrecord censorship commandline computerscience console convert cron cut database date debian degree design desktop development disk dpkg dvd economics education emacs email europe exim faad ffmpeg file files firefox firewall flash foss freedom ftp fun fuse git gnumeric graphics grep growisofs grub gtkpod hardware hardware html idiocy image imagemagick images installation ip iphone ipod iptables iso itunes ivman kde kernel keyboard knoppix lame laptop latex linux locale lockin longlines m4a microsoft mimetypes minitab mount mp3 mp4 mplayer multimedia music mysql network nfs nfs4 nmap openbox openoffice opinion opinion partition pdf perl php politics postgresql printing privacy programming rant remote rhythmbox rss rsync rxvt scp screengrab screenshot script scripting scsi security sed server shell siteadmin sitenews sitesoftware skype skype slackware sound sox spam spreadsheet ssh statistics subversion sudo svk swap t23 t43 terminal text thinkpad thunderbird time timezone ubuntu udev upgrade usb usbmount users uuid versioncontrol vfat video vnc windows wine wordpress wordprocessing X40 xwindows xwindows youtube
Spam is such a problem on the internet, that almost everyone needs a way to deal with it. One common question is how to filter it while it is being handled at smtp time by the mail transport agent.
Exim uses what are called 'transports' to handle messages in its spool. Transports can be defined in any order you like and are called at the appropriate time.
To actually handle messages exim3 (exim4 works slightly differently) uses 'directors' and 'routers'. 'Routers' deal with delivery to other computers, 'directors' to the computer on which exim is running, the localhost. So, it's directors that we're interested in here.
When exim is handling an email that is intended to be delivered locally it will pass it to each director in the order they appear in the exim.conf file. Directors do various things. One director, for example, will alias addresses so that an email addressed to 'webmaster' will end up in the mailbox of a real person.
Directors call on a 'transport' to deal with the message. So to integrate spamassassin with exim we need to to define a transport and a director.
One excellent example of how to get exim and spamassassin can work together is provided by Derrick Hudson here: (http://dman.ddts.net/~dman/config_docs/)
We're going to to look at it the opposite way around then he does, because it makes it understanding what exim does easier. However, they must go into your exim configuration file, exim.conf, in the right order.
Because the order directors go in is important, this one should probably be put in after the director that handles email aliases, that way personal spam preferences can be used.
"spamcheck_director" is the name of the director.
"no_verify" means that this will be skipped if addresses are verified.
The "condition" line says that the director will be skipped if there is a header called X-Spam-Flag, which means it has already been scanned by spamassassin, if there the received header contains with 'spam-scanned', which means it has already been put through the spamcheck transport (see below), or if the email originates locally, as we don't send spam to ourselves.
"Driver = smartuser" means that all mail addressed locally is handled by the director even if they are not an actual user. I have changed this to "Driver = localuser", because mail that is not addressed to an account or exists in the aliases file is bounced and I don't want to waste CPU cycles spam checking it.
"Transport = spamcheck" sets the transport that will be used
Further up in the exim.conf you define the transport which actually calls spamassassin.
"spamcheck:" is the name of the transport.
The lines are as follows:
"driver = pipe" this sets the transport to behave as a pipe, that is email goes in and gets processed by some command.
command = /usr/sbin/exim -oMr spam-scanned -bS
Here spamassassin spawns a sub-process. This might seem heavyweight, but it is the only way to do it in exim 3.
transport_filter = /usr/bin/spamc -s60000 -u${local_part}
This tells exim to filter the message by piping it to spamassassin. In the above example, a machine with not enough RAM is used, hence the -s switch is used so that message greater than 60k are not scanned. The -u switch means that a certain user's preferences will be used. Because we're using the exim variable 'local_part' it is important that this transport gets placed after any transports that deal the properly resolving the local users to whom mail is to be delivered.
bsmtp = all
This instructs exim to use batch processing. This prepares the message to be sent to a non-exim process, i.e. spamassassin.
home_directory = "/tmp"
current_directory = "/tmp"
These set the home and current directory for exim when using this director.
user = mail
group = mail
Setting the user and group for the exim sub-process.
return_path_add = false
We don't need a return path since we're processing this ourselves
log_output = true
This ensures it it is logged properly in whatever file you've set up as the log.
return_fail_output = true
If this pipe ends in an error - the output is returned in the delivery
prefix =
suffix =
This is necessary because we're using batch smtp (see above) and need to ensure there are no prefixes or suffixes to the messages.
Because spam checking can be expensive in terms of processor time one problem that I found and others have reported is that the pipe transport times out. The default is set to 5 minutes. So far I've increased this to 20 minutes by setting the option:
smtp_receive_timeout = 20m
There have been no bounces since.
In summary, in the transport section of your exim.conf put:
spamcheck:
driver = pipe
command = /usr/sbin/exim -oMr spam-scanned -bS
transport_filter = /usr/bin/spamc -s60000 -u${local_part}
bsmtp = all
home_directory = "/tmp"
current_directory = "/tmp"
user = mail
group = mail
return_path_add = false
log_output = true
return_fail_output = true
prefix =
suffix =
In the directors section put:
spamcheck_director:
no_verify
condition = "${if and { {!def:h_X-Spam-Flag:} {!eq {$received_protocol}{spam-scanned}} {!eq {$received_protocol}{local}} }{1}{0}}"
driver = localuser
transport = spamcheck