Home | History | Documents | Software | Feedback | Disclaimer

The Arda.Homeunix.Net Mail Setup

Table of contents

  1. Introduction
  2. Preliminaries
  3. The MTA (Mail Transfer Agent)
    1. Control Files
    2. The Vmail System Account
    3. .qmail Files
    4. System Aliases
    5. The User Database
    6. Run Scripts
  4. qmail as a Null Client
    1. Control Files
    2. Run Scripts
  5. The IMAP Server
    1. Configuration Options
    2. Mail Accounts
    3. Configuration Files
    4. Starting Courier
  6. The Webmail Interface
  7. Retrieving Mail from my ISP
  8. Starting Processes with Daemontools
    1. Daemontools on Callisto
    2. Daemontools on Europa
  9. Stopping Spam
    1. Spfilter
    2. TMDA (Tagged Message Delivery Agent)
  10. Mail & DNS
  11. Software Home Sites
  12. Further Reading

Introduction

This document describes how mail moves around on the arda.homeunix.net domain. It describes what software I use and how each piece is configured to get mail from point A to point B. It is intended to help anyone who is looking for some guidance in setting up their own mail system.

Some of the features of my mail system I’ll cover in this document include:

Preliminaries

Before we get into the nitty-gritty of email delivery systems, I should go over the general environment all the software I’m about to describe operates in.

You will find an overview of the Arda Network, including a very nice diagram, here.

All mail accounts for the domain reside on Callisto and all are virtual, managed by a single system account. Mail received by and generated on Metis, Europa, Io, and Thebe is forwarded to Callisto for delivery. Ganymede, being a Windows box, doesn’t have much to do with any of this except in the capacity of making sure Windows mail clients still work after I’ve changed something.

I’ve set up my mail server with the idea of being able to host multiple virtual domains for email accounts. People familiar with using multiple virtual domains will likely know about two very good packages designed to make virtual domains easier to use; vmailmgr and vpopmail.

I use neither of these packages in my setup, having opted for my own way of managing virtual domains. Because of my particular implementation, I don’t have access to many of the useful tools available in the two packages mentioned. This isn’t a big limitation for me because I need to deal with only a small number of virtual domains. For anyone contemplating setting up a mail server that will host a large number of virtual domains (I leave the interpretation of the word 'large' to the reader), I would recommend investigating either of the two packages mentioned.

Here is a list of the various software packages that I will be discussing in this document.

Software Installed On
netqmail 1.05 Callisto
Europa
Io
Metis
Thebe
Courier IMAP 3.0.4 Callisto
Courierpassd 1.0.1 Callisto
Courierpasswd 1.0.1 Callisto
Courieruserinfo 1.0.1 Callisto
daemontools 0.76 Callisto
Europa
Io
Metis
Thebe
Fetchmail 6.2.5 Callisto
SquirrelMail 1.4.3a Io
spfilter 0.59 Callisto
TMDA 1.0.3 Callisto
ucspi-tcp 0.88 Callisto

The MTA (Mail Transfer Agent)

I use qmail as my MTA for handling mail delivery for my domain. Qmail is installed on all my machines save Ganymede. In this section, I will describe qmail as it is installed on Callisto. See the section Qmail as a Null Client for a description of qmail installed on Europa. I also use the ucspi-tcp and daemontools packages to control and enhance the functionality of qmail.

There are numerous MTAs available nowadays and you might be asking yourself why I chose qmail over the others. My needs likely could be filled by any of the more common MTAs but there were a few considerations that made qmail win out over the others.

I did a bit of research and found that qmail was a little more mature than most of the more modern MTAs. I include Courier, Cyrus, Exim, and Postfix in this category. I also found numerous patches and add-ons to extend qmail’s functionality. From this, it looked like qmail was a stable, proven MTA that would have the features that I would need and that had a substantial developer community contributing to it. As it turns out, I am happy with the choice I made. Qmail has done everything I’ve needed it to do so far and has not caused me any trouble.

I’m not actually using stock qmail on any of my machines anymore. I’ve upgraded them all to use netqmail. For those who don’t know, netqmail is stock qmail distributed with a small number of patches and a script to apply the patches. You will find a link to netqmail in the Software Home Sites section. Once netqmail is installed, you configure it in the same way as stock qmail so this document still applies to people using qmail.

In addition to the patches included with netqmail, I typically add two more patches before installing it. Here are the patches I apply.

Patch Description
starttls-2way-auth-20040725.patch Provides startTLS and authentication capability to SMTP sessions
qregex-20040725.patch Adds full regular expression matching to the badmailfrom control file and adds the badhelo and badmailto control files.

Because the process of building qmail was somewhat involved, I’ll explain it in depth.

  1. First I unpacked the netqmail package and ran the collate.sh script to apply the included patches.
  2. I then cd'ed into the resulting netqmail-1.05 directory and applied the first patch using the command; 'patch < /path/to/starttls-2way-auth-20040725.patch'. This patch applied cleanly.
  3. I then applied the qregex patch with this command; 'patch < /path/to/qregex-20040725.patch'. This patch didn’t apply cleanly because it collided with some changes made by the first one. I used the *.rej files generated by patch to find the parts that failed and applied them manually.
  4. Still in the netqmail-1.05 directory, I ran 'make setup check' to build and install netqmail.
  5. Once installed, I set to work configuring netqmail.

You can find a description of how I used to install qmail from the FreeBSD ports tree here

I applied the starttls-2way-auth patch for two reasons:

  1. I wanted to use authentication between mail clients and qmail-smtpd to restrict who could relay mail through my mail server. This method seemed more flexible and reliable than using host-based filtering.

  2. Because usernames and passwords would be passed between mail clients and my server, I wanted to protect those passwords from network sniffers.

The starttls-2way-auth patch filled both these needs. This patch requires some additional configuration of qmail over a stock installation and I’ll go into these differences where applicable.

It is also important to remember to disable CRAM type authentication in qmail-smtpd if you aren’t going to be using it. To do this, undefine CRAM_MD5 in qmail-smtpd.c after applying the above patches and before building qmail. I didn’t at first and later found that qmail would advertise CRAM-MD5 authentication even though my mail server as configured doesn’t support it. This confused some other programs I have that interact with qmail and would cause them to fail authentication.

The starttls-2way-auth patch is actually a combination of three patches I found at www.qmail.org; qmail-remote_authenticated_smtp, qmail-smtpd-auth-043, and netqmail-1.05-tls-20040419. While qmail-smtpd-auth-043 can be used to tell qmail-smtpd to require authentication before accepting mail, qmail-remote_authenticated_smtp can tell qmail-remote to use authentication when sending mail. I’m not using this later capability yet, but I thought I might, so I included it in my qmail setup.

I’m using the qregex patch just to add a little more flexibility to my ability to block mail at the level of my MTA. The latest version offers case insensitive pattern matching, logging of all matches, and a badhelo control file for checking the helo host of smtp conversations.

These patches can be found in the Arda Network Store. In addition, I’ve prepared a patch that combines the two together if you decide you want to use both.

Control Files

Here is the list of control files I use located in /var/qmail/control on Callisto.

