Random Sequence

Setting up a Debian server as a POP3 mail host for a collection of domains with MySQL, Exim & Courier.

Sponsored Links:

SMTP & POP3 Email for Virtual Users on Debian Sarge


I’m setting up a Debian server as a POP3 mail host for a collection of miscellaneous domains. I want to administer the domains & user accounts through a PHP front end, so it’s easiest for me if the configuration is stored in MySQL. After a brief period of reseach, I’m using Exim 4, Courier POP3 + SSL and SpamAssassin.

Below are my notes so far.

Current status:

The server will receive messages on port 25 (or 587) for users in the MySQL database and file them into the correct mailbox. Messages can be downloaded using POP3 using the same database for authentication using plain text authentication (port 110) or SSL (993). Messages can be sent using the server as an SMTP relay providing they authenticate first. TLS is available for sending.


  1. Quotas
  2. Optional mail forwarding
  3. Write front end for user administration


Required packages:

sudo apt-get install mysql-server mysql-client libmysqlclient12-dev
sudo apt-get install exim4-daemon-heavy
sudo apt-get install courier-pop-ssl
sudo apt-get install courier-authmysql

If you want to use PHPMyAdmin:

sudo apt-get install apache2
sudo apt-get install apache2-ssl
sudo apt-get install php4
sudo apt-get install phpmyadmin

Create the mail directory

sudo mkdir -m 600 /usr/local/vdomains
sudo chown mail:mail /usr/local/vdomains

Create an example domain

sudo mkdir -m 600 /usr/local/vdomains/example.com
sudo mkdir -m 600 /usr/local/vdomains/example.com/users
sudo chown mail:mail /usr/local/vdomains/example.com


Create a new database called mail, and a user mail with all privileges on that database.


