About Code Collections Diversions Musings Personal Photos Search
Printer Friendly Version of This Page An Anti-Virus/Anti-Spam Email Setup Using Sendmail and MailScanner.

Note: This article originally ran on in June of 2002.

As any systems administrator probably knows, viruses and worms are the bane of innocent network users. Most users simply cannot be counted upon to install weekly virus scanning engine and data file updates, leaving them exposed to the rogue code running amok on the Internet. Wouldn't it be great to have the ability to stop email-borne virus traffic, arguably the most ubiquitous kind, at the server level where you control the action? If this idea appeals to you, read on.

One of the great advantages we Unix users have over the Windows populace is the lack of viruses written for our platform. While some may argue that this will change over time, the least we can do right now for our Windows compatriots is to help stop the flow of email-borne viruses before it hits the desktop. The beauty of the virus-scanning email server is the ability to auto-update your signatures and scanning engine, essentially providing a blanket of protection for your slow-to-update end users. Note that you still need to stress individual scanner updates to compensate for other methods of infection such as IM, web browsing and shared files.

Enter the MailScanner package, written and maintained by Julian K Field of the UK's University of Southampton. In addition to virus scanning, MailScanner offers integration with SpamAssassin for heuristic SPAM detection and filtering. MailScanner is queue-based and will scan both inbound messages (for local delivery) and outbound messages sent by your internal users. Messages awaiting scanning sit in one queue and messages scanned and ready to be delivered wait in another. MailScanner provides the mechanism for moving messages from one queue to another.

Let me stop and explain why I think this is an excellent choice in architecture. Other virus scanners integrate with the mailer to scan messages as they are received. While this allows for less latency in delivery times, the administrators have no flow control. Should a flood of inbound messages roll in, your server will try valiantly to scan each and every one, driving up the system load until messages are ultimately rejected. Other scanners pass the message from your MTA to the scanner, but "lose" the message if the scanner process dies or is otherwise "hung". The queue architecture nearly guarantees zero message loss, leaving a worst-case scenario of message delay. Scanning messages in batches, instead of as they come in, also allows you to more efficiently manage your system resources.

Installing MailScanner is a relatively painless process. You need a working MTA, sendmail preferred, exim supported, otherwise you are on your own. You will also need an external virus scanner like Command, F-Secure, F-Protect, Inoculate, Kaspersky, McAfee or Sophos. In my installations, and the example below, I use Sendmail 8.12.3/SMMSP as the MTA and McAfee as the system virus scanning utility.

Installing your virus scanner is a good place to start. I installed McAfee's VirusScan for UNIX into "/usr/local/uvscan" and ran a quick EICAR test to make sure it was working properly. I won't go into installation details because the process was relatively simple and straightforward, as well as not the topic of this feature ;)

If you want SpamAssassin support for tagging suspected junk email messages:

Download a recent version of SpamAssassin (2.20 at the time of this writing)
tar zxf Mail-SpamAssassin-2.20.tar.gz
cd Mail-SpamAssassin-2.20
perl Makefile.PL
make test
make install

You need the following perl modules (along with perl5) installed for MailScanner to work:
  • Sys::Syslog
  • IO::Stringy
  • MIME::Base64
  • MailTools (G/GB/GBARR/MailTools-1.15.tar.gz from CPAN works)
  • File::Spec
  • MIME::Tools
Feel free to either download and install these yourself or use the perl CPAN module: "perl -MCPAN -e shell".

Next, you need to extract the MailScanner source:

Download MailScanner (3.15-3 was the version I used)
tar zxf MailScanner-3.15-3.tar.gz
cd MailScanner-3.15-3/

You will need to choose a final resting place for the MailScanner installation and copy the "mailscanner" subdirectory into that location. The documentation uses "/opt/", I used "/usr/local/"; the choice is up to you. Just bear in mind you will need to make configuration path changes if you do not install it into "/opt/mailscanner/". Not a big deal, but consider yourself warned ;)

MailScanner includes a decoder for unpacking Outlook rich text attachments. In the "mailscanner/bin/" subdirectory you need to extract and compile tnef-1.1.1+sizelimit.tar.gz:

tar zxf tnef-1.1.1+sizelimit.tar.gz
cd tnef-1.1.1+sizelimit
make (no tests for this package)
cp ./tnef ../

Okay, now let's configure MailScanner. In the "mailscanner" directory, you will find three sub-directories:

bin/: MailScanner "executables"
etc/: Configuration files
var/: Working directories

It is extremely advisable to have the "var" directory on the same hard disk partition as your sendmail queue directories, so symlink it if you must.

Since I am using McAfee, I copied both the "autoupdate" and "mcafeewrapper" scripts from the "MailScanner-3.15-3/mcafee" source directory into "mailscanner/bin/". Only a minor path change was needed in both the wrapper and the auto-update scripts to ensure they would work on my platform.

In "etc/", the main configuration file is "mailscanner.conf". Most likely, it is a symlink to the solaris sample file or linux sample. Save yourself some time and make sure the link is correct prior to editing. There are many options in this file, but we'll only go through the ones you're likely to change. Recall that if you have changed the installation location from "/opt/mailscanner/" you will need to make a few extra file path edits.

Host nameName used in virus warnings. Good idea to customize this if you have multiple mail-scanning machines.
Incoming Work DirPath to "var/incoming" in your installation
Quarantine DirPath to "var/quarantine" in your installation
Pid FileMake sure the path to "mailscanner/var" matches what you have in your installation
Incoming Queue Dir,
Outgoing Queue Dir
Paths for the incoming and outgoing sendmail queues. Make sure the Outgoing Queue Dir in "mailscanner.conf" matches the QueueDirectory option in your ""
MTAsendmail or exim (defaults to sendmail)
Virus ScanningDo you want to scan messages? (yes/no, most likely yes ;)
Virus Scannersophos,mcafee,command,kaspersky,inoculate,f-secure or f-prot
SweepLocation of virus scanner wrapper (provided by MailScanner, for most)
Notify SendersShall we tell the sender their computer is infected?
Notify Local PostmasterDo you want to know when a virus is caught?
Local PostmasterEmail address for virus infection warnings
Local DomainsEither a file or a list of locally-handled domain names
Scanning By DomainSome sites which handle multiple domain names' email might not want to scan all of them.
Domains To ScanIf above is set to "yes", This is where you can control which domains get scanned
Spam ChecksSet to "yes" if you want to check for Spam
Use SpamAssassinIf you installed SpamAssassin earlier, "yes"
Spam White ListBelieve me, your users will help you fill this file with addresses NOT to scan ;)
Delivery Method"queue" ("batch" and "individual" are also supported)
Deliver In BackgroundAlmost a must for busy servers, "yes"
For more options, see the MailScanner documentation page.

The notices sent by MailScanner for virus detections and such are also incuded in the "etc" directory as ".txt" files. If your site wants to customize these, this is definitely the place. Since this tends to lean towards preference, we won't go into it here ;)

MailScanner will log progress information to syslog for you, using the MAIL.INFO facility. Be sure to rotate your logs frequently, as they tend to fill up quickly ;)

On to sendmail. Configuration-wise, you don't need to change anything. The secret lies in starting the sendmail processes. Two are required, one to queue incoming requests and one to process the "outbound" queue:

sendmail -bd -ODeliveryMode=queueonly -OQueueDirectory=<Incoming Queue Dir from mailscanner.conf>
sendmail -q10m

Make sure the permissions on both sendmail queue directories are the same. In my case, we have:
drwxr-x---  2 root  root  mqueue
drwxr-x---  2 root  root
You'll probably also want some helpers run out of cron:

# Every 20 minutes, make sure MailScanner is running
*/20 * * * * [ -x /path/to/mailscanner/bin/check_mailscanner ] && /path/to/mailscanner/bin/check_mailscanner 1>/dev/null 2>&1
# Process any to-be-delivered local mail more quickly than every 10 minutes
0-59/2 * * * * /usr/sbin/sendmail -qR@YOURDOMAIN
# Update the virus definitions from McAfee weekly
0 3 * * 4 /usr/local/mailscanner/bin/autoupdate 1>/dev/null 2> 1

We also use SMMSP (one of the newer security features in Sendmail), and I noticed our Majordomo messages seemed to take a bit too long to be delivered. What happened was that Majordomo would "resend" the received message which caused it to go back through the queued scanning loop. Barring some Majordomo foolery, it was highly unlikely that a virus-free message would be infected during the resend process. Looking to save some time and resources, I made the following change to sendmail's "":

O DeliveryMode=queue

This forces sendmail to leave all locally-generated messages in the client mqueue. I wrote a quickie perl script to run out of cron every 5 minutes and handle local messages. The script will :
  • Move messages from the client queue (in my case, "/var/spool/clientmqueue") into a new queue.
  • Change the permissions to 0600 and ownership of the queue files to "root:root", to keep sendmail happy.
  • Launch a queue-runner for this new queue.
The script itself is not a huge challenge to write, but I'd be happy to provide my version to anyone who asked. Think of it as an exercise in perl, left for the reader ;)

If you have a sendmail startup/shutdown script (say in "/etc/rc.d/"), be sure to update it with the new multiple-daemon configuration. You might also want to add a line to start MailScanner prior to starting sendmail ;)

And that's all there is to it. Just make sure a human receives the anti-virus postmaster messages to check for potential problems within the system, and keep an eye on your log files.

MailScanner home page:
SpamAssassin home page:

We support open web standards. This page contains both Valid XHTML 1.0 and Valid CSS .
Unless otherwise noted, all content © 2000 - 2006 Scott Sorrentino.

Version History
Created:   04 November 2003  
Updated:   07 January 2004   Added print-friendly version button
    29 March 2004   Updated Kill-HUP story link