Control File Contents
badhelo !\.
badmailfrom some\.spamming\.domain
badmailto andrewisp@arda\.homeunix\.net
bouncehost arda.homeunix.net
concurrencyincoming 40
databytes 10485760
defaultdelivery ./Maildir/
defaultdomain arda.homeunix.net
defaulthost arda.homeunix.net
dh1024.pem -----BEGIN DH PARAMETERS-----
A1UdEwQCMAAwDQYJKoZIhvcNAQEFBwOI...
-----END DH PARAMETERS-----
dh512.pem -----BEGIN DH PARAMETERS-----
ZEJ6AqG6CSrSH/ujYjbVQ5rELRNbmG3LB...
-----END DH PARAMETERS-----
doublebouncehost arda.homeunix.net
envnoathost arda.homeunix.net
helohost arda.homeunix.net
idhost arda.homeunix.net
localiphost arda.homeunix.net
me mail.arda.homeunix.net
plusdomain arda.homeunix.net
rcpthosts arda.homelinux.net
.arda.homeunix.net
arda.homeunix.net
rsa512.pem -----BEGIN RSA PRIVATE KEY-----
NUPOZCXWVXCBskmR8tvtxM+3C51f6J7T...
-----END RSA PRIVATE KEY-----
servercert.pem -----BEGIN RSA PRIVATE KEY-----
XBzWPCYm98nvOcTxXVrbPf4t330TQns...
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
cmRhIE5ldHdvcmswgZ8wDQYJKoZIhv...
-----END CERTIFICATE-----
smtpgreeting arda.homeunix.net
smtproutes :smtp-server.my.isp.dom
tlsserverciphers HIGH:MEDIUM:!EXP:!ADH:+SSLv2:@STRENGTH
virtualdomains arda.homelinux.net:arda-homelinux-net
.arda.homeunix.net:arda-homeunix-net
arda.homeunix.net:arda-homeunix-net

Some of these control files are worth explaining in some detail.

badhelo is a control file provided by the qregex patch. It’s used to filter connections according to the helo host reported by the smtp client. I use it to block mail that doesn’t report a proper fully qualified domain name as the helo host.
badmailto is another control file provided by the qregex patch. I use this control file to block mail to certain addresses at my MTA’s front door rather than during local delivery. I put all the example email addresses that appear in this document into this control file for instance.
concurrencyincoming is not a standard qmail control file. It’s use is recommended by Life with Qmail. See the Run Scripts section for more details.
defaultdelivery is another control file recommended by Life with Qmail. It is also described in the Run Scripts section.
dh1024.pem, dh512.pem, and rsa512.pem are three control files used by the starttls patch. They contain pre-computed Diffie-Hellman parameters in the first two control files and an RSA private key in the last one. Pre-computing these values speeds up starttls transactions a lot, especially ones that use Diffie-Hellman parameters. These values are changed periodically by calling update_tmprsadh from a cron job. The update_tmprsadh script is included in the starttls patch. Better yet, it includes documentation on how to use it.
servercert.pem is also part of the starttls patch. It allows connections to and from qmail-smtpd to be made using SSL. Since I’m using authentication to restrict who can send mail through my server, passwords are traveling between mail clients and my server every time someone sends mail. This way, passwords are protected against network sniffing attacks.
The smtproutes file points at my ISP’s SMTP server causing all mail leaving my domain to be routed through this server. I do this because a significant number of mail servers in the wild will refuse mail coming from a server that fails a reverse DNS lookup. Also, an increasing number of ISPs reject mail coming from dynamically assigned IPs as an anti-spam measure. Since I have a dynamic IP, passing my mail through my ISP presents the world with a nice, statically IPed, mail server to talk to.
The tlsserverciphers file is also part of the starttls patch. I’m using it to make sure SMTP clients don’t connect to my mail server using export grade algorithms (no keys less than 128 bits are allowed). If you have OpenSSL installed on your system, then 'man ciphers' will explain the contents of this file for you.
You’ll notice that I have no locals control file. That’s because I’ve set up the domains that I accept mail for as virtual domains which are listed in the virtualdomains file. Why did I set things up this way? I did it this way partly as an exercise but also because I liked the idea of keeping mail accounts out of my /etc/passwd file. A more usual configuration would have a single local domain servicing system administrators for example plus one or more virtual domains for mail users who don’t need login rights on the server. My network is pretty small, so I put everything in virtual domains. The fact that I have no local domain also forced me to set up aliases to standard mail recipients like root and mailer-daemon a little differently than what you’d normally expect. I’ll get to the details in the next section.

Whereas most of the control files are owned by root:wheel with permissions set to 644, the dh1024.pem, dh512.pem, rsa512.pem, and servercert.pem control files are owned by qmaild:qmail with permissions set to 600. This is to preserve the security of the Diffie-Hellman parameters and private keys used by qmail.

The Vmail System Account

Vmail is the system account whose sole purpose is to handle the mail accounts of all virtual domains set up on my server. The breathtakingly original name vmail was an arbitrary decision, the system account can be named anything you want. Mailboxes of all mail users are located in subdirectories in vmail’s home directory. A sample listing of vmail’s home directory looks like this:

Here you can see the .qmail files for the vmail account. For a further explanation of the .qmail files see the next section. The .tmda directory and the getvuserhome.sh and tmda.certkey.pem files are explained in the section dealing with TMDA. When using virtual domains, it is common practice to place all the mail accounts for a particular domain within a directory named after the domain. This is what I’ve done here. I have two virtual domains listed here, arda-homelinux-net and arda-homeunix-net, which correspond to the domains in qmail’s control files listed in the previous section. Here is a sample of what one of these directories looks like.

Each mail account has its own subdirectory within the domain directory. Giving each mail account its own subdirectory was convenient because it gave me somewhere to put account specific configuration files. It also helps to keep the mail accounts organized.

.qmail Files

My qmail installation makes extensive use of .qmail files to control the delivery of mail. There are two reasons for this. The first is because I’m using virtual domains to handle all mail accounts. The second is because of one of the anti-spam packages I use, TMDA.

Vmail’s home directory contains only the .qmail files directly related to the vmail system account. All .qmail files associated with virtual mail accounts reside in the subdirectory of that mail account. For example, .qmail files used by johanne@arda.homeunix.net reside in /home/vmail/arda-homeunix-net/johanne. Each mail user gets two .qmail files that follow this basic pattern:

File Name Contents
.qmail |preline /usr/bin/tmda-filter
./Maildir/
.qmail-default none - link to .qmail

These two files direct incoming mail to the proper Maildir directory for each mail account set up on my server. The second file ensures that mail will be delivered properly if users add extentions to their mail usernames. The first file also tells qmail to filter incoming mail through the tmda-filter program. Since each user gets their own .qmail files, not all users need to use TMDA to filter their mail. In such a case, the tmda-filter line in the above example wouldn’t be present.

In addition to .qmail files for each mail account, vmail also gets two .qmail files that follow the same pattern as described above. The purpose of vmail’s .qmail files is a little different, though. Vmail’s .qmail files look like this:

File Name Contents
.qmail |preline /usr/bin/tmda-filter
./arda-homeunix-net/andrew/Maildir/
.qmail-default none - link to .qmail

The first file in this case is used to forward mail to a particular Maildir directory; I have it delivering mail to my account, andrew. This .qmail file is not likely to receive any mail directly as that would mean the mail was addressed to vmail which shouldn’t happen. The second file is what makes the first file work. The second file catches all mail addressed to an account not supplied with its own .qmail files. Therefore, mail addressed to andrew@arda.homeunix.net would be caught by the .qmail file in andrew’s mail account subdirectory while mail addressed to bogususer@arda.homeunix.net would be caught by the .qmail-default file in vmail’s home directory. It would then be handled according to the rules in vmail’s .qmail file. How qmail finds the proper mail account subdirectory of legitimate mail users is explained in the User Database section of this document.

