HOWTO: Virtual Domains with the Courier Mail Suite

Document version: 0.9; created 2004-02-04; last modified 2014-01-17.

Base setup
Adding one domain
Adding one user
Optional: Testing
Optional: Maildrop filtering
Optional: Adding courier-authdaemon support to the SpamAssassin daemon


If you read this document, I suspect you already know what "Virtual Hosts" are when it comes to email. Basically, the MTA (Mail Transport Agent) has to be configured to accept mail for that "additional" domain, it has to be configured to deliver it to "virtual accounts" and the mail service daemons (the POP3 and IMAP daemons) have to be configured to look in the right places for mail.

This document describes how to set up Courier to serve as a virtual mail host. It is more a "How I Did It" instead of a "How To", but I think it should suffice...
I wrote this document while setting up a server, so you should be able to follow the instructions in this document in the specified order. I just recommend reading the whole document and doing some thinking before typing ;-)

I use Debian GNU/Linux woody on my servers, so the paths here may be Debian-specific. E.g. you may find the file /etc/courier/esmtpacceptmailfor referenced in this document as /etc/esmtpacceptmailfor or /usr/lib/courier/etc/esmtpacceptmailfor on your system.

This document may be old (originally written in 2004), but I received an email in 2014 telling me that it's still helpful. ;-)


Naturally, you should have an MX record pointed to your server :-)

You should also have Courier-MTA and Courier-IMAP up and running for at least one domain, even if it is only for some DynDNS-Domain (see the DynDNS section on

Make sure authuserdb is active as authentication module. This means that the authmodulelist line in /etc/courier/authdaemonrc should contain the module authuserdb.

In this document, I used the system account mail, uid 8, belonging to the group mail, gid 8, with /var/mail as the home directory.
You may (some people would say "should") use another user, maybe vmail, uid 42, belonging to the group vmail, gid 42, with the home directory /var/vmail (these are just examples). If you use another user, you'll naturally have to substitute some paths while following the instructions.

Base setup

You may find this script useful:

The userdb authentification mechanism is only one of many methods. You could also use LDAP or MySQL, but that's beyond the scope of this document.

So, become root and begin creating the userdb source directory. Every file in this directory will be parsed for userdb entries by makeuserdb later.
/etc/courier/userdb may also be a single file, but using a directory is way more flexible, especially when you write scripts doing the dirty work.

andaka:~# cd /etc/courier
andaka:/etc/courier# mkdir userdb
andaka:/etc/courier# chmod 700 userdb

We need one system account to deliver mail to. I chose mail, since it already existed, had the home directory /var/mail and seemed not only made for such purposes, but also pretty useless on my system :-)
Maybe you need to create a new system user like suggested above before proceeding.

andaka:/var# pw2userdb |grep mail
mail    uid=8|gid=8|home=/var/mail|shell=/bin/sh|systempw=*|gecos=mail
8=      mail
andaka:/var# pw2userdb |grep mail >/etc/courier/userdb/vmail
andaka:/var# makeuserdb

Now we have told the mail system which system user is responsible for mails on "virtual hosts". The "8" in the second line is some special entry to map the uid back to the name (I do not know how and why, I just followed instructions myself at this point...)

OK, we have the base setup ready.

If you want to have ESMTP authentication for virtual users, see the appropiate section in the courier installation documentation. If you do not want to know what you're doing, edit /etc/courier/esmtpd:


(ESMTP auth is not covered by the script mentioned above)

Adding one domain

You may find this script useful:

Now we want to add one domain. I use in this example, a DynDNS entry I set up to point to my server.

First, the domains has to be listed in /etc/courier/hosteddomains/ and one of /etc/courier/esmtpacceptmailfor (one file containing all entries) or /etc/courier/esmtpacceptmailfor.dir/ (all files in this directory are parsed for entries). I'd prefer the .dir approach; it makes the whole thing easier to script. Since all files in the directories are parsed, we could use an almost arbitrary filename -- I chose vmail.

andaka:/var# cd /etc/courier/
andaka:/etc/courier# mkdir -p esmtpacceptmailfor.dir
andaka:/etc/courier# echo "" >>esmtpacceptmailfor.dir/vmail
andaka:/etc/courier# makeacceptmailfor
andaka:/etc/courier# makesmtpaccess
andaka:/etc/courier# mkdir -p hosteddomains
andaka:/etc/courier# echo "" >>hosteddomains/vmail
andaka:/etc/courier# makehosteddomains

Next, we have to create the directory for that domain in /var/mail:

andaka:/etc/courier# su - mail
mail@andaka:~$ pwd
mail@andaka:~$ mkdir -p domains/

Let directory names be in all lowercase.

Adding one user

You may find this script useful:

Now we want to add one user. I use in this example.

We need to create the maildir for the user manually and create the user in the userdb. Use all lowercase for directory names. It makes life easier.

mail@andaka:~$ mkdir -p domains/
mail@andaka:~$ maildirmake domains/
mail@andaka:~$ logout
andaka:/etc/courier# userdb "maligree-yi-org/" set \
                               home=/var/mail/domains/ uid=8 gid=8
andaka:/etc/courier# userdbpw | userdb "maligree-yi-org/" set systempw
Reenter password:
andaka:/etc/courier# makeuserdb

Note: Let the home field in the db point to the directory right below the Maildir of the user and do not use the mail field. That way, you can use .courier, .mailfilter and even .spamassassin in that directory (if you patch spamd a little bit to be aware of the courier-authdaemon -- more on that topic below).

Thats all, folks!

Optional: Testing

At last, we could test if there would be any problem logging in besides of client problems or wrong passwords (on systems other than pre-2010-Debian, courierauthtest may be called simply authtest):

andaka:/etc/courier# courierauthtest ""
Authenticated: module authdaemon
Home directory: /var/mail/domains/
UID/GID: 8/8
(On newer authtest versions, you may wonder why there's a line telling you that the "Maildir" property is empty. Don't worry about that.)

Now there's only one thing left: Drop me a mail if you were successful. I'd like to know if my work also works for other people.

Optional: .courier and .mailfilter

Put .courier and .mailfilter into /var/mail/domains/ They will be parsed.

Optional: Adding courier-authdaemon support to the SpamAssassin daemon

In order to use SpamAssassin's bayes feature, you'll need to patch spamd a little bit. Normally, SA uses /etc/passwd to determine the homedirs; you need to get SA to ask courier-authdaemon for the homedir of virtual users. Else, the homedir of the user responsible for virtual accounts (in our case /var/mail) will be used in spamd -- sa-learn somehow gets it right as of this writing. The conclusion: sa-learn puts it's db into one place -- and spamd looks in another place for it. Here is a documentation on how to patch spamd: Courier with Virtual Domains and SpamAssassin

Copyright 2003-04 by Dave Kliczbor. Feedback in english or german welcome. Original location of this document:
Free distribution of this document is allowed.