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 pam_mysql.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:
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
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
In /etc/default/spamassassin:
# Change to one to enable spamd ENABLED=1
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 pam_mysql.so host=localhost user=YOURUSER passwd=YOURPASS db=YOURDB table=dbmail_users usercolumn=userid passwdcolumn=passwd auth required pam_mysql.so host=localhost user=YOURUSER passwd=YOURPASS db=YOURDB table=dbmail_users usercolumn=userid passwdcolumn=passwd account sufficient pam_mysql.so host=localhost user=YOURUSER passwd=YOURPASS db=YOURDB table=dbmail_users usercolumn=userid passwdcolumn=passwd account required pam_mysql.so host=localhost user=YOURUSER passwd=YOURPASS db=YOURDB table=dbmail_users usercolumn=userid passwdcolumn=passwd session sufficient pam_mysql.so host=localhost user=YOURUSER passwd=YOURPASS db=YOURDB table=dbmail_users usercolumn=userid passwdcolumn=passwd session required pam_mysql.so host=localhost user=YOURUSER passwd=YOURPASS db=YOURDB table=dbmail_users usercolumn=userid passwdcolumn=passwd
#> 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 testuser@yourdomain.com #> /etc/init.d/dbmail restart
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`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=8 ; insert into mail_transports values ('','yourdomain.com',0);
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_eximconfig_configtype='internet' #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: dc_other_hostnames="yourhostname:yourdomain.com" ## 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='0.0.0.0.25 : 127.0.0.1.10025' dc_readhost='' dc_relay_domains='' dc_minimaldns='true' dc_relay_nets='10.10.1.0/24' dc_smarthost='' CFILEMODE='644' dc_use_split_config='true' dc_hide_mailname='true' dc_mailname_in_oh='true' dc_localdelivery=transport_dbmail
ADD the following into /etc/exim4/conf.d/transport/40-exim4-config_dbmail:
transport_dbmail: driver = pipe command = "/usr/sbin/dbmail-smtp -d $local_part@$domain" return_fail_output user = dbmail
ADD the following into /etc/exim4/conf.d/router/899_exim4-config_dbmailalias:
dbmailuser: driver = accept condition = ${lookup mysql{SELECT alias_idnr FROM dbmail_aliases WHERE \ alias='${quote_mysql:$local_part@$domain}' OR \ alias='${quote_mysql:@$domain}'}{yes}{no}} transport = transport_dbmail
You'll also need to add these lines at the top of /etc/exim4/conf.d/main/01_exim4-config_listmacrosdefs:
MYSQL_SERVER=YOURDBHOST MYSQL_USER=YOURDBUSER MYSQL_PASSWORD=YOURDBPASS MYSQL_DB=YOURDBNAME hide mysql_servers = YOURDBHOST/YOURDBNAME/YOURDBUSER/YOURDBPASS
# 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
In /etc/exim4/conf.d/auth/30_exim4-config_examples comment out all the auth servers and just use these:
pam_plain: driver = plaintext public_name = PLAIN server_condition = "${if pam{$2:$3}{1}{0}}" server_set_id = $2 server_prompts = : pam_login: driver = plaintext public_name = LOGIN server_prompts = "Username:: : Password::" server_condition = "${if pam{$1:$2}{1}{0}}" server_set_id = $1 support_broken_outlook_express_4_server: 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")' AHRlc3R1c2VyAHRlc3RwYXNz #> telnet localhost 25 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. 220 localhost.localdomain ESMTP Exim 4.50 Mon, 22 Aug 2005 10:37:41 -0400 EHLO yourdomain.com 250-localhost.localdomain Hello yourdomain.com [127.0.0.1] 250-SIZE 52428800 250-PIPELINING 250-AUTH PLAIN LOGIN 250-AUTH=PLAIN LOGIN 250 HELP AUTH PLAIN AHRlc3R1c2VyAHRlc3RwYXNz 235 Authentication succeeded QUIT #>
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.
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
to
${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:
dnslookup: 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 = 0.0.0.0 : 127.0.0.0/8 : 192.168.0.0/16 :\ 172.16.0.0/12 : 10.0.0.0/8 : 169.254.0.0/16 no_more
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.