The above explanation seems to imply that I don’t, in fact, need vmail’s .qmail file at all and could make due with just the .qmail-default file. That is probably true. However, all of the mail accounts use the two .qmail files and so I set up vmail the same way for consistency’s sake.

You’ll notice that vmail uses TMDA to filter incoming mail. This is what allows me to reject mail addressed to non-existant users on my domains but still receive mail to specific system aliases that don’t have .qmail files of their own. A more thorough explanation of this can be found in the sections dealing with aliases and the user database as well as the section on TMDA.

System Aliases

In a typical qmail installation, the system aliases are configured by adding files to qmail’s alias directory. In the context of my mail server, I was interested in setting up the following system aliases:

Each alias gets a file in the alias directory telling qmail who should receive mail addressed to that alias, typically the mailbox of some overworked sysadmin. This setup does not work on my installation however.

Because I’m using virtual domains with my system aliases, the recipient of all incoming mail is rewritten to the form <domain-name>-<recipient>. For example, mail received for postmaster@arda.homeunix.net will actually be delivered by qmail to arda-homeunix-net-postmaster. This confuses the alias directory no end and means that aliases for postmaster, or even arda-homeunix-net-postmaster, don’t work. This is the reason I had for setting up the .qmail and .qmail-default files in vmail’s home directory described in the previous section.

The User Database

The qmail user database is normally used to map qmail usernames to system usernames and can also be used to set up user aliases. The database lives in the /var/qmail/users/assign file. The assign file can be converted into a cdb format database using the qmail-newu program. Again, because I’m using virtual domains controlled by one system account, my user database is set up a little differently.

I’m using the user database to do two things. One is to map my system account to my mail account. I’m doing this because I have some cron jobs that mail error reports to my system account and I want to pick up these reports in my virtual mail account. The second job the user database is doing is to tell qmail where to look for the .qmail files associated with mail user accounts. This is how qmail knows to look in /home/vmail/arda-homeunix-net/johanne for instructions on how to deliver mail to johanne’s inbox for example.

This is what my assign file looks like.

All mail users get two lines in the assign file, one starting with a '+' sign and the other starting with a '=' sign. The '+' at the beginning of the line indicates a wildcard match allowing extended addresses to be delivered correctly. Mail addressed to andrew-mailinglist would be delivered to andrew for example. The '=' sign indicates that an exact match to the mail address is required. Together, these two lines allow a mail user to receive mail using extended addresses while reducing the possibility of receiving unwanted mail; mail addressed to jonathan will not be delivered to jon for example.

The first two lines of the file don’t refer to regular mail users. The first line directs mail addressed to my system account (the account I use to log into my various machines) to my virtual mail account. The second line tells qmail where to find .qmail files for mail retrieved from my mail account on my ISP’s mail server. See the section Retrieving Mail from my ISP for more details. Notice that both these lines begin with a '='. This means that both require exact matches, no address extentions are allowed.

The last entry in the assign file is special. It is a catch-all line that directs mail not caught by a more specific entry to vmail’s home directory. Remember that this is where mail addressed to the system aliases will go and where I handle mail addressed to non-existant users with the help of TMDA. Notice that the last line of this file is a period. Don’t forget this period or the user database won’t work.

Some of you may have realized that I could have put all my system aliases into the user database and eliminated the need for TMDA to be involved in delivering mail to these addresses. For example, I could put the line:

into the assign file which would be sufficient to deliver mail for postmaster to my mail account. As is apparent from this example, however, I would need a separate entry for every virtual domain for which I wished to receive mail addressed to postmaster. With many domains, this would quickly become tedious and lead to a cluttered user database.

I used to have qmail set up so that all .qmail files resided in vmail’s home directory. Setting up the user database as described has allowed me to move most .qmail files out of vmail’s home directory and into the subdirectories of the mail accounts they pertain to. This has gone a long way to making my mail system more manageable as having all those .qmail files in one directory was making vmail’s home very crowded.

Run Scripts

Two scripts are used to start qmail, qmail-send which handles delivering mail to local accounts and for sending it to remote servers, and qmail-smtpd which handles receiving mail from other mail servers and from mail clients that can talk SMTP. We’ll look at each of my run scripts in turn.

My qmail-send run script looks like this:

It’s pretty simple. It sets up the needed PATH environment variable and sets the default delivery location for mail intended for local mail accounts. The defaultdelivery control file is not standard to qmail but its use is recommended by Life with Qmail. The default delivery location is not normally used as the .qmail files in each user’s subdirectory will be consulted by qmail to determine delivery instructions. If I forget to put a .qmail file in someone’s directory or if the file gets deleted, however, the default location acts as a safety net for mail delivery.

My qmail-smtpd run script is rather more complicated. It looks like this:

Like the qmail-send run script above, I modeled this run script after the one found in Life with Qmail. Like defaultdelivery, concurrencyincoming is not a standard qmail control file but is something added by Life with Qmail. Softlimit is part of the daemontools package while tcpserver and rblsmtpd are from the ucspi-tcp package. I’m using softlimit to cap the memory usage of qmail-smtpd. Tcpserver acts as a super-server and is intended to replace other super-servers such as inetd and xinetd.

Two things are of particular note with this run script. The -x option directs tcpserver to filter incoming SMTP connections through a database; tcp.smtp.cdb in this case. On my system, this database file is created by the second anti-spam program that I use, spfilter. The section on spfilter details how this file is created and what it does. It is rblsmptd that uses the information in tcp.smtp.cdb to actually make the decision whether or not to accept an SMTP connection.

The second thing to note is the program being invoked by qmail-smtpd, courierpasswd. This program authenticates users who try to send mail through my server to a remote domain. This is how I prevent my mail server from being used as an open relay. Courierpasswd allows me to access user account information using Courier authentication modules. Very convenient given that I use the Courier IMAP server. One consequence of this configuration is that no one can relay mail through my mail server unless they use a mail client that supports SMTP authentication.

qmail as a Null Client

In addition to providing mail services to the outside world, I also want to receive mail from other machines on my network. For the most part, these consist of automated mailings from root providing status information on the machines. In order to receive this mail in my account on Callisto, I needed to set up qmail on the other machines on my network as well. So, by null client, I mean using qmail to send mail generated locally to a designated mail server but to not accept any mail from other machines nor to deliver mail locally. As an example, I’ll describe how qmail is set up on Europa, my DNS and DHCP server. You’ll recall that Europa is running Mandrake Linux as the operating system.

On Europa, I installed netqmail after patching it with the same starttls-2way-auth patch I used on Callisto. Call me paranoid, but I always use encrypted channels for communicating between machines if I have the option. The SMTP authentication portion of the patch isn’t used because qmail’s configuration on Europa doesn’t allow it to receive mail from remote sources at all. I like having the capability there in case I ever need it in the future, though. Because Europa will not be accepting mail from other machines nor delivering mail locally, its configuration was simpler than that for Callisto.

Things I didn’t have to worry about on Europa were aliases, a user database, dot files, or virtual mail users. None of these items are necessary to run qmail as a null client. This really only left control files and a startup script to deal with.

