An SMTP and POP3/IMAP4 Server with courier (pacman refers as "courier-mta" to it)
This is a "little" text which shall help you to configure the courier mail server. It doesn't cover explicitely the configuration of the popular and widely used Courier-IMAP server. Instead it focuses the big Courier-MTA mail server suite which integrates an MTA and the POP3/IMAP mail fetching methods. While there are many methods how authorization of users for MTA and POP can be integrated in one database there is no such really integrated solution which comes out of the box. There are a couple of Mail-Servers on Windows which support that. But we face Unix/Linux here, don't we. Also some admins might argue that the integration of authentification via external databases or LDAP repositories are absolutely sufficient and even desirable since the POP3 server and the MTA are hosted on seperated machines anyway. Well, what does the enthusiastic user who rents one dedicated server ore the homeuser who just wants to serve his or her home network. Mostly the enterprise solutions are copied and narrowed down to personal needs. This creates potential securety risks since it is tricky to coordinate all this different pieces of software appropriately.
Courier-MTA is not really simple, but it might be easier than the constructs mentioned above. What advantages are there in Courier-MTA:
- authentification for MTA and POP3/IMAP happens against one data source
- this datasource can be a MySQL, PgSQL or LDAP, but also can be simpler like PAM or a compiled plaintextfile (BerkelyDB)
- easy support of virtual users
- SMTP-auth out of the box
- comes with webmail
- web based administration possible
- also has a seperate mail delivery agent(MDA) if it is needed
The following text describes a setup for two local domains on one physical machine which is not so uncommon for single users or small companies. We authentificate against a BerkelyDB based .dat file which is created from a text or a bunch of textfiles automatically by some tools that come with courier. This method is described in Couriers documentation as authuserdb. So don't get confused about names. The authentification against other providers happens in an adequate way and is covered in courier-authlibs documentation. There are differences in the handling of SASL methods (such as PLAIN or CRAM-MD5) depending on which authentification backend (authuserd, authpam, authmysql ...) you like to use. Just don't expect that this setup can be painlessly converted from the described authuserdb to authmysql.
NOTE: If you like to test that on your local box but have no DNS-server running the setup fails on some edges cuz Courier-MTA needs at least an MX entry to work. To work around that you can recompile courier-mta from "abs". Add
--without-tcpddns to the configure attributes and go make some coffee, since this will take a while. Then make sure, that you add our dummy domains "domain1" and "domain2" to your
1. Let courier know that we like to authentificate against authuserdb. So edit
/etc/authlib/authdaemonrc and find "authmodulelist=...". Remove all modules but authuserdb :
authmodulelist="authuserdb" # For test it is useful, to set DEBUG_LOGIN from 0 to 2 DEBUG_LOGIN=2
2. We wanna deliver our mails primaryly to virtual users, so that we easily can create E-mail accounts without creating real users. Granny might like to read some mails but she doesn't need ssh access to that box, does she? To make that possible we need one "physical" user, that owns all of our mails physically on the drive. Note, that this is not the courier user which is primarily there to make sure that the actual server process doesn't run as root. Many people save this stuff in
/var since it's primarily thought for these things. You can create the users "home" just anywhere you want! The decision will be influenced by the partition layout of your drive(s).
# -as root # add a user "vmail", who is the lord of all of the mail files useradd -u 7200 -m -s /bin/bash vmail passwd vmail
3. There is a place, where the virtual users and their attributes will be stored. This can be either a plain textfile or a directory where several textfiles are contained. See courier-authlib's documentation for details. The directory based approach makes maintainace a bit easier since we can separate the users of domains and subdomains. So let's go with this approach. The name of the directory is not negotiable.
# as root mkdir /etc/authlib/userdb
The attributes of the "vmail"-system user need to be stored here, too, since we allowed only authuserdb in
/etc/authlib/authdaemonrc . Fortunately, courier comes with a handy script that converts all local users into a file in courier-syntax. This file can be named freely, we call it "system". Later we also create a file for "domain1" and "domain2". Got the idea?
# as root pw2userdb > /etc/authlib/userdb/system # keep only the "vmail" user, means that no local user can recieve emails! sed -n -i "/vmail/p" /etc/authlib/userdb/system
Now we create the virtual users in the authentification database. The actual Maildir folders have to be created manually later. This creates a user "user1@domain1" and a "user2@domain2". For details about these commands check the man pages for the command itself and the man pages that are linked to.
# as root userdb -f /etc/authlib/userdb/domain1 user1@domain1 \ set home<code>/home/vmail/domain1/user1 uid</code>7200 gid=7200 # let's set a password for the user (used for PLAIN and LOGIN and APOP) userdbpw -md5 || userdb -f /etc/authlib/userdb/domain1 user1@domain1 set systempw # this is used for CRAM-MD5 and friends (SASL-methods) # also note that this construct pipes the the password directly into the # command and thus can be read as cleartext, but can be handy for shell scripts # that create new users echo 'pwuser1' || userdbpw -hmac-md5 || \ userdb -f /etc/authlib/userdb/domain1 user1@domain1 set hmac-md5pw # repeat that for user2@domain2 userdb -f /etc/authlib/userdb/domain2 user2@domain2 \ set home<code>/home/vmail/domain2/user2 uid</code>7200 gid=7200 userdbpw || userdb -f /etc/authlib/userdb/domain2 user2@domain2 set systempw echo 'pwuser2' || userdbpw -hmac-md5 || \ userdb -f /etc/authlib/userdb/domain2 user2@domain2 set hmac-md5pw
4. We need to create the virtual users "Maildir" as a physical place on harddrive in "vmail"-systemuser home directory. Note that "vmail" need write rights the and also shall own the files. It's easiest to create that stuff as "vmail"
# become "vmail" su vmail mkdir -p /home/vmail/domain1/user1 && maildirmake /home/vmail/domain1/user1/Maildir mkdir -p /home/vmail/domain2/user2 && maildirmake /home/vmail/domain2/user2/Maildir exit
5. Make sure you become root again, so just leave vmails account by "exit" as written. Now it's time to create the BerkelyDB from the plain textfiles. It is important, that the files in
/etc/authlib/userdb are visible for root only. If the have any world or group rights, courier will not allow to create the db-files from the informations.
# as root chmod 700 /etc/authlib/userdb && chmod 600 /etc/authlib/userdb/* makeuserdb
Now we can check if the authentification works. Courier come with a little tool that check if users can be authentificated. But before that you have to make sure, that your authentification daemon is running.
# as root /etc/rc.d/authdaemond start authtest user1@domain1 authtest user2@domain2
6. Now we are done with authentification stuff for the first. It gave us a flexible layout which can be easily extended. Time to move on to courier's configuration itself. Firstly, we shall try to give some aliases for the server. The aliases follow the userdb's scheme very closely. Unlike in other servers, there is no need to handle with all aliases in just one file. Again, you can create several plain textfiles in one folder, where you can handle the aliases by domains or even finer structured if you like. The folders place is again not negotiable, you have to use
/etc/courier/aliases. There is already a "system" file which deals with root, postmaster and the usual suspects. Just add a "user1@domain1" behind the existing "postmaster: " to have all system relevant mails delivered to "user1@domain1". We just assume that this user is your primary account.
# as root cat > /etc/courier/aliases/domain1 << EOALIASES user1@domain1: user1@domain1 user.user1@domain1: user1@domain1 u.user1@domain1: user1@domain1 userer1@domain1: user1@domain1 looser1@domain1: user1@domain1 EOALIASES
Repeat that for every domain and user, in our testcase for user2@domain2. It might help to create another scheme here like naming your files domain1.user1 which makes administration easier and more transparent. This will also help on automated, script based administration.
Finally, these aliases must be exported to the BerkelyDB. Again, Courier comes with a little utility for that task, it's called
# as root makealiases # just check if everything is fine makealiases -chk
7. Now we need to tell courier the who is who on this box. Whom shall we serve the mails for and whom shall we not. Courier seperates this into these levels:
- locals: this is the localhost for sure and on dedicated servers you are mostly part of a domain like costumercode.serverfarm.tld
- hosteddomains: for your hosted ad the subdomains
After some conversations, an example to clerify things: lets say you have a server at "blahfarm.com". Usally they make your server a host on their domain. This is likely something like server234.blahfarm.com . Now, you wanna have your server availaible from the web by a more meaningful and even cooler name, so you buy (or rent) a domain like my-cool-domain.ca . In this case the setup looks like this:
server237.blahfarm.com and localhost* must be in
my-cool-domain.ca* must be in
any subdomain like project1.my-coold-domain.ca or smtp.my-cool-domain.ca* also must be in
/etc/courier/hosteddomains if you like to have email addresses like email@example.com
To know, what's the difference between these specifications go ahead and read the manpage for
makehosteddomains. You will figure, that the following suits our approach:
# as root echo localhost > /etc/courier/locals echo costumercode.serverfarm.tld >> locals mkdir /etc/courier/hosteddomains cat > /etc/courier/hosteddomains/domain1 << EODOMAIN1HOSTED domain1 mail.domain1(tab)domain1 EODOMAIN1HOSTED cat > /etc/courier/hosteddomains/domain2 << EODOMAIN2HOSTED domain2 mail.domain2\tdomain2 EODOMAIN2HOSTED
Again, thes values must be converted into a BerkelyDB - use the couriers command:
# as root makehosteddomains
8. Now the server is read to rock. Let's run several tests on the SMTP server and see if it's working nicely at least for sending and receiving mails. Note: The perftest1 script is currently NOT in our distribution, I will added with the next release, promised. For now you can get it from the soure tarball, or check out if you find a webcvs acces if you don't like to download 5MB
############################################################################### # this is a testcase suggested on couriers very own webpage, we just convert it # from a local to a virtual user # prepare as vmail su vmail cd ~/domain1/user1 maildirmake bounces && maildirmake test echo "./test" > .courier-test-default echo "./bounces" > .courier # back to root, start the server and finally run the script exit /usr/sbin/courier start /usr/lib/courier/courier/perftest1 1000 "user1@domain1 user2@domain2" ###############################################################################
Let's test some more stuff, which can be useful.
# send an oridinary mail (as root or oridinary user) echo "To: user2@domain2" || /usr/sbin/sendmail # send a mail to an alias echo "To: userer2@domain2" || /usr/sbin/sendmail # send a mail to an external email address echo "To: firstname.lastname@example.org" || /usr/sbin/sendmail
9. So far, our operations have been focused on the box which runs the server itself. Now we need to setup some interaction related configuration. Since security is important we will setup some nice authentification modes, which doesn't send cleartext passwords. Courier supports CRAM-MD5 among others. You will have to make sure that your clients suppport that too. So far I tested sylpheed-claws > 1.0.4, esmtp and thunderbird with these settings.
Now it comes in, that we will have to configure the several server daemons. Courier is already running (from the perftest above) but it doesn't provide services to the network. So we have to configure esmtpd, pop3d and imapd with their respective configuration files in
Since we like to use SMTPAuth instead if a IP/Domain based SMTP authentification we need to activate the AUTHREQUIRED option in esmtpd. Also we activate the CRAM-MD5 challenge method for authorization. NOTE: this setup definately keeps Outlook loosers out. For these buggy and old fashioned clients you will need to use way less restrictive settings!
# this in /etc/courier/esmtp AUTH_REQUIRED=1 ESMTPAUTH="CRAM-MD5" # Add a similar setting to pop3d (note, this happens in file pop3d) POP3AUTH="CRAM-MD5"
The imapd setting is a bit different. There is a long line starting with IMAP_CAPABILITY. Just add a "AUTH=CRAM-MD5" at the end of the arguments and you should be done.
Remarks: Because of aur very small testcase with just 2 boxes and no domaincontrol we have to take a look at couriers intrinsics and work around a little issue Courier is nitpicking about RFC compliance, which does mean you have to make sure that you understand how to configure your E-mail clients for testing. This will fail in our testing:
+------------+ +---------------+ +-------------------+ |- |local laptop|| -------> ||local box(with || ------------> || MTA somwhere on || +------------+ || courier-mta) || || web || +---------------+ +-------------------+
Why? Because you send from a non valid domain name. I assume here, that we use our "domain1" and "domain2" testpark. Now, when you create an account in Sylpheed which looks like this: Name: user numberone Address: user1@domain1 Sylpheed consequently sends the mail as "user numberone <user1@domain1>". This is wrong, since it violates the RFC. You get a Error: 517 - Syntx Error. For the testing you can simply fool Courier-MTA by setting the domainin sylpheeds dialog to: Address: email@example.com
Something similar (you just get Error 513 -Syntax Error) happens on this case:
+--------------------------+ +------------------------+ |- |local laptop || -------> ||local MTA (courier-mta) || |- | sylpheed account || || MTA delivers to || |- | firstname.lastname@example.org sends || || user2@domain2 || |- | to user2@domain2 || +------------------------+ +--------------------------+
because domain2 is not valid. You can send to mail.domain2 which will work around that. For boxes at the internet and properly configured domains this is absolute no problem, since you are alway part of a domain and thus have one dot (.) behind the @