How to install/configure Exim4 MTA for SMTP AUTH (pam) + DBMail (MySQL) + SpamAssassin (spam block) + ClamAV (Antivirus)

By: GLUG: Greensboro Linux Users Group

Let me preface this with a few statements. First, this information was NOT easily available on the Internet. DBMail does NOT have a good HowTo document repository. Also, how to make PAM work with exim4 was just a happenstance… as in I was TRYING to use “saslauthd” but after many hours of no luck I gave up. I also tried using the built-in mysql support in exim4-daemon-heavy, but that didn't work either… so it was, and it seems to work very well.

I should also mention that I AM NOT an expert on Spamassassin, PAM, ClamAV, or Exim4. Through this install I have become rather familiar with exim4's split config and I rather like it. I have set up a similar machine using postfix, but after looking back through my notes this setup is much easier to duplicate.

This install is NOT for the light of heart. I STRONGLY recommend you install this on a test machine or a NON-production machine first. Get it working, make sure spamassassin/sa-exim and clamav are both working and that you still get good mail into the inbox.

I'm starting with a very minimal Debian SARGE installation.

Well, let's get started:

Install the software

apt-get install exim4-daemon-heavy
apt-get install spamassassin
apt-get install sa-exim # For Spamassassin auto-blocking
apt-get install clamav
apt-get install clamav-base clamav-daemon clamav-freshclam
apt-get install mysql-server # or install mysql-server-4.1
apt-get install libpam-mysql
  • For DBMail you need to visit the site and find the package repositories to use for the next package.
apt-get install dbmail2-mysql

Follow the on-screen prompts for each of the above installs.

Note for Debian users building dbmail from source etc. mysql_config is not installed by default. Use apt-get install libmysqlclient15-dev

Turn on the Daemons:

In /etc/default/spamassassin:

# Change to one to enable spamd