Control Files

Here is the list of control files I use located in /var/qmail/control on Europa.

Control File Contents
defaultdelivery ./Maildir/
defaultdomain arda.homeunix.net
defaulthost arda.homeunix.net
me europa.arda.homeunix.net
plusdomain arda.homeunix.net
rcpthosts europa.arda.homeunix.net
arda.homeunix.net
servercert.pem -----BEGIN RSA PRIVATE KEY-----
gYEA3eRg97byFQM+aLI2MqNJRx8QNj...
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
PyluweDuqCmnWtmbcmqZ4VkmYgRt36...
-----END CERTIFICATE-----
smtproutes :mail.arda.homeunix.net

You’ll notice that there are fewer control files on Europa as compared to Callisto. Of particular note is the absence of a virtualdomains file. Also, the smtproutes file points to mail.arda.homeunix.net instead of my ISP’s SMTP server as it does on Callisto. Mail.arda.homeunix.net is an alias I’ve set up in my DNS server to point to Callisto. Some time ago I had occasion to change which of my machines was acting as the mail server and using an alias made the switch less complicated.

Also missing are the dh1024.pem, dh512.pem, and rsa512.pem control files. I can justify going to the trouble of maintaining these files on Callisto because of the volume of mail it handles. However, Europa’s volume is so low that it’s just not worth the effort.

As with Callisto, the servercert.pem control file is owned by qmaild:qmail with permissions set to 600. All the other control files are owned by root:root with permissions set to 644.

Run Scripts

Because Europa doesn’t accept mail from other machines, I don’t need a qmail-smtpd run script. I do have a qmail-send script on Europa. Here it is.

This script starts up the processes necessary to send mail to Callisto. It also starts up processes used to deliver mail locally. These processes aren’t necessary as no mail is delivered locally but they don’t harm anything for being there. As with Callisto, I use programs from the daemontools package to control the qmail-send run script. I’m also using the defaultdelivery control file as I do on Callisto.

The IMAP Server

I use Courier as my IMAP server. I originally used UW-IMAP but I wanted something that would support Maildir format mailboxes natively as well as a more flexible authentication mechanism than what UW-IMAP provided.

I wished to use virtual accounts for all the mail users on Callisto and Courier provides a number of ways to do this. I opted to use the userdb option since there is very good documentation on the Courier IMAP web site on how to do this. You probably already know that the IMAP server portion of Courier is available as a package separate from the full mail server package. I use the IMAP server package and this should be kept in mind while reading the following description. I will often refer to my setup as ‘Courier’ rather than ‘Courier IMAP’ simply to save keystrokes. Where I make reference to the full Courier package, I will make this clear.

Configuration Options

I built Courier from the FreeBSD ports tree. It can be found in /usr/ports/mail/courier-imap. Before going through the 'make', 'make install' procedure, I needed to modify the configuration options and the location of the userdb database specified in the top level Makefile. Here are the options I used.

USERDB?= ${PREFIX}/etc/userdb.d/userdb
CONFIGURE_ARGS= --without-authshadow \
--sysconfdir=${CONFDIR} \
--with-userdb=${USERDB} \
--datadir=${DATADIR} \
--libexecdir=${LIBEXECDIR} \
--enable-workarounds-for-imap-client-bugs \
--enable-unicode \
--disable-root-check \
--with-locking-method=fcntl \
--with-authchangepwdir=${LIBEXECDIR}/authlib

Take note of the --with-authchangepwdir option. This option is necessary if you want to make use of the password changing functionality of Courier authentication modules. This functionality is installed by default in the full Courier package but not in the IMAP package. Even with this option set, I still needed to manually copy the authdaemon.passwd program to the libexec/courier-imap/authlib directory.

Mail Accounts

Here is a sample of what my userdb file looks like:

It shows the entries for the vmail system account as well as three entries for mail accounts. Vmail is the only account that gets two entries in the userdb file. andrew and dhahn107 represent typical mail user accounts while the tmda entry is a special entry used by tmda-ofmipd for authenticating outgoing mail. See the section describing
TMDA for more information on what the tmda entry is used for.

You will notice that the entries for andrew, dhahn107, and tmda use imappw to identify the user’s password. This provides a way for Courier to restrict what a particular password can be used for. Other possible values are 'poppw' and 'systempw'. It is because I’m using imappw here that I need to include the -s switch with courierpasswd and courierpassd.

Courier includes very good documentation describing how to populate the userdb file. In my case, the reason the --with-userdb option above points to a file instead of a directory is because I’m using a small number of virtual domains. When setting up mail accounts for many virtual domains, it is often a good idea to point the --with-userdb option to a directory to provide a more manageable organization of your mail accounts. See the Courier documentation for more details.

One account, dhahn107, bears considering in more detail. Because it is so often the case that the user id of an email account matches the first part of the user’s email address (the part before the '@' sign) it is easy to forget that the two don’t have to be the same. When using multiple virtual domains, having the two always the same would impose an undesirable limitation. If the two were always the same, it would mean that I could not have the two accounts david@arda.homeunix.net and david@arda.homelinux.net on my mail server; it would be ambiguous which 'david' account I was sending mail to or from. With the user id different from the email address, I can have a 'david' account in each of my hosted virtual domains. Note that I still cannot have two 'david' accounts within the same virtual domain.

In my example, I’ve created a user id for David that consists of his initials, an acronym derived from the virtual domain he is a part of, and an arbitrary number just to ensure that the user id will be unique.

So why then do I have the user id andrew in my userdb file instead of asjahn001 you ask? Because I’m the sysadmin, and I make the rules.

It may be useful to note that the mail account user id appears nowhere else in my server setup. The only other place the user id will be used is by the user when logging into my server with his or her mail client.

Configuration Files

In my installation, the following three configuration files are located in /usr/local/etc/courier-imap.

Here is my authdaemonrc file.

This file is pretty staightforward. You will notice that the authmodulelist has two authentication modules listed, authuserdb and authpam. All my mail accounts are set up in the userdb file so I don’t really need the authpam module there. I find it useful to test authentication against system accounts from time to time, however, which is why I haven’t removed it.

Here is my imapd file.

Apart from setting IMAPDSTART to yes, the only options I changed from their default values were IMAP_MOVE_EXPUNGE_TO_TRASH and MAXPERIP. I changed the first of the two options simply as a safeguard in case I delete a message I really want. I can always go looking for it in the Trash folder. I needed to change the MAXPERIP option because of a problem I was encountering with the default value of 4 when used with Netscape. Netscape likes to spawn new connections to the IMAP server whenever you open a new mail folder. This soon exhausted the maximum of 4 connections and Netscape would refuse to read any more folders until I had disconnected from the server and reconnected. The value of 12 I’m using now was chosen completely arbitrarily. All I can say is that I’ve had no problems since changing the value. You may need to fiddle with this depending on how many folders are in your mail account. If you have a webmail system that connects to Courier and you have lots of users accessing their accounts at the same time, you may need to use a larger value.

Here is my imapd-ssl file.

The only thing I changed here was where Courier looks for my server certificate. It’s the same certificate that qmail uses to establish secure connections.

Starting Courier