CREATE TABLE domains (
  userid char(128) NOT NULL default ”,
  KEY userid (userid)

CREATE TABLE users ( id char(128) NOT NULL default ”, crypt char(128) NOT NULL default ”, clear char(128) NOT NULL default ”, name char(128) NOT NULL default ”, uid int(10) unsigned default ‘8’, gid int(10) unsigned default ‘8’, home char(255) NOT NULL default ”, maildir char(255) NOT NULL default ”, quota char(255) NOT NULL default ”, KEY id (id) ) ENGINE=MyISAM;

Note - I later changed the schema when developing a PHP front end for administration. I found that the id field could be named anything you like, as long as it’s not exactly username. That is: Courier Authdaemon will not authenticate if the id field is named username. These are fine: userName, name, email.

Example User:

INSERT INTO users (id, crypt, clear, name, uid, gid, home, maildir, quota) VALUES (‘johnnie@example.com’, ENCRYPT(‘johnniepass’), ‘johnniepass’, ‘johnnie’, 8, 8, ‘/usr/local/vdomains/example.com/users/johnnie’, ‘/usr/local/vdomains/example.com/users/johnnie/Maildir/’, ”);

Note The Maildir field has a trailing slash. Without this exim uses file_transport instead of directory_transport, and you’ll get error messages in the format:

2007-04-04 11:17:43 /usr/local/vdomains/example.com/users/johnnie/Maildir johnnie@example.com R=virtual_user defer (-30): file_transport unset in virtual_user router

Make a directory for the user’s data

sudo maildirmake /usr/local/vdomains/example.com/users/johnnie

Configuring Courier

File: /etc/courier/authdaemonrc
Set: authmodulelist="authmysql"

File: /etc/courier/authmysqlrc

MYSQL_SERVER        localhost
MYSQL_SOCKET        /var/run/mysqld/mysqld.sock

Configuring Exim

Define MySQL server

Edit file: /etc/exim4/conf.d/main/01_exim4-config_listmacrosdefs

Tell Exim which domains it’s handling mail for

domainlist local_domains = MAIN_LOCAL_DOMAINS

domainlist local_domains = localhost:january.randomsequence.com:mysql;SELECT userid FROM domains WHERE userid='$domain';

New File: /etc/exim4/conf.d/router/999_exim4-config_mysql_user

    driver = redirect
    data = ${lookup mysql{ SELECT maildir FROM users WHERE id='${local_part}@${domain}' }}
    directory_transport = address_directory

virtual_catchall_user: driver = redirect allow_fail allow_defer data = ${lookup mysql{ SELECT maildir FROM users WHERE id='*@${domain}' }} directory_transport = address_directory

Edit File: /etc/exim4/conf.d/transport/35_exim4-config_address_directory

This transport is used for handling file addresses generated by alias

or .forward files if the path ends in "/", which causes it to be treated

as a directory name rather than a file name.

address_directory: debug_print = "T: address_directory for $local_part@$domain" driver = appendfile envelope_to_add = true return_path_add = true check_string = "" escape_string = "" maildir_format = true mode = 0600 user = mail group = mail

Allow remote connections to Exim

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


This is a Debian specific file

dc_eximconfig_configtype='internet' dc_other_hostnames='' dc_local_interfaces='[SERVER IP ADDRESS]' dc_readhost='' dc_relay_domains='' dc_minimaldns='false' dc_relay_nets='' CFILEMODE='644' dc_use_split_config='true' dc_hide_mailname='false' dc_mailname_in_oh='true'

Removing Lookup Delays

Edit file: /etc/exim4/conf.d/main/02_exim4-config_options
Set: rfc1413_query_timeout = 0s

Allow Exim to use Courier Authdaemon

Add Exim to the daemon group:

sudo usermod -G daemon Debian-exim

Edit file: /etc/exim4/conf.d/auth/30_exim4-config_examples

Un-comment plain_courier_authdaemon: & login_courier_authdaemon:, comment out cram_md5:, plain: & login: sections.

Enable Exim TLS

Generate a self-signed certificate for Exim using the tool:

New file: /etc/exim4/conf.d/main/000_localmacros

switch on tls


Listen on Standard TLS Port

daemon_smtp_ports = smtp : 587

enable login without TLS / SSL



To install the latest spamassassin with sa-update, it was necessary to use the unstable Debian branch. This my come back to haunt me.

Add Unstable Source

Edit file: /etc/apt/sources.list

deb http://ftp.us.debian.org/debian unstable main non-free contrib

Make sure we use stable packages by default for everything else:
Edit file: /etc/apt/apt.conf

APT::Default-Release "stable";

Install spamassain & required packages for sa-update

sudo apt-get install -t unstable spamassassin
sudo apt-get install libnet-dns-perl gnupg 

This involves upgrading a bunch of other libraries to unstable, and therefore probably isn’t a good idea.

Start spamd each reboot

Edit file: /etc/default/spamassassin

Change to one to enable spamd


Enable SpamAssassin in Exim

Edit file: /etc/exim4/sa-exim.conf

Remove or comment out the following line to enable sa-exim

SAEximRunCond: 0

Cron Job for sa-update

New file: /etc/cron.daily/sa-update


Update SpamAssassin Rules

/usr/bin/sa-update -D channel,dns /etc/init.d/spamassassin restart

Run the update now:

sudo /usr/bin/sa-update -D channel,dns

Training SpamAssassin

sudo sa-learn --showdots --spam folder_of_spam/*
sudo sa-learn --showdots --ham folder_of_ham/*

Starting SpamAssassin

sudo /etc/init.d/spamassassin start

Dubugging Exim problems

Enable extended logging (to file /var/log/exim4/mainlog):
File: /etc/exim4/conf.d/main/02_exim4-config_options
Set: log_selector = +all

Show log for a particular message:

sudo /usr/sbin/exim4 -Mvl [Message ID]

Force Exim to process the mail queue:

sudo /usr/sbin/exim4 -qf

Helpful Links


Sponsored Links: