Setting up Postfix + MySQL + Courier-IMAP + Mailman + vmail + Procmail + SpamAssassin
Original document by Probsd.net, rewritten and extended by Mitsu Hadeishi
I just finished setting up Postfix + MySQL + Courier-IMAP + Mailman + vmail + Procmail + SpamAssassin.
This combination will give you email sending, receiving, and picking up via IMAP, POP3 or POP3+SSL,
true virtual domains and email accounts, mailing lists with a web interface, and a simple web interface for
creating virtual domains and email accounts.
These instructions should work with Fedora Core 1 and Red Hat 9, and I hope these instructions will also be helpful for
people with other distributions. This document is based on the vmail
setup document, but I have added much more detail as well as specific instructions for Red Hat-based distributions,
as well as explanations of the structure of the mail system and some information on Mailman, Procmail, and
SpamAssassin (more to come later).
Basic defintions. Postfix is a mail transfer agent which handles SMTP (for sending and receiving email).
Courier-IMAP is the IMAP and POP3 component (for retrieving email)
of the Courier mail system, which can be configured to work with other mail transfer agents (like Postfix).
Procmail is used to actually deliver the email, and passes the
email through SpamAssassin. SpamAssassin is a
spam email filter.
Mailman is a mailing list system with
a web interface for configuring the mailing lists (but basic
configuration must be done by hand), and vmail is a simple PHP-based web interface for setting up
virtual domains and virtual domain-based email accounts. MySQL is used to store authentication
information and virtual domain account information.
To get all this software to work together, we have to configure them to use a compatible format
for storing/delivering mail (when Postfix receives mail it needs to store it in a form that Courier-IMAP understands,
so users can retrieve their email via POP3 or IMAP, and it should send it to Procmail for the actual
delivery), authentication (Courier-IMAP needs to know how
to check user passwords when users retrieve their email), administration (vmail needs to be configured
to store user and virtual domain information in a way that Postfix and Courier-IMAP can understand), spam
filtering (Procmail needs to filter email through SpamAssassin) and
since Mailman also creates email aliases, we also need to configure Postfix and Mailman so they are using
a compatible format for these aliases (Mailman creates its own aliases, and Postfix needs to know how
to read these aliases).
For in depth information about using the postfix virtual agent
check out this howto.
We assume a base directory of /usr/local/vmail, user "vmail", database user "vmail" here, use whatever
values you want, these are only examples, but be sure to put the right settings in the php and perl scripts.
Make a user
Our user "vmail" will own all the mail directories, run vipw (or use whatever administrative tool
you like) and add it:
Note: change uid:gid to whatever free uid and
gid are available for the vmail account.
Note the uid and gid for later reference.
Add a group for vmail and a mail alias for vmail to root or some admin account, so you get an email if the
maintainence cron script spits out an error.
A few notes about Postfix. You cannot use the prebuilt rpm for Postfix that comes with Red Hat 9 or
Fedora Core 1 because it does not support mysql. Therefore you must compile Postfix from source,
making sure you use the --with-mysql option. Generic
instructions on building rpms from source rpms (SRPMS), and some instructions
on building Postfix from an srpm (however note those instructions are designed for Cyrus-SASL, not
Courier-IMAP, so make sure you use the --with-mysql option). Alternately, if you want the latest version,
download the Postfix source and build it (again with the
--with-mysql option, plus any others you might like).
IMPORTANT: For security reasons it is a good idea to configure Postfix to run chrooted,
which means that certain Postfix processes (like the SMTP server) will only be able to see files
underneath /var/spool/postfix. For instructions on configuring Postfix in a chrooted environment,
read the INSTALL document in the Postfix source directory. The problem is when you run Postfix chrooted,
it will not be able to access the /var/lib/mysql/mysql.sock file to talk to MySQL on localhost,
since that file is outside of the chroot jail. Symlinks to files outside the chroot jail will also fail. You can create a hard link to the socket, but that link will be invalidated
whenever you restart mysqld. You can do two things to get around this: either re-create the hard
link by editing the mysqld startup script and adding the link command there (/etc/rc.d/init.d/mysqld),
which seems a bit kludgy to me, or, a better solution is to specify 127.0.0.1 as the host name
to pfsqlfiles (see below), instead of localhost, which will force Postfix to use TCP to talk with
MySQL. Note that your mysqld server must be configured to accept TCP connections on the standard
port (at least from the local machine) --- this is the default so you probably don't need to do anything special here.
The pfsqlfiles script will make the mysql info files for postfix, to save some annoying typing. It will prompt for database info
(remember to use 127.0.0.1) and write the files to the current directory.
# cd /etc/postfix; mkdir sql; cd sql;
Set permissions on the files so the postfix user can read them and others can't access them.
Put the following in your main.cf:
virtual_mailbox_base = /usr/local/vmail
virtual_minimum_uid = 500 <== the minimum uid that can be returned
from a virtual_uid_maps lookup, 500 is probably fine
virtual_mailbox_maps = mysql:/etc/postfix/sql/vmailbox
# the virtual-mailman.db file must exist or Postfix will fail
# when receiving mail; be sure Mailman has generated this
# file: manually generate a dummy virtual-mailman.db file
# with the postmap command, or remove virtual-mailman.db
# from the virtual_maps list until Mailman generates the file
virtual_maps = mysql:/etc/postfix/sql/virtual,
transport_maps = mysql:/etc/postfix/sql/transport
# change to the uid of the vmail user
virtual_uid_maps = static:uid
# change to the gid of the vmail group
virtual_gid_maps = static:gid
local_recipient_maps = unix:passwd.byname $alias_maps $virtual_mailbox_maps
fallback_transport = virtual
relay_domains = $transport_maps
virtual_mailbox_base: Used to determine under which directory the virtual domain mailboxes will be stored.
virtual_maps: The first map refers to the database which will contain virtual aliases information, and the
second refers to aliases created by the Mailman mailing list manager (see below)
Also, edit alias_maps to look like this:
alias_maps = hash:/etc/postfix/aliases, hash:/usr/local/mailman/data/aliases
Again, this allows Mailman to modify the aliases for Postfix.
You also need to edit various parameters in /etc/postfix/main.cf. Some of the parameters below are needed,
others are just some possible recommendations --- please look at main.cf and edit these parameters carefully.
Note that some of these parameters are not found in main.cf, but are rather defined in main.cf.default --- do NOT
edit them in main.cf.default, rather copy them from main.cf.default to main.cf and edit them there (or simply
insert these lines into main.cf):
myhostname = full_hostname <== i.e., host.mydomain.com
mydomain = domainname <== i.e., mydomain.com
myorigin = $myhostname <== This sets the default origin
domain for email coming from this server directly. You can also
set this to $mydomain. Since I use $mydomain as a virtual
email domain, I set this to $myhostname to avoid collisions
inet_interfaces = all <== listen to all interfaces on this machine
mydestination = $myhostname, $mydomain, virtual_domain1,
virtual_domain2, ... <== list out all virtual domains on
this email server
local_recipient_maps = unix:passwd.byname $alias_maps
$virtual_mailbox_maps <= list out aliases and virtual mailboxes
unknown_local_recipient_reject_code = 550 <== set to 550 after
everything is working, set to 450 (try again later) while debugging
mynetworks_style = host <== set to host if you only trust
the local machine for accepting mail for relaying, etc.,
without doing additional checks
home_mailbox = Maildir/ <== this is necessary! so Courier-IMAP can
read the mailboxes (Courier-IMAP does not support mbox format)
mailbox_command = /usr/bin/procmail <== Procmail does the
delivery and filtering via SpamAssassin
disable_vrfy_command = yes <== disables verification that a user
is valid, for security reasons
smtpd_recipient_restrictions = permit_mynetworks,
reject_unauth_destination, reject_unknown_client <== helps to
secure your SMTP server
owner_request_special = no <== this is needed by Mailman
Note that you can find log file messages from Postfix in /var/log/maillog (Courier-IMAP places log messages here as well).
First, we create and populate the database, then create a vmail user to access the database (choose your
mysql -u root -p < vmail.sql
mysql> GRANT select, insert, update, delete
ON vmail.* TO vmail@localhost IDENTIFIED BY 'password';
mysql> GRANT select, insert, update, delete
ON vmail.* TO vmail@hostname IDENTIFIED BY 'password';
mysql> FLUSH PRIVILEGES;
NOTE: The first GRANT is for processes that are accessing the database via the localhost /var/lib/mysql/mysql.sock
socket directly (this includes the vmail PHP scripts), and the second is for processes (like Postfix inside a chroot jail) to
access the database via a TCP socket. In place of hostname, use the domain name for the server computer (that
seems to be what Postfix uses when logging in).
Debugging MySQL problems: You may wish to start mysqld with the log option turned on so you can debug
common problems with configuration. To do this, edit the /etc/rc.d/init.d/mysqld script file and add
--log=/var/log/mysql.log as the last argument to /usr/bin/safe_mysqld and restart mysqld with "service mysqld restart".
You will then be able to track problems with logins or permissions by looking at /var/log/mysql.log. Be sure
to take the log option out once you have everything working, because logging will slow down the performance
of the MySQL database.
Note that vmail requires Apache and PHP be installed already (you can use the standard Red Hat/Fedora rpms for this'
Download vmail and
copy the php scripts into their directory (we're assuming /usr/local/vmail in this document),
copy php/config.php.dist to php/config.php and edit:
$server = 'localhost';
$user = 'vmail';
$pass = 'password'; // <== database password you chose above
$db = 'vmail';
// vmail home dir (set this)
$vmailbase = '/usr/local/vmail';
// vmail uid, gid
$uid = uid; // <== set this to the uid of the vmail user
$gid = gid; // <== set this to the gid of the vmail group
// main admins email address
$admin = 'admin_email_address'; // <== send to a real person
// dir name for admin login (http://url.to/vmail/admindir/)
$admindir = 'admin';
Install the perl scripts maintain and vmadmin in the base vmail directory and make sure
the options in the top of the scripts. Make sure to set secure permissions on config.php and perl scripts containing the db password.
The maintain script handles deleting maildirs on deleted accounts, renaming maildirs, etc...
I add an /etc/crontab entry to run it as the vmail user:
*/5 * * * * vmail /usr/local/vmail/maintain
Add an admin account for the web interface:
# vmadmin +admin
Now you can browse to http://your.url.to/vmail/admin/ to login as the superuser and add a domain. Your base url will be the normal login for postmasters.
You can also use the vmadmin script to edit things on the command line, but its not quite polished yet. make sure to su to the vmail user to run it.
The web interface is pretty self explainitory, just take a look around...
Unfortunately there is no pre-configured package for Red Hat for Courier-IMAP, so you have to download and build it
from source. When you do this, you'll notice that the source package doesn't like to compile and install
directly, but rather tries to get you to build an RPM file, which you then install via rpm -ivh.
Note that the instructions on the Courier-IMAP web page
do not mention this. Basically, download Courier-IMAP,
copy to a normal (non-root) user folder, become that user, unpack the file and build Courier-IMAP as an rpm file
following the directions in the INSTALL file. Remember to configure Courier-IMAP with the following
--with-authmysql --with-mysql-libs=/usr/local/lib/mysql/ \
Notes for FreeBSD users:
The courier-imap port in freebsd is kinda messed up with regards to getting the mysql auth stuff to compile... find ".if !defined(WITH_MYSQL)"
in the Makefile and change this:
--with-authmysql --with-mysql-libs=/usr/local/lib/mysql/ \
Add --with-authpwd to CONFIGURE_ARGS if you're going to be serving regular system accounts also.
Then you can make -DWITH_MYSQL and courier will compile with authmysql correctly.
Consult the docs for courier-imap to get it set up and use these settings in your authmysqlrc
(the default location is /usr/lib/courier-imap/etc/authmysqlrc). These settings tell Courier-IMAP
which database, table, and field names to use for accessing virtual domain mailbox information:
MYSQL_PASSWORD password <== database password
MYSQL_SOCKET /var/lib/mysql/mysql.sock <== or whereever
mysql.sock is on your system, sometimes /tmp/mysql.sock
MYSQL_PORT 3306 <== you don't necessarily need to
set this since it will use mysql.sock
Authdaemond also, by default, just chooses the first authentication module it finds in the
/usr/lib/courier-imap/libexec/authlib directory. You can either move all the authdaemond.* files out of that
directory except for authdaemond.mysql, or set AUTHDAEMOND="authdaemond.mysql" in the
If you installed Postfix from an rpm compiled from an SRPM, you should be able to install the Mailman rpm
from a Red Hat or Fedora repository. Otherwise you have to download Mailman
and build it from source. Once you've installed Mailman, follow these
instructions for configuring Mailman for Postfix. Note that some of the things you need to do for Postfix I've
already included in the above instructions, but you will need to modify the Mailman part of the instructions.
Make sure Procmail is installed; the standard Red Hat procmail rpm should work fine.
You should be able to use the SpamAssassin rpm from a Red Hat repository. I have not yet tested this extensively.
This page discusses SpamAssassin/Procmail setup.
I have found this interesting SpamAssassin configuration generator
which I haven't yet tried out. I will post more here as I learn to use the configuration.