Courier uses two init scripts to start itself. The only difference between the two is the port that each tells Courier to listen on. The script imapd.rc causes Courier to listen on port 143 (the imap port), while imapd-ssl.rc causes Courier to listen on port 993 (the imaps port). I didn’t need to modify either imapd.rc or imapd-ssl.rc. Installing the courier-imap port created symlinks in /usr/local/etc/rc.d that point to these two rc files. All I needed to do was rename the two symlinks to make them active.

I used to use both init scripts to start Courier so it would listen on both the imap and imaps ports. I did this because, while the mail clients I use can speak SSL, the webmail package I use cannot. I have since configured Stunnel to secure the connection between my webmail and Courier so I no longer need to have Courier listen on port 143. Now I start Courier with the imapd-ssl.rc script only. I’ve removed the symlink in /usr/local/etc/rc.d that points to imapd.rc. My Stunnel Setup Doc has more information on how I’m using Stunnel.

The Webmail Interface

I use SquirrelMail to access virtual mail accounts through the web. Why SquirrelMail you ask? Because it was the first webmail package that I was able to successfully install is the short answer. Part of this may be because it required less supporting software to get it to work than other webmail packages I investigated. I was also looking specifically for IMAP support and didn’t mind that SquirrelMail does not do POP. It turned out to be a good choice as I’m quite happy with it. SquirrelMail offers quite a bit of flexibility in the IMAP servers it supports and in the many plugins written for it which allow you to pick and choose the functionality you want.

There really isn’t much to say about my SquirrelMail setup. I installed the software on Io, told it to use Courier as the IMAP server, told it that my SMTP server requires authentication and it worked. You can’t argue with results like that. One aspect of my SquirrelMail configuration that is peculiar to my setup is that I have SquirrelMail pointing to localhost for both my IMAP and SMTP servers with the smtp port set to 8025. My configuration is set up this way because I’m using Stunnel to secure the connections between SquirrelMail and my IMAP server and TMDA. See the section Daemontools on Callisto and my Stunnel Setup Doc for more details. Setting SquirrelMail’s smtp port to 8025 (used by TMDA’s smtp proxy) has also meant that I need to set up certain TMDA files even for users who don’t use this anti-spam software on my system. See the TMDA section for more details.

Because SquirrelMail is written in php, I needed to ensure certain parameters were set properly in my php.ini file. The settings that are relevant to SquirrelMail follow.

The /var/php-sessions directory is owned by the user that my web server runs as. It’s permissions look like this.

By the way, I’m using php version 4.3.8 built as an Apache module.

As I mentioned previously, one of the nice things about SquirrelMail is the ability to extend its capabilities with the numerous plugins available for it. Here is the list of plugins I have working with my installation.

Name Version
abook_take core
calendar core
change_pass 2.7
compatibility 1.3
compose_chars 0.1
folder_sizes 1.4
message_details core
msg_flags 1.4.3
password_forget 2.0
quicksave 2.3
select_range 2.8.2
sql_squirrel_logger 1.1.0
squirrelspell core
timeout_user 1.1.1
view_as_html 3.5a
vkeyboard 0.6
weather 4.1.1

The plugins with version numbers of 'core' are included in the SquirrelMail distribution.

One of the plugins listed in the above table is change_pass. As you may have guessed, this plugin provides mail users the ability to change their account password. Given that all mail accounts on Callisto are virtual, providing a means for users to change their password seemed like a good idea to me.

The change_pass plugin uses one of two programs (poppassd or courierpassd) to change the password of users. Both use the same network protocol to talk to clients making the two programs interchangable. Which program you choose to use depends on how you want to authenticate mail users. Poppassd uses PAM to change passwords. Since I use Courier as my IMAP server, I’m using the courierpassd program which uses configured Courier authentication modules to change passwords. Its use allows SquirrelMail to access Courier’s user database even though Courier is installed on a different machine from my web server. Another reason I’m using courierpassd is because I wrote it.

The big downside of using courierpassd in this way is that the connection between server and client is insecure, plain text user IDs and passwords are flying around the network when using this program. I’ve overcome this drawback by using Stunnel to secure the connection between SquirrelMail and my mail server.

Some of you familiar with Squirrelmail may be aware that Squirrelmail provides the option to use TLS secured connections between it and the IMAP and SMTP servers it talks to. All I have to do is enable these options and I don’t need Stunnel at all. All I can say is that when I started using Squirrelmail, it didn’t offer TLS secured connections. If I were setting up my servers now, I would likely use Squirrelmail’s native TLS support. Since I’ve already gone to all the trouble to set up Stunnel, however, I won’t be changing it until I need to.

Retrieving Mail from my ISP

In addition to the mail accounts I have set up on my own mail server, I still have an email account with my ISP that I just haven’t been able to ween myself away from. Rather than have mail in two different locations, I decided it would be nice to be able to automatically download mail from this account into an account on my own mail server. Another reason to do this is because I get spammed on this account from time to time. Rather than pay my ISP to apply their anti-spam measures to my account, I’d rather download the messages to my server and use my own spam-stopping tools. This is what I’m using Fetchmail to accomplish.

Fetchmail really is a gem of a program. My simple setup doesn’t do justice to its capabilities. If anyone needs a program to take mail from one or more mail accounts and deliver it to accounts on one or more other mail servers, you should take a look at Fetchmail. You’ll be glad you did.

Since my ISP mail account doesn’t see a lot of volume, I’m running Fetchmail twice a day from a cron job to check for mail on my ISP’s mail server and download it to Callisto. Here is what the cron job in /etc/crontab looks like.

Fetchmail runs as vmail, the system account I use to control virtual mail accounts on Callisto. Fetchmail doesn’t have to run as vmail, but I didn’t see any reason why it should run as root and running it as vmail is convenient.

In my setup, Fetchmail gets most of its runtime parameters from a configuration file, /home/vmail/.fetchmailrc. Here is what the file looks like.

Since this file contains the password to my mail account on my ISP’s server, I’ve set the permissions on this file to 600; something that Fetchmail requires, in fact. It’s nice when a program does the Right Thing by default. Here is a listing of the configuration file.

This configuration file tells Fetchmail to connect to my ISP’s mail server using the POP3 protocol, log in with my user ID and password, and deliver any mail it finds there to andrewISP@arda.homeunix.net on my local mail server. The smtpaddress parameter is necessary because otherwise Fetchmail will try to deliver mail to andrewISP@localhost, something my qmail setup doesn’t like. By default, Fetchmail tries to connect to port 25 on localhost to deliver mail it has retrieved which is why I don’t need to tell Fetchmail where my mail server is.

Once Fetchmail was set up, I needed to create an entry in qmail’s user database and set up an account directory in /home/vmail/arda-homeunix-net just like I would with any other mail user account.

And that’s it. For very little effort, I am able to pull all of my mail delivered to my ISP’s mail server into my own mail server where I can manipulate it to my heart's content.

Starting Processes with Daemontools

Daemontools is a package that includes programs used to control the startup and shutdown of long-running processes. This package is intended to ensure that processes that are supposed to run all the time actually do.

Daemontools on Callisto

I’ve set up the qmail processes, courierpassd and tmda-ofmipd to be controlled by the supervise program from the daemontools package. I also use svscan as the overseer to ensure all processes controlled by supervise are started during system boot. Here’s how I did it.

I have two separate supervise directories, one for qmail processes and the second for everything else. There really is no good reason that I can see for having qmail separated like this. My only excuse is that I set up qmail first and that I was following a recipe. Feel free to put all your run scripts under a single supervise directory.