Setup PAM (we'll use this later in our auth section)

My /etc/pam.d/exim file looks like this: (I also made a copy of this in /etc/pam.d/exim4 … just in case)

auth sufficient host=localhost user=YOURUSER passwd=YOURPASS db=YOURDB table=dbmail_users usercolumn=userid passwdcolumn=passwd
auth required host=localhost user=YOURUSER passwd=YOURPASS db=YOURDB table=dbmail_users usercolumn=userid passwdcolumn=passwd
account sufficient host=localhost user=YOURUSER passwd=YOURPASS db=YOURDB table=dbmail_users usercolumn=userid passwdcolumn=passwd
account required host=localhost user=YOURUSER passwd=YOURPASS db=YOURDB table=dbmail_users usercolumn=userid passwdcolumn=passwd
session sufficient host=localhost user=YOURUSER passwd=YOURPASS db=YOURDB table=dbmail_users usercolumn=userid passwdcolumn=passwd
session required host=localhost user=YOURUSER passwd=YOURPASS db=YOURDB table=dbmail_users usercolumn=userid passwdcolumn=passwd

Get DBMail up and running

#> gunzip /usr/share/doc/dbmail2-mysql/examples/create_tables_innoDB.mysql.gz
#> mysql -u root 
mysql> create database YOURDB;
mysql> use YOURDB;
mysql> source /usr/share/doc/dbmail2-mysql/examples/create_tables_innoDB.mysql;
mysql> exit;
#> dbmail-users -a testuser -w testpass -p plaintext -s
#> /etc/init.d/dbmail restart
  • DBMail pretty much takes care of itself on the IMAP & POP3 servers … just check /etc/dbmail/dbmail.conf if it doesn't work.
  • I also added the following table for my local domains
CREATE TABLE `mail_transports` (
  `transportID` int(11) NOT NULL auto_increment,
  `transport` varchar(150) NOT NULL default '',
  `clientID` int(11) NOT NULL default '0',
  PRIMARY KEY  (`transportID`)

insert into mail_transports values ('','',0);

Exim4 Config

My /etc/exim4/update-exim4.conf.conf file:

# /etc/exim4/update-exim4.conf.conf
# Edit this file and /etc/mailname by hand and execute update-exim4.conf
# yourself or use 'dpkg-reconfigure exim4-config'


#dc_other_hostnames="mysql;SELECT DISTINCT transport FROM mail_transports where transport = '$domain'" 
## ... REGARDLESS of what you have read, the above DOES NOT WORK.  You must use the form as follows:

## If you want to use a mysql transport table then you have to go through the config files and 
## replace "+local_domains" with the following:
## ${lookup mysql{SELECT DISTINCT transport FROM mail_transports WHERE transport = '${quote_mysql:$domain}'}}

dc_local_interfaces=' :'

ADD the following into /etc/exim4/conf.d/transport/40-exim4-config_dbmail:

        driver = pipe
        command = "/usr/sbin/dbmail-smtp -d $local_part@$domain"
        user = dbmail

ADD the following into /etc/exim4/conf.d/router/899_exim4-config_dbmailalias:

  driver = accept
  condition = ${lookup mysql{SELECT alias_idnr FROM dbmail_aliases WHERE \
		alias='${quote_mysql:$local_part@$domain}' OR \
  transport = transport_dbmail

You'll also need to add these lines at the top of /etc/exim4/conf.d/main/01_exim4-config_listmacrosdefs:


"sa-exim" for Spamassassin

  • The main config file is /etc/exim4/sa-exim.conf
# SAEximRunCond: 0 # Make sure to COMMENT-OUT this line!!!

There are other options, so read that file thoroughly. It is well-documented.


In /etc/exim4/conf.d/acl/40_exim4-config_check_data add these lines RIGHT BEFORE the “accept” line (the last line):

  # Deny viruses.
  deny message = Message contains malware or a virus ($malware_name).
    log_message = $sender_host_address tried sending $malware_name
    demime = *
    malware = *

Then in /etc/exim4/conf.d/main/01_exim4-config_listmacrosdefs add this at the top:

av_scanner = clamd:/var/run/clamav/clamd.ctl


  • Finally, for SMTP AUTH you should use PAM's mysql library (libpam-mysql for … remember that pam file we created above:

In /etc/exim4/conf.d/auth/30_exim4-config_examples comment out all the auth servers and just use these:

    driver = plaintext
    public_name = PLAIN
    server_condition = "${if pam{$2:$3}{1}{0}}"
    server_set_id = $2
    server_prompts = :

    driver = plaintext
    public_name = LOGIN
    server_prompts = "Username:: : Password::"
    server_condition = "${if pam{$1:$2}{1}{0}}"
    server_set_id = $1

  driver = plaintext
  public_name = "\r\n250-AUTH=PLAIN LOGIN"
  server_prompts = User Name : Password
  server_condition = "${if pam{$2:$3}{1}{0}}"
  server_set_id = $2


#> perl -MMIME::Base64 -e 'print encode_base64("\0testuser\0testpass")'
#> telnet localhost 25
Connected to localhost.
Escape character is '^]'.
220 localhost.localdomain ESMTP Exim 4.50 Mon, 22 Aug 2005 10:37:41 -0400
250-localhost.localdomain Hello []
250-SIZE 52428800
250 HELP
235 Authentication succeeded

You're all set!


I deleted/commented out all the files in the /etc/exim4/conf.d/router/ directory so that ONLY dbmail's tables were used and NO local users were authenticated. This keeps my shell accounts and my email accounts COMPLETELY separate.

You cannot use special characters in the dbmail_users table. that means NO ”@” signs… I'd recommend using the ”#” as a replacement or possibly just a ”-” if you were planning to use the email address in that table. The reason you can't use these is because exim4 (not dbmail) can't handle them at this time. Go bug Exim4's dev staff and get them to support it if you need it. (It's actually a combination of exim4 and pam… but mostly exim4).

This article was/is current as of 8/23/2005.

MySQL Transports

Okay, I wanted my config to all be stored in the mysql database… including local_domains. So I had to make some additional changes.

First, in the /etc/exim4/update-exim4.conf.conf file I changed back the line as follows:

dc_other_hostnames = "yourhostname" # Notice NO domain names here

Next I replaced EACH AND EVERY OCCURRENCE in EACH AND EVERY one of the config files from:

local_domains # or +local_domains


${lookup mysql{SELECT DISTINCT transport FROM mail_transports WHERE transport = '${quote_mysql:$domain}'}}

So for example my /etc/exim4/conf.d/router/200_exim4-config_primary file looks like this:

  debug_print = "R: dnslookup for $local_part@$domain"
  driver = dnslookup
  # notice that the "!" sign works with the mysql lookup too
  domains =  ! ${lookup mysql{SELECT DISTINCT transport FROM mail_transports where transport = '${quote_mysql:$domain}'}}
  transport = remote_smtp
  same_domain_copy_routing = yes
  # ignore private rfc1918 and APIPA addresses
  ignore_target_hosts = : : :\
               : :

Small Edit to the great instructions above

Thanks a lot for the great instuctions. I was able to get my setup working exactly as yours but I had to change every instance of dbmail_* to the actual table name in the database without the dbmail_ prefix. I am using debian testing (2006-6-06) with mysql 5.0 and used the sql scripts that came with the dbmail package to create the tables The special user I created only has access to the dbmail database. Also the database creation scripts in the dbmail package have small bug on the default date value (scripts set it to 0) and will fail just go ahead and delete the default value and the sql script should be able to finish fine.

debian/exim4.txt · Last modified: 2011/12/08 23:12 by jacobwg
DBMail is developed by Paul J Stevens together with developers world-wide