Here is what my qmail supervise directory looks like. It is located in /var/qmail/supervise.

Once you start supervise the first time, a lot more files and directories will appear under the supervise directory. I’ve listed only the ones that I had to put there myself.

Here are what the four run scripts look like.

File Contents
qmail-send/run
#!/bin/sh
	
exec /var/qmail/rc
	
qmail-send/log/run
#!/bin/sh

exec /usr/local/bin/setuidgid qmaill /usr/local/bin/multilog t /var/log/qmail
	
qmail-smtpd/run
#!/bin/sh

exec /var/qmail/smtprc
	
qmail-smtpd/log/run
#!/bin/sh

exec /usr/local/bin/setuidgid qmaill /usr/local/bin/multilog t /var/log/qmail/smtpd
	

The qmail-send/run and qmail-smtpd/run scripts simply invoke the run scripts I descibed in the qmail run script section. The run scripts located in the log directories send all qmail logs to the directories indicated; in other words, qmail logs don’t show up in syslog. The setuidgid and multilog programs are also part of the daemontools package by the way.

Before I could start using multilog, I needed to create the directories it would be sending logs to. Here they are.

The second supervise directory is located in /usr/local/etc and looks like this.

And here are the run scripts.

File Contents
courierpassd/run
#!/bin/sh

exec /usr/local/bin/tcpserver -v -R -l callisto.arda.homeunix.net \
127.0.0.1 pop3pw /usr/local/sbin/courierpassd -s imap --stderr 2>&1
	
courierpassd/log/run
#!/bin/sh

exec /usr/local/bin/multilog t /var/log/courierpassd
	
tofmipd/run
#!/bin/sh

exec su - vmail -c 'exec /usr/local/bin/tmda-ofmipd -f -p localhost:8025 \
-A "/usr/local/sbin/courierpasswd -s imap -- /usr/bin/true" \
-S /home/vmail/getvuserhome.sh' 2>&1
	

And here is courierpassd’s log directory as specified in the courierpassd/log/run script.

There is no log directory under tofmipd because logging in tmda-ofmipd is really only designed to be used for debugging problems with the program.

Courierpassd’s run script is set up much like qmail’s smtprc script. It uses tcpserver to provide the network connectivity. Three things are of note in this file. One is that I specify the loopback address for courierpassd to listen on. But this doesn’t seem to make any sense because courierpassd must accept connections from Io, my web server, to do any good. I have courierpassd listening on localhost because I use Stunnel to create a secure connection between Callisto and Io. See my Stunnel Setup Doc for more details. The second point is that pop3pw is the alias given to port 106 in my /etc/services file. I’ve also seen poppassd used for this port. Make sure what you put here matches whatever is in your /etc/services file or just put the port number you want here instead. The third point is the --stderr switch used with courierpassd. This switch causes courierpassd logs to go to the directory specified in the log/run file instead of to syslog. This way, logs from tcpserver and courierpassd will go to the same place.

Before setting up Stunnel, I used tcpserver’s -x switch to restrict which IPs could connect to courierpassd. Now I’m using a client certificate with Stunnel which, at least in theory, is a lot more powerful than IP filtering.

I originally had courierpassd running under xinetd instead of supervise and tcpserver. However, I don’t use xinetd for anything else and I was already using supervise and tcpserver with qmail so I decided to do a bit of consolidation. There is an example of how to run courierpassd with xinetd in the documentation that comes with courierpassd.

Like courierpassd, tmda-ofmipd is listening on localhost as specified by the -p switch. It’s doing this for the same reason courierpassd is. My Stunnel Setup Doc talks about tmda-ofmipd too. Port 8025 is the default port tmda-ofmipd listens on and I saw no good reason to change that.

You will notice that I’m using two exec commands in the tofmipd run script as well as the -f switch to force tmda-ofmipd to run in the foreground. This is necessary to make tmda-ofmipd run properly as a supervised process.

Once all the supervise directories and run scripts were in place, I needed a way to start everything at system boot. To do this, I use svscan from the daemontools package. I created the directory /var/service and put symlinks into it that point to the various directories under my supervise directories. If that sentence confuses you, don’t worry, it confuses me too. So in the interest of clarity, here is what the /var/service directory looks like.

The last thing to do is activate the startup script in /usr/local/etc/rc.d/ called svscan.sh.sample. This file was installed as part of the FreeBSD port of daemontools and all I needed to do to make it work was rename it to svscan.sh. The FreeBSD ports system can be really handy at times. Here is what the file looks like.

/usr/local/etc/rc.d/svscan.sh

This script directs svscan to start supervise processes for all the run scripts it finds under the /var/service directory. A number of ulimit parameters are provided but I’ve only uncommented the MAXCHILD parameter in order to prevent fork bombs. You may want to explore the other ulimit parameters further to see if any are worth using. Using the script to stop svscan not only stops svscan itself but also every process with a run script under /var/service. Because of the way svscan.sh determines the PREFIX variable, you need to specify the full path when running this script manually.

Daemontools on Europa

On Europa, I use daemontools to control qmail. The set up closely follows that of Callisto although it is simpler since I don’t have an SMTP process running on Europa.

Here is what my qmail supervise directory looks like. It is located in /var/qmail/supervise.

Here are what the two run scripts look like.

File Contents
qmail-send/run
#!/bin/sh

# Using stdout for logging
# Using control/defaultdelivery from qmail-local to deliver messages by default

exec env - PATH="/var/qmail/bin:$PATH" \
qmail-start "`cat /var/qmail/control/defaultdelivery`"
qmail-send/log/run
#!/bin/sh

exec /usr/local/bin/setuidgid qmaill /usr/local/bin/multilog t /var/log/qmail

Here is the log directory used by multilog.

I have a /service directory on Europa. It contains only one symlink to the qmail-send directory.

One difference between this setup and that of Callisto is that the qmail-send run script is not a link to a separate rc file. There is no reason why I couldn’t set up the run script in the same way as it is on Callisto and I probably should to be consistant. I just haven’t gotten around to doing it.

The reason I have a /service directory on Europa and not a /var/service directory like on Callisto is because that’s where daemontools put it. On Callisto, I installed daemontools from the FreeBSD ports tree and the port maintainer has evidently set up daemontools to install the service directory under /var. I installed daemontools from a tarball on Europa and so service went into the root directory. I haven’t had any trouble with either setup.

Stopping Spam

I use two programs in my war against spam, spfilter and TMDA. These two programs use very different approaches to stopping unwanted email and so compliment each other nicely. With spfilter and TMDA in play, I have not had to worry about exposing my email address on the web since the miniscule amount of spam that reaches my mailbox simply isn’t a problem.

Spfilter

Spfilter is used to create a list of IP addresses of known spam sources. MTA administrators then must integrate this list into their network somehow so that incoming SMTP connections from IPs on this list are rejected. Happily, spfilter makes this a fairly painless operation as it supports all the most popular MTAs (at least the ones I know of) as well as DNS zones.

I’ve integrated spfilter with my MTA, qmail, with the help of tcpserver and rblsmtpd from the ucspi-tcp package. A cron job is set to run a script every night which tells spfilter to build the blocked IP list. It then uses this list as input for tcprules which creates the cdb file used by tcpserver. The cron job belongs to root, by the way. Here is what the script looks like.

And here is the line I added to the /etc/crontab file to invoke the script.

I am currently using spfilter to build lists using two sources; TAIWAN-local, and LOCAL_BL. Spfilter supplies a number of aliases for combining blacklists from different sources or you can explicitly name each source you want to use.

Both the the sources I use are custom sources. You can define custom sources (among other things) in a local xml file and then tell spfilter to include it using the -x option. My local xml file defines one new source, LOCAL_BL, which lists additional IP addresses that I wish to block and also a source I modified from an existing one in the standard spfilter configuration file. I maintain LOCAL_BL so that I don’t have to use one or more of the large sources defined by spfilter when all I want to do is block a few extra IPs.

I created the modified TAIWAN-local source because I wanted rblsmtpd to return a permanent error (553) when matching an incoming connection. To do that, I needed to include a 'tag' parameter in TAIWAN-local so that I could put a hyphen at the beginning of the text. This hyphen is what tells rblsmtpd to return a permanent error instead of a temporary one (451). The 'tag' parameter for the LOCAL_BL source also begins with a hyphen for the same reason. Apart from the 'tag' parameter, the TAIWAN-local source is identical to the TAIWAN source found in the spfilter-config.xml file. Here is what the spfilter-local.xml file looks like.

Here is an example of what the local-blocks file looks like.

The spfilter documentation recommends that you run the program as a non-priviledged user and furthermore, warns against using the -u option but to use the su command instead. I’ve followed that advice by running spfilter as user nobody. All files and directories under the spfilter directory are owned by nobody:nogroup except for the spfilter-command script listed above. It is owned by root:wheel.

In order for qmail to use the list created by spfilter, I added the -x option to the tcpserver command in my qmail-smtpd run script. I also call rblsmtpd which is the program that makes the decision whether or not to allow the incoming SMTP connection based on the state of the RBLSMTPD environment variable. I repeat the script here so you don’t have to go looking for it in the qmail section above.

My run script shows that I use rblsmtpd to query Spamhaus’ combined SBL and XBL block list zone. I was using spfilter’s SBL and CBL sources to do that same thing locally but the CBL zone became too large for my poor little PC to process so I had to stop using it. Since I would need to do a remote query for the CBL list anyway, I decided to start using Spamhaus’ sbl-xbl.spamhaus.org zone and get the benefits of both lists in one shot.

You might be wondering why I maintain local blacklists at all if I’m already using rblsmtpd to query a remote list. Creating local blacklists using spfilter seems to be a redundant step. In my case, I might agree. I have a single, low volume, mail server on my small network so doing DNS lookups against a remote rbl server for all incoming mail doesn’t place a great burden on my setup. Spfilter would provide more benefit to high volume mail servers that might suffer significant loads due to constant DNS lookups. But I think spfilter’s a pretty neat piece of software which is reason enough for me to use it.

Spfilter provides a second output format for use with qmail called qmail_uce. To use this format, however, you need to patch qmail so that it recognizes the DENYMAIL environment variable. I never did find a suitable patch that would play nice with the starttls-2way-auth patch that I use so I elected to go the rblsmtpd route instead.

At one time, I included the RELAYS alias when constructing my block list until I found that RELAYS was blocking the mail servers of some major ISPs. Regardless as to whether these ISPs allow their mail servers to be used as open relays or not, I need to receive mail from them.

Before I stopped using the RELAYS alias, I modified the tcprules command I was using to construct my block list to remove certain IP ranges of ISPs I wanted to receive mail from. Here is what I was using.

This command removes any line from the block list that contains an IP address from the specified subnets before piping it to tcprules. I first checked that only the mail servers of the desired ISPs would be removed from the list. I’ve also changed the IP addresses shown to protect the guilty.

Even though I don’t use this tcprules command any more, I thought someone might find it useful if he or she wishes to use one of the more aggressive blacklist source aliases but remove a small number of IP address ranges from the resulting block list.

TMDA (Tagged Message Delivery Agent)

TMDA is a very cool piece of software, not only because of what it does, but also because it’s written in my favorite language of choice (Python).

TMDA allows you to set up email whitelists as well as blacklists, add arbitrary email headers, and filter mail according to its source or destination address. What action TMDA takes can also be tailored according to source or destination address. Like I said, cool stuff.

I use TMDA to control the passage of mail both into and out of my account. TMDA can be used with a number of MTAs but it integrates especially well with qmail. My TMDA setup was complicated by the fact that I insisted on setting up all mail accounts as virtual accounts without shell access on my server. After overcoming a few bumps in the road, all is running smoothly. Here is how I did it.

Apart from the system wide TMDA configuration file /etc/tmdarc, all tmda related files are located under the home directory of vmail, the system account that controls all mail accounts regardless of domain.

Each mail account that uses TMDA (i.e. /home/vmail/<domain>/<username>) has these files and directories in it:

Maildir is, obviously, where the mail goes. You’ll also notice the .qmail files which qmail is using to tell it how to deliver mail to this particular mail account. The contents of the .qmail files are explained in the relevant qmail section. All directories and files related to TMDA are in the .tmda directory. Below are listed the parameters I add to the default config file of each mail account that uses TMDA. I didn’t alter any of the lines already present in the default config file. In this example, the user Johanne Doe has the account user id of johanne and uses the email address johanne@arda.homeunix.net.

The TMDA web site has great documentation on what all these parameters do so I’ll not repeat all that here.

Not all accounts on my system need to use TMDA. Because I have my webmail package pointing to TMDA’s smtp proxy, tmda-ofmipd, even these users need a minimal TMDA setup to be able to send mail from my webmail interface.

When I say minimal, that’s exactly what I mean. This is what the .tmda directory of an account not using TMDA looks like.

The crypt_key file is created that same way as for accounts that use TMDA. The config file has a single parameter in it.

This parameter tells tmda-ofmipd to not add any tags to outgoing mail, which is what you want for an account that doesn’t use TMDA.

The only other difference compared to an account that uses TMDA is, of course, that the user’s .qmail files won’t include any mention of TMDA in them.

In addition to the virtual accounts, the vmail system account also has its own set of TMDA files and directories as well as .qmail files to control mail delivery. The two files, .qmail and .qmail-default, that vmail uses are explained in the .qmail Files section. This is what vmail’s .tmda directory looks like.

You will notice that this directory looks a lot like the /home/vmail/arda-homeunix-net/<username> directory described above except for the addition of the tofmipd file and the templates directory. The file is for storing user IDs and passwords of accounts that use tmda-ofmipd. I authenticate users with one of tmda-ofmipd’s other methods but the program complains if this file isn’t here. The templates directory allows me to use customized messages for automatic responses generated by TMDA which override the default messages.

The config file used by vmail is quite a bit different from that of a virtual mail account. Here is what it looks like.

Most of the parameters found in a mail account’s config file aren’t here because mail won’t be sent from the vmail account directly. Another difference is that vmail doesn’t have its own Maildir; it never receives mail for itself. Vmail always fowards mail to another account or bounces it in the case of mail addressed to an unkown account.

The TEMPLATE_DIR parameter is set because I’m using a custom bounce template.

The really perceptive among you might be asking yourselves, ‘If the vmail account catches all mail not destined to a virtual account listed in qmail’s user database, doesn’t it foward mail addressed to every bogus account sent it’s way?’ The answer is; it would if not for my incoming filter file found in .tmda/filters. Here it is.

I have only two virtual domains listed here but any number could be supported. Just add another 'to' line for each additional virtual domain.

We also need to look at TMDA’s global configuration file /etc/tmdarc. Here it is.

The SMTPSSL_* parameters are set here because I built qmail to use the starttls protocol and so TMDA can take advantage of a secure connection with my MTA. The certificate and private key are in a single file owned by vmail:vmail with permissions set to 400. The PURGED_HEADERS parameter removes the specified headers from a mail message before it is sent to the MTA. What the SMTPHOST parameter is doing should be self-evident.

The BOUNCE_ENV_SENDER parameter exists because there are many MTAs out there configured to reject mail with an empty 'Return-Path' header, which is what TMDA does by default when sending confirmation requests. Setting this parameter causes the Return-Path header to be filled with the specified value. It also provides a convenient way to identify bounces to messages generated by TMDA. For example, if a TMDA confirmation request bounces (which it will in the vast majority of cases when spam is involved) I don’t really want to see the bounce. That is why I drop mail that is bounced back to bitbucket in vmail’s incoming filter file detailed above.

The two SMTPAUTH_* parameters are necessary because, as explained in the MTA section, my qmail-smtpd requires authentication in order to relay mail through it. The two SMTPAUTH_* parameters are used by TMDA when sending confirmation requests and when dealing with undeliverable mail.

Note that the user 'tmda' has an entry in the userdb file described in the IMAP Server section.

Because the /etc/tmdarc file contains a plain text password enabling anyone to relay mail through my server, I’ve done my best to restrict access to the file. A listing of /etc/tmdarc looks like this.

The only reason I can get away with restricting read access to the file like this is because I’m using virtual mail accounts controlled by the single system account vmail.

The last thing to deal with is outgoing mail tagged by tmda-ofmipd. Don’t worry, the tricky parts were already covered when I explained how I’m authenticating users with Courier.

Tmda-ofmipd is an SMTP proxy. Mail clients that speak SMTP connect to tmda-ofmipd which manipulates a mail message according to the rules in a mail user’s outgoing filter file. This usually involves tagging the From: or Reply-To: headers in some way. Tmda-ofmipd then forwards the mail on to a regular SMTP server (in my case, qmail-smtpd). Tmda-ofmipd needs to authenticate users trying to send mail through it in order to work properly. How tmda-ofmipd authenticates users is given by the command I use to invoke the program. The command is invoked by the svscan program during system startup as explained in the Daemontools on Callisto section. Here is the tofmipd run script once again.

I’ve chosen to run a single persistent instance of tmda-ofmipd instead of invoking a new one each time a user wishes to send mail. There are three things to note in the above command. Tmda-ofmipd has a -u switch which tells it to run as a specified user. The -u switch does not seem to work when using virtual mail users controlled by a single system account. This is why my run script invokes su to make tmda-ofmipd run as user vmail.

The second point to note is my use of the -A option to authenticate users with a checkpassword compatible program called courierpasswd. This program requires that Courier (either the full package or just the IMAP server) be installed and that the accounts you want to authenticate against be accessible to Courier’s authentication modules. This is just what I want since I use Courier as my IMAP server and all virtual accounts are set up so Courier can authenticate against them. This is the same program that I’m invoking from my qmail-smtpd run script. Note that prior to version 0.70 of TMDA, I needed to use courierpasswd’s --stdin switch to have it work with TMDA. Version 0.70 and better no longer need this switch.

The third point is the -S option. This is how I tell TMDA where a user’s home directory is (and thus where that user’s TMDA config file is). This option is necessary because I have virtual accounts split into different directories according to domain and because a single system account controls all virtual domains. The shell script invoked, getvuserhome.sh, calls another program, courieruserinfo, that does the actual work of retrieving the user’s home directory. All getvuserhome.sh does is some formatting of the output. Courieruserinfo is another of the programs I wrote to allow me to use TMDA with my particular setup of Courier IMAP and qmail. Here is a listing of the getvuserhome.sh script.

And this is what the script looks like.

The reasons why I’m using the -f and -p switches of tmda-ofmipd are explained in the part of the Daemontools on Callisto section dealing with tmda-ofmipd.

I find this setup particularly convenient because it means that tmda-ofmipd doesn’t care where the user account information is stored so long as Courier can get at it. I also have to maintain only one mail account database.

All this talk of authentication is important because, as you’ll recall if you read the section on my MTA setup, I built qmail with the starttls-2way-auth patch and authenticating users is how I restrict who can relay mail through my server.

Before I managed to get tmda-ofmipd running using the daemontools package, I had it set up to start from a regular init script. In that scenario, I found that tmda-ofmipd would not detach from its controlling terminal properly which would result in two persistant processes instead of one; one running as vmail like it should, and the second running as root that shouldn’t have been there. To overcome this problem, I did a bit of hacking on tmda-ofmipd and added the -D option (for Daemonize). Here is the startup command that I used in my init script.

Although the patch I created for tmda-ofmipd is still available from my home page, I haven’t used it for some time. It may not be necessary with recent versions of tmda-ofmipd. Make sure you need it before using it.

And one more thing. Don’t forget to set the port of your SMTP server on you mail client to 8025 which is the port that tmda-ofmipd listens to by default.

Mail & DNS

After all of this work, you would think that my mail setup should be complete. Well, not quite. There is one more thing to consider; DNS.

In order for mail to route correctly through my network, I needed to put an MX record into my primary DNS server’s zone files. In fact, for each mail account domain hosted by Callisto (virtual or otherwise), I need a corresponding zone file containing the relevant MX record in my DNS server.

How MX records are set up on Europa and Io, my primary and backup DNS servers, is detailed in my DNS & DHCP Setup Doc.

Software Home Sites

Checkpassword http://cr.yp.to/checkpwd.html
Courier IMAP server http://www.courier-mta.org/imap/
Courierpassd
Courierpasswd
Courieruserinfo
http://www.arda.homeunix.net/
Daemontools http://cr.yp.to/daemontools.html
Fetchmail http://catb.org/~esr/fetchmail/
Netqmail http://qmail.org/netqmail/
Poppassd http://echelon.pl/pubs/poppassd.html
Qmail MTA http://cr.yp.to/qmail.html
SP Filter http://spfilter.openrbl.org/
SquirrelMail Webmail http://www.squirrelmail.org/
Tagged Message Delivery Agent (TMDA) http://tmda.net/
ucspi-tcp http://cr.yp.to/ucspi-tcp.html

Further Reading

In the unlikely event that this document doesn’t answer all your questions, here are some other documents I’ve come across that that may be of help. Remember to check out the home pages listed above as they include plenty of documentation too.

Qmail single UID Howto http://www.pgregg.com/projects/qmail/singleuid/index.php
Home of much qmail documentation, patches, and more http://www.qmail.org/
Life with Qmail document http://www.lifewithqmail.org/lwq.html
Linux Email Server in an NT Domain http://www.flatmtn.com/computer/Linux-EmailServer.html
Qmail Newbie's Guide to Relaying http://www.palomine.net/qmail/relaying.html
Qmail and Courier-IMAP on Red Hat Linux http://www.sxpress.com/~henry/qmail-pop-imap-web-howto.htm
Tutorial on how to set up a complete mail server using Qmail and Courier-IMAP with lots of bells and whistles http://www.qmailrocks.org/

Copyright © 2002-2004 Andrew St. Jean Last update Oct. 08, 2005
Apache Webserver FreeBSD