David R. Harris has cleaned up the patch that adds maildir support to the University of Washington IMAP server and documented the installation process. See http://www.davideous.com/imap-maildir/.

5.2.5. Courier-IMAP

Sam Varshavchik has written an IMAP server that supports maildir mailboxes only. It's available from http://www.inter7.com/courierimap/.

5.3. POP and IMAP clients

5.3.1. fetchmail

fetchmail is a program that retrieves mail from a POP or IMAP server and re-injects it locally. fetchmail has no trouble retrieving mail from qmail servers, but there are a couple tricks for making it work well on a qmail client.

Here's a sample .fetchmailrc for a user on a qmail system:

poll mail.example.net proto pop3 nodns

    user dsill with password flubgart is dave here

    fetchall forcecr to * here

This instructs fetchmail to connect to mail.example.net via POP3, log in as user dsill, password flubgart, retrieve all messages, and deliver them to dave@localhost. The forcecr causes fetchmail to end each line with a carriage return when injecting the message on the local system via SMTP. qmail requires this.

Note: fetchmail is not very reliable. If a re-injection fails for any reason (such as a formatting error that causes a bounce or there's no SMTP server running), the message will be lost.

5.3.2. getmail

getmail is a program that retrieves mail from a POP server and delivers it to a maildir mailbox. It's actually a Python script, so you may need to install the Python interpreter before you can use getmail

getmail was written by Charles Cazabon, who maintains a web page for it at http://www.qcc.sk.ca/~charlesc/software/getmail/.

5.4. Multi-RCPT vs. Single RCPT delivery

Say you're an MTA, and one of your users sends a message to three people on hostx.example.com. There are several ways you could do this.

  1. You could open an SMTP connection to hostx, send a copy of the message to the first user, send a copy to the second user, send a copy to the third user, then close the connection.
  2. You could start three processes, each of which opens an SMTP connection to hostx, sends a copy of the message to one of the users, then closes the connection.
  3. You could open an SMTP connection to host, send a copy of the message addressed to all three users, then close the connection.

The first method is clearly inferior to the third. Even if the message is tiny, it'll take at least as long. And if the message is large, it'll take a lot longer *and* use more network bandwidth.

So scratch that one.

The second and third methods are a little more interesting.

The third method only opens one connection to hostx, and only sends one copy of the message. That makes for efficient use of bandwidth.

The second method uses multiple connections and sends multiple copies of the message. That "wastes" bandwidth, but due to the nature of the SMTP protocol, requires fewer round-trip delays, and is faster than the third method. It's also simpler than the third method, so the MTA can be coded in a more straightforward manner. And finally, because each recipient gets their own copy of the message, it's possible for the MTA to implement VERPs (see next section).

qmail always uses the second method (single RCPT). There are no patches to implement the third method (multiple RCPT)--it would require major work.

Although there are pathological cases where it can be slower than multiple RCPT, the simplicity and VERP advantages outweigh that.

Single RCPT delivery does use more bandwidth than multiple RCPT delivery, but the difference is often exaggerated. Most messages have, at most, a couple recipients, and they're usually on separate hosts, so multi-RCPT delivery buys them nothing. Even on a list server, where multi-RCPT delivery could help, the potential gains are small because SMTP uses only a fraction of the bandwidth over most links--HTTP usually gets the lion's share.

For example, if 10% of your uplink's bandwidth goes to SMTP, and your SMTP bandwidth could be reduced by, say, 25%, by using multi-RCPT delivery, that would only drop your SMTP bandwidth to 7.5%.

5.5. VERP

When a message is undeliverable, the MTA that determines that is supposed to return a bounce message to the envelope return path (ERP). The bounce message should include the address of the recipient, the reason the message is undeliverable, and whether the problem is temporary or permanent. Some MTA's don't do the right thing, though. They might send the bounce the address in the From header field, or the bounce might not identify the recipient.

For most user-to-user messages, these problems aren't too bad. One can usually figure things out based on the timing of the bounce or the contents. For mailing lists, the problem of bad bounces is more serious. Subscribers move, forwarding mail to their new address. If the new address starts having delivery problems, it can be impossible to tell which subscriber's mail is bouncing if the bounce message only includes the new address.

Dan Bernstein came up with something called VERP (Variable Envelope Return Path). Using VERPs, each message sent to each subscriber to a list has a unique return path. This allows a bounce handler to identify the problem subscriber.

For example, a typical non-VERP'ed mailing list has a return address of the form listname-owner@domain. For a VERP'ed list, the return address would look like listname-owner-subscriber=sdomain@ldomain, where the subscriber's address, subscriber@sdomain, is embedded between the "owner" and the "@". (The "@" in the subscriber's address is replaced with an "=".)

The ezmlm list manager uses VERPs to automatically handle bounces. It even provides subscribers with temporary delivery problems with a list of the messages they missed so they can retrieve them from the archive.

Russell Nelson wrote a bounce manager for Majordomo under qmail, but he no longer maintains it. It's available from http://www.qmail.org/bounceman-0.4.shar.

5.6. Troubleshooting

5.6.1. Processes

A properly-running, complete, but minimal qmail installation should always have the following four processes:

Depending upon your flavor of UNIX, one of the following two commands should list these processes, and possibly a few more:

    ps -ef | grep qmail

    ps waux | grep qmail

For example:

[dave@sparge dave]$ ps waux|grep qmail

dave      2222  0.0  0.8   836   348  p4 S    10:25   0:00 grep qmail

qmaild     351  0.0  1.0   840   400  ?  S N  12:43   0:00 /usr/local/bin/tcpserver -v -x /etc/tcp.smtp.cdb -u 49491 -g 31314 0 smtp /var/qmail/bin/qmail-smtpd-

qmaild    2220  0.0  1.0   844   420  ?  S N  10:25   0:00 /usr/local/bin/tcpserver -v -x /etc/tcp.smtp.cdb -u 49491 -g 31314 0 smtp /var/qmail/bin/qmail-smtpd-

qmaill     365  0.0  0.8   748   344  ?  S N  12:43   0:00 splogger qmail

qmailq     368  0.0  0.7   736   292  ?  S N  12:43   0:00 qmail-clean

qmailr     367  0.0  0.6   732   272  ?  S N  12:43   0:00 qmail-rspawn

qmails     350  0.0  0.8   776   336  ?  S N  12:43   0:00 qmail-send

root       340  0.0  0.6   724   252  ?  S N  12:43   0:00 /usr/local/sbin/supervise /var/supervise/qmail-send /var/qmail/rc

root       341  0.0  0.6   724   252  ?  S N  12:43   0:00 /usr/local/sbin/supervise /var/supervise/tcpserver-qmail /usr/local/bin/tcpserver -v -x /etc/tcp.smtp

root       366  0.0  0.7   736   276  ?  S N  12:43   0:00 qmail-lspawn ./Mailbox

[dave@sparge dave]$

If you run qmail or qmail-smtpd under supervise, as in the example above, you should see those processes as well. And if run qmail-smtpd under tcpserver, you should see a parent tcpserver process plus an additional tcpserver process for each active incoming SMTP connection.

If you use splogger (or multilog or cyclog) to handle logging, you'll have a splogger (or multilog or cyclog) process or two running as user qmaill.

Also, if qmail is busy delivering messages locally or remotely, you'll see up to concurrencylocal qmail-local processes and up to concurrencyremote qmail-remote processes.

5.6.2. Logs splogger

splogger uses the syslog logging system to timestamp messages and send them to the syslog daemon. Syslog is configured in /etc/syslog.conf. Messages sent to syslog have a facility and priority. Entries in /etc/syslog.conf filter on the facility and priority to direct the messages to the desired log file, remote log host, or the console. splogger logs to the mail facility, by default, so grep'ing the syslog.conf file for "mail" should show the disposition of qmail's log messages.

Typical locations include:

A typical syslog log entry looks like:

Jun  3 11:35:23 sparge qmail: 928424123.963558 delivery 153: success: did_1+0+0/

"Jun 3 11:35:23" is the syslog timestamp.

"sparge" is the name of the system that sent the message.

"qmail:" is the tag splogger places on all qmail log entries.

"928424123.963558" is an optional TAI timestamp (see next section).

"delivery 153: success: did_1+0+0/" is the log message itself. multilog

multilog, which is part of the daemontools package, logs messages to a series of files in a specified directory.

The log directory is specified on the multilog command line, so you can find it by examining your qmail startup script.

The number of files in the log directory, and the maximum size of each file, are determined by multilog options. The log file names are the TAI (Temps Atomique International) timestamps of the time at which the file was started. The tai64nlocal command, also from daemontools, converts TAI timestamps into local, human-readable timestamps.

A typical multilog log entry looks like:

@4000000038c3eeb104a6ecf4 delivery 153: success: did_1+0+0/

"@4000000038c3eeb104a6ecf4" is the optional, but recommended, TAI timestamp. "delivery 153: success: did_1+0+0/" is the log message itself. Log messages

Here's a typical log sequence for a message sent to a remote system from the local system:

1 @4000000038c3eeb027f41c7c new msg 93869

2 @4000000038c3eeb027f6b0a4 info msg 93869: bytes 2343 from <dave@sill.org> qp 18695 uid 49491

3 @4000000038c3eeb02877ee94 starting delivery 2392: msg 93869 to remote lwq@w3.to

4 @4000000038c3eeb0287b55ac status: local 0/10 remote 1/20

5 @4000000038c3eeb104a13804 delivery 2392: success:


6 @4000000038c3eeb104a4492c status: local 0/10 remote 0/20

7 @4000000038c3eeb104a6ecf4 end msg 93869

Line 1 indicates that qmail has received a new message, and its queue ID is 93869. The queue ID is the i-node number of the /var/qmail/queue/mess/NN/ file--the queue file that contains the message. The queue ID is guaranteed to be unique as long as the message remains in the queue.

Line 2 says that the message is from dave@sparge.sill and is 189 bytes.

Line 3 says qmail-remote is starting to deliver the message to lwq@w3.to, and it's assigning the ID 2392 to the delivery.

Line 4 says 0 local deliveries and 1 remote delivery are pending.

Line 5 says delivery 2392 is complete and successful, and it returns the remote server's response, which often contains information the remote mail administrator would find helpful in tracking a delivery. In this case, the "CAA01516" is the remote system's delivery ID.

Line 6 says 0 local deliveries and 0 remote deliveries are pending, i.e., the delivery is complete.

Line 7 says that the message has been delivered completely and removed from the queue. At this point, the queue ID, 93869, is reusable for another delivery.

5.7. Big Servers

See also qmail-ldap.

5.7.1. Scalable parallelism

Use a fast NFS network file server to store user directories. Set up multiple equal-preference SMTP servers delivering to maildir mailboxes on the file server.

5.8. Migrating from Sendmail to qmail

First, check Dan Bernstein's Sendmail->qmail page at http://cr.yp.to/qmail/sendmail.html.

5.9. Mailing List Managers

Mailing list managers (MLM's) are systems that help list owners run mailing lists. Their duties fall into two main divisions: managing the lists of subscribers, and controlling the resending of messages to the subscribers.

Most (all?) UNIX mailing list managers can be made to work with qmail.

5.9.1. ezmlm

ezmlm was written by Dan Bernstein, the author of qmail. It was written for use with qmail, and relies on several features of qmail. Most notably, it uses VERPs to reliably process bounce messages. ezmlm is somewhat unique among MLM's in that it doesn't process commands sent to a central MLM address: it appends the command to the name of the list. E.g., to subscribe to the "foo@list.example.net" list, one sends a message to "foo-subscribe@list.example.net".

For more information about ezmlm, see http://www.ezmlm.org, the unofficial ezmlm web site, and the official home of ezmlm-idx, a very nice add-on that includes many useful features.

5.9.2. Majordomo

Majordomo is the most popular UNIX MLM. It works fine with qmail provided a few simple changes are made. Russ Allbery has written a FAQ about qmail/Majordomo available from http://www.eyrie.org/~eagle/faqs/mjqmail.html.

5.10. Patches

Various source code patches are available for qmail. To install a patch, download it, cd to the qmail source tree, and apply it using the patch command.

    cd /usr/local/src/qmail/qmail-1.03

    patch -p0 </tmp/patchfile

Stop qmail by killing qmail-send or, if you installed the qmail script in the Installation section, do:

    /usr/local/sbin/qmail stop

Then rebuild and install the new binaries:

    make setup check

5.10.1. DNS

Historically, DNS responses have been limited to 512 bytes. Some large sites have started returning MX responses longer than that. qmail and many other programs have a problem with Domain Name Server (DNS) queries that return very large results. There are two ways to fix this in qmail: Bump the packet buffer size up to 65536.

Works with recent BIND resolver libraries, which will automatically do a TCP query within the library code if the reply comes back with the truncation bit set. This is the simplest fix, though it's also potentially the most wasteful of memory, depending on how your system handles paging. To do this, just replace PACKETSZ with 65536 in dns.c and rebuild qmail. Christopher K. Davis' patch http://www.ckdhr.com/ckd/qmail-103.patch.

This is an adaptation of a patch by Chuck Foster's which should work with any resolver library, no matter how old, and uses a guard byte to avoid the "number of bytes placed in the buffer" library bug. It reallocates only once, to 65536, rather than just to the size needed, so it can be less memory-efficient than Chuck's patch (though, like his patch, it only reallocates if the response is larger than PACKETSZ, which defaults to 512 bytes). After reallocating, it forces a TCP query, rather than requiring the resolver library to do so (avoiding an extra round-trip between qmail and the name server, though if they're on the same machine or local network this is not a big worry).

5.10.2. qmail-ldap

This patch, by Andre Oppermann, et al, implements Lightweight Directory Access Protocol (LDAP) support in qmail. LDAP is like a network phone book. Using qmail-ldap, it should be possible for a POP server to serve many thousands of users. See http://www.nrg4u.com/.

5.11. QMTP

QMTP is the Quick Mail Transfer Protocol, an SMTP replacement protocol designed by Dan Bernstein. The protocol is defined at http://cr.yp.to/proto/qmtp.txt. QMTP is similar to SMTP, but is simpler, faster, and incompatible with SMTP. qmail includes a QMTP server, qmail-qmtp, which is run very much like qmail-smtp. QMTP usually uses port 209.

qmail doesn't include a QMTP client, but the serialmail package does. maildir2qmtp takes a maildir mailbox and delivers the messages it contains to designated QMTP server via QMTP.

QMTP is not a drop-in replacement for SMTP, and is not yet in widespread use across the Internet.

A. Acknowledgments

First, thanks to Dan Bernstein for designing and writing such a powerful and elegant system. After four years of use, qmail still impresses me.

I'd also like to thank the members of the qmail mailing list. Russell Nelson deserves special mention as one of the most helpful, patient, knowledgeable, and funny contributors. His contributions to the qmail community are second only to DJB's.

Thanks also to everyone who reviewed or contributed to this document, including:

Life with qmail was written using Simple Document Format (SDF), a very cool Perl-based markup language that generates HTML, plain text, PostScript, POD, and other formats. It made the job much easier. See http://www.mincom.com/mtr/sdf/ for more information.

B. Related Packages

B.1. dot-forward

Sendmail uses .forward files, pronounced dot forward, to allow users to control the delivery of messages they receive. qmail uses a similar mechanism: .qmail files. The dot-forward package gives qmail the ability to use .forward files. Systems running Sendmail or any other MTA that uses .forward files might want to consider using dot-forward to avoid having to convert existing .forward files to their .qmail equivalents--or simply to make the transition to qmail less visible to their users.

dot-forward is a small package: easy to install and configure. The source is available from ftp://cr.yp.to/software/dot-forward-0.71.tar.gz.

dot-forward was written by Dan Bernstein, who maintains a web page for it at http://cr.yp.to/dot-forward.html.

B.2. fastforward

fastforward is another Sendmail compatibility add-on. Sendmail uses a central alias database kept in a single file, usually /etc/aliases. qmail uses a series of dot-qmail files in /var/qmail/alias, one file per alias. If you're migrating to qmail, and you've got a Sendmail-format aliases file you don't want to convert, fastforward gives qmail the ability to use the aliases file as-is.

The source is available from ftp://cr.yp.to/software/fastforward-0.51.tar.gz.

fastforward was written by Dan Bernstein, who maintains a web page for it at http://cr.yp.to/fastforward.html.

B.3. ucspi-tcp

qmail's SMTP server doesn't run as a stand alone daemon. A helper program such as inetd, xinetd, or tcpserver runs as a daemon. When it receives a TCP connection to port 25, the SMTP port, it executes a copy of qmail-smtpd.

Inetd is the standard network server "super-server". It can be configured through /etc/inetd.conf to run qmail-smtpd, but the recommended tool is tcpserver, which is part of the ucspi-tcp package. ucspi-tcp is an acronym for UNIX Client-Server Program Interface for TCP, and it's pronounced ooks-pie tee see pee.

tcpserver is preferred over inetd because:

The source is available from ftp://cr.yp.to/ucspi-tcp/ucspi-tcp-0.88.tar.gz.

ucspi-tcp was written by Dan Bernstein, who maintains a web page for it at http://cr.yp.to/ucspi-tcp.html.

B.4. daemontools

The daemontools package contains a set of utilities for controlling and monitoring services. It's not mandatory, but it's highly recommended, especially for busy systems. It includes:

The source for daemontools is available from: http://cr.yp.to/daemontools/daemontools-0.70.tar.gz.

daemontools was written by Dan Bernstein, who maintains a web page for it at http://cr.yp.to/daemontools.html.

B.5. qmailanalog

qmailanalog processes qmail's log file and produces a series of reports that tell one how much and what kind of work the system is doing. If you need statistics about how many messages are being sent or received, how big they are, and how quickly they're being processed, qmailanalog is what you need.

As a bonus, the matchup program combines qmail's multiple log lines per delivery into one--not unlike the familiar Sendmail logs.

The source for qmailanalog is available from http://cr.yp.to/software/qmailanalog-0.70.tar.gz.

qmailanalog was written by Dan Bernstein, who maintains a web page for it at http://cr.yp.to/qmailanalog.html.

Note: qmailanalog relies on log entry timestamps in the fractional second format used by accustamp. In order to use it with logs generated by multilog, which are in TAI64N format, you'll need to translate them into the old format. One program to do that is available from http://www.qmail.org/tai64nfrac.

B.6. rblsmtpd

If you've never been spammed, consider yourself very lucky. Most e-mail users are all to familiar with Unsolicited Bulk E-mail (UBE), aka "spam". Most of it is advertisements for sex sites, chain letters, and other scams. Back in the days of old, up until around 1998 or so, most MTA's on the Internet were open relays, i.e., they would accept mail from anyone for anyone, even if neither sender nor recipient was local. Spammers use open relays, if they can find any, to deliver their spam. It covers their tracks, redirects the backlash toward the "innocent" relay site, and saves them lots of CPU time and network bandwidth.

Such open relays are considered very bad form these days, and several anti-spam vigilante groups have created a mechanism for identifying open relays and other common sources of spam so they can avoid accepting SMTP connections from them. These include the Realtime Blackhole List (RBL), ORBS (Open Relay Behavior-modification System), and DUL (Dial-up User List).

rblsmtpd is an RBL SMTP Daemon. It sits between tcpserver and qmail-smtpd and rejects connections from systems identified on one of these lists.

For example, to run rblsmtpd under tcpserver, try something like:


    QMAILDUID=`id -u qmaild`

    NOFILESGID=`id -g qmaild`

    MAXSMTPD=`cat /var/qmail/control/concurrencyincoming`

    exec /usr/local/bin/softlimit -m 2000000 \

    /usr/local/bin/tcpserver -v -p -x /etc/tcp.smtp.cdb -c "$MAXSMTPD" \

        -u $QMAILDUID -g $NOFILESGID 0 smtp /var/qmail/bin/rblsmtpd\

        /var/qmail/bin/qmail-smtpd 2>&1

rblsmtpd was previously available as a separate utility, but is now bundled with ucspi-tcp.

rblsmtpd was written by Dan Bernstein, who maintains a web page for it at http://cr.yp.to/ucspi-tcp/rblsmtpd.html.

B.7. serialmail

qmail was designed for systems with full time, high speed connectivity. serialmail is a set of tools that make qmail better suited to intermittent, low speed connectivity. With serialmail on such a system, qmail is configured to deliver all remote mail to a single maildir. The serialmail maildir2smtp command is used to upload the maildir to the ISP's mail hub when the connection is brought up. If the ISP supports QMTP (see QMTP under Advanced Topics), maildir2qmtp can also be used.

serialmail can be used on the ISP side of the connection to implement AutoTURN: an SMTP connection by a client causes the server to initiate a connection back to the client for sending messages queued on the server for the client. This is similar to the ETRN SMTP function.

The source for serialmail is available from http://cr.yp.to/software/serialmail-0.75.tar.gz.

serialmail was written by Dan Bernstein, who maintains a web page for it at http://cr.yp.to/serialmail.html.

B.8. mess822

mess822 is a library and set of applications for parsing RFC 822 compliant mail messages. The applications include:

The source for mess822 is available from http://cr.yp.to/software/mess822-0.58.tar.gz.

mess822 was written by Dan Bernstein, who maintains a web page for it at http://cr.yp.to/mess822.html.

B.9. ezmlm

ezmlm is a high performance, easy-to-use mailing list manager (MLM) for qmail. If you're familiar with LISTSERV or Majordomo, you know what a mailing list manager does. For more information about mailing lists under qmail see Mailing List Managers under Advanced Topics.

The source for ezmlm is available from http://cr.yp.to/software/ezmlm-0.53.tar.gz.

ezmlm was written by Dan Bernstein, who maintains a web page for it at http://cr.yp.to/ezmlm.html.

B.10. safecat

safecat reliably writes a file into a maildir mailbox. It is particularly useful for filing messages in procmail recipes. For example, the following recipe files all messages in Maildir:


|safecat Maildir/tmp Maildir/new

safecat was written by Len Budney, who maintains a web page for it at http://www.pobox.com/~lbudney/linux/software/safecat.html.

B.11. maildrop

maildrop is a mail filter similar to procmail. One feature it has that procmail doesn't (without patches) is support for maildir mailboxes.

maildrop was written by Sam Varshavchik, who maintains a web page for it at http://www.flounder.net/~mrsam/maildrop.

C. How Internet Mail Works

C.1. How a message gets from point A to point B

When a user on one host sends a message to a user on a another host, many things happen behind the scenes that you may not be aware of.

Let's say Alice, alice@alpha.example.com, wants to send a message to Bob, bob@beta.example.com. Here's what happens:

  1. Alice composes the message with her mail user agent (MUA), something like mutt or pine. She specifies the recipient in a To field, the subject of the message in a Subject field, and the text of the message itself. It looks something like:
        To: bob@beta
        Subject: lunch
        How about pizza?
  2. When she's satisfied with the message, she tells the MUA to send it.
  3. At this point, the MUA can add additional header fields like Date and Message-Id and modify the values Alice entered (e.g., replace bob@beta with "Bob <bob@beta.example.com>". Next, the MUA injects the message into the mail system. There are two ways to this: it can run a program provided by the mail system for the purpose of injecting messages, or it can open a connection to the Simple Mail Transfer Protocol (SMTP) port on either the local system or a remote mail server. For this example, we'll assume the MUA uses a local injection program to pass messages to the MTA. The details of the injection process vary by MTA, but on UNIX systems the sendmail method is a de facto standard. With this method, the MUA can put the header and body in a file, separated by a blank line, and pass the file to the sendmail program.
  4. If the injection succeeds--the message was syntactically correct and sendmail was invoked properly--the message is now the MTA's responsibility. Details vary greatly by MTA, but generally the MTA on alpha examines the header to determine where to send the message, opens an SMTP connection to beta, and forwards the message to the MTA on the beta system. The SMTP dialogue requires messages to be sent in two parts: the envelope, which specifies the recipient's address (bob@beta.example.com) and the return address (alice@alpha.example.com), and the message itself, which consists of the header and body.
  5. If the beta MTA rejects the message, perhaps because there's no user bob on the system, the MTA on alpha sends a bounce message to the return address, alice@alpha, to notify her of the problem.
  6. If the beta MTA accepts the message, it looks at the recipient's address, determines whether it's local to beta or on a remote system. In this case, it's local, so the MTA either delivers the message itself or passes it to a mail delivery agent (MDA) like /bin/mail or procmail.
  7. If the delivery fails, perhaps because Bob has exceeded his mail quota, the beta MTA sends a bounce message to the envelope return address, alice@alpha.
  8. If the delivery succeeds, the message waits in Bob's mailbox until his MUA reads it and displays it.

C.2. More information

For information about how Internet mail works, see one or more of the following:

C.2.1. Internet RFC's

Internet Requests for Comment (RFC's) are the official documentation of the Internet. Most of these are well beyond the commentary stage, and define Internet protocols such as TCP, FTP, Telnet, and the various mail standards and protocols.

A comprehensive list of mail-related RFC's is available from the Internet Mail Consortium at http://www.imc.org/mail-standards.html.

D. Architecture

D.1. Modular system architecture

Internet MTA's perform a variety of tasks. Earlier designs like Sendmail and smail are monolithic. In other words, they have one large, complex program that "switches hats": it puts on one hat to be an SMTP server, another to be an SMTP client, another to inject messages locally, another to manage the queue, etc.

qmail is modular. Each of these functions is performed by a separate program. As a result, the programs are much smaller, simpler, and less likely to contain functional or security bugs. To further enhance security, qmail's modules run with different privileges, and they don't "trust" each other: they don't assume the other modules always do only what they're supposed to do.

The core modules are:

Modules Function
qmail-smtpd accepts/rejects messages via SMTP
qmail-inject injects messages locally
qmail-rspawn/qmail-remote handles remote deliveries
qmail-lspawn/qmail-local handles local deliveries
qmail-send processes the queue
qmail-clean cleans the queue

There's also a down side to the modular approach. Unlike a monolithic MTA, the interactions between modules are well-defined, and modules only exchange the minimum necessary information with each other. This is generally A Good Thing, but sometimes it makes it hard to do things. For example, the sendmail "-v" flag causes Sendmail to print a trace of its actions to standard output for debugging purposes. Since the one sendmail binary handles injection, queueing, alias processing, .forward file processing, and remote forwarding via SMTP, it is able to easily trace the entire delivery until the message is delivered. The equivalent capability in qmail doesn't exist, and would require substantial code changes and additional complexity to implement the passing of the "debug" flag from module to module.

D.2. File structure

/var/qmail is the root of the qmail file structure. This can be changed when qmail is being built, but it's a good idea to leave it unchanged so other administrators know where to find things. If you really want to relocate some or all of the qmail tree, it's better to do that using symbolic links. See the Create directories subsection of the Installation section for details.

The top-level subdirectories are:

Directory Contents
alias .qmail files for system-wide aliases
bin program binaries and scripts
boot startup scripts
control configuration files
doc documentation (except man pages)
man man pages
queue the queue of unsent messages
users the qmail-users database files

D.3. Queue structure

The file INTERNALS in the build directory discusses the details of queueing more thoroughly. This is a broader overview of structure of the queue.

Subdirectory Contents
bounce permanent delivery errors
info* envelope sender addresses
intd envelopes under construction by qmail-queue
local* local envelope recipient addresses
lock lock files
mess* message files
pid used by qmail-queue to acquire an i-node number
remote* remote envelope sender addresses
todo complete envelopes

Note: directories marked with an "*" contain a series of split subdirectories named "0", "1", ..., up to (conf-split-1), where conf-split is a compile-time configuration setting contained in the file conf-split in the build directory. It defaults to 23. The purpose of splitting these directories is to reduce the number of files in a single directory on very busy servers.

Files under the mess subdirectory are named after their i-node number. What this means is that you can't manually move them using standard UNIX utilities like mv, dump/restore, and tar. There are a couple user-contributed utilities on http://www.qmail.org that will rename queue files correctly.

Note: It is not safe to modify queue files while qmail is running. If you want to modify the queue, stop qmail first, play with the queue carefully, then restart qmail.

D.4. Pictures

There is a series of files in /var/qmail/doc with names starting with PIC. These are textual "pictures" of various situations that qmail handles. They show the flow of control through the various modules, and are very helpful for debugging and creating complex configurations.

Filename Scenario
PIC.local2alias locally-injected message delivered to a local alias
PIC.local2ext locally-injected message delivered to an extension address
PIC.local2local locally-injected message delivered to a local user
PIC.local2rem locally-injected message delivered to a remote address
PIC.local2virt locally-injected message delivered to an address on a local virtual domain
PIC.nullclient a message injected on a null client
PIC.relaybad a failed attempt to use the local host as a relay
PIC.relaygood a successful attempt to use the local host as a relay
PIC.rem2local a message received via SMTP for a local user

These files are also available on-line from:

If you want real pictures of qmail, check out Andre Opperman's "big qmail picture" at http://www.nrg4u.com/.

E. Infrequently Asked Questions

These are questions that don't qualify as frequently asked, but which are important and not easy to answer.

E.1. How frequently does qmail try to send deferred messages?

Each message has its own retry schedule. The longer a message remains undeliverable, the less frequently qmail tries to send it. The retry schedule is not configurable. The following table shows the retry schedule for a message that's undeliverable to a remote recipient until it bounces. Local messages use a similar, but more frequent, schedule.

Delivery Attempt Seconds D-HH:MM:SS
1 0 0-00:00:00
2 400 0-00:06:40
3 1600 0-00:26:40
4 3600 0-01:00:00
5 6400 0-01:46:40
6 10000 0-02:46:40
7 14400 0-04:00:00
8 19600 0-05:26:40
9 25600 0-07:06:40
10 32400 0-09:00:00
11 40000 0-11:06:40
12 48400 0-13:26:40
13 57600 0-16:00:00
14 67600 0-18:46:40
15 78400 0-21:46:40
16 90000 1-01:00:00
17 102400 1-04:26:40
18 115600 1-08:06:40
19 129600 1-12:00:00
20 144400 1-16:06:40
21 160000 1-20:26:40
22 176400 2-01:00:00
23 193600 2-05:46:40
24 211600 2-10:46:40
25 230400 2-16:00:00
26 250000 2-21:26:40
27 270400 3-03:06:40
28 291600 3-09:00:00
29 313600 3-15:06:40
30 336400 3-21:26:40
31 360000 4-04:00:00
32 384400 4-10:46:40
33 409600 4-17:46:40
34 435600 5-01:00:00
35 462400 5-08:26:40
36 490000 5-16:06:40
37 518400 6-00:00:00
38 547600 6-08:06:40
39 577600 6-16:26:40
40 608400 7-01:00:00

E.2. Why can't I send mail to a large site with lots of MX's?

If you're getting:

deferral: CNAME_lookup_failed_temporarily._(#4.4.3)/

The problem might be that qmail can't handle large name server query responses. The fix is to install a patch. See Patches under Advanced Topics.

There's also a question as to why some people don't have trouble reaching such systems. Basically, depending on the timing and ordering of queries made to your local nameserver, the size of the response to an ANY query for "aol.com" may be larger than the 512 byte limit of a UDP packet, or it may not.

"May not" is likely to happen if the A and MX records time out, but the NS records don't. Since the .COM servers set a 2 day TTL on those, but AOL sets a 1 hour TTL on their records, this will often happen on less busy nameservers. Busier nameservers are more likely to have those records in their cache at any given time, frustrating an unpatched qmail's attempts to check for CNAMEs.

A better test is to send mail to nosuchuser@large-mx.ckdhr.com; if it clears your queue and winds up bouncing from ckdhr.com, your MTA can send mail to hosts with MX lists that exceed 512 bytes. (By using a single RRset, with a single TTL, that exceeds 512 bytes, the problem can be seen without depending on the timing and ordering of other queries.)

E.3. What is QUEUE_EXTRA?

QUEUE_EXTRA is a compile-time configuration variable that specifies an additional recipient that will be added to every delivery. This is used primarily for logging. E.g., the FAQ describes how to use QUEUE_EXTRA to keep copies of all incoming and outgoing messages.

To use QUEUE_EXTRA, edit extra.h specifying the additional recipient in the format "Trecipient\0", and the length of the QUEUE_EXTRA string in QUEUE_EXTRALEN (the "\0" counts as one character). For example:

    #define QUEUE_EXTRA "Tlog\0"

    #define QUEUE_EXTRALEN 5

Shut down qmail if it's running. If you installed the qmail script from the Installation section, that can be done by:

    /usr/local/sbin/qmail stop

If you don't have the qmail script, you should use your startup/shutdown script or send qmail-send a TERM signal.

Then rebuild qmail using:

    make setup check

Populate ~alias/.qmail-log with whatever logging you want. E.g., to log Message-ID's:

    | awk '/^$/ { exit } /^[mM][eE][sS][sS][aA][gG][eE]-/ { print }'

Finally, restart qmail.

F. Error Messages

qmail error messages and what they mean.

See RFC 1893 for an explanation of the error codes in parentheses.

This appendix is incomplete.





G. Gotchas

These frequently cause problem for qmail newbies.

G.1. qmail doesn't deliver mail to superusers.

To prevent the possibility of qmail-local running commands as a privileged user, qmail ignores all users whose UID is 0. This is documented in the qmail-getpw man page.

That doesn't mean qmail won't deliver to root, it just means that such a delivery will have to be handled by a non-privileged user. Typically, one creates an alias for root by populating ~alias/.qmail-root.

G.2. qmail doesn't deliver mail to users who don't own their home directory.

Another security feature, and just good general practice. This is documented in the qmail-getpw man page.

G.3. qmail doesn't deliver mail to users whose usernames contain uppercase letters.

qmail converts the entire "local part"--everything left of the "@" in an address, to lowercase. The man page doesn't come out and say that, but the code does. The fact that it ignores users with uppercase characters is documented in the qmail-getpw man page.

G.4. qmail replaces dots (.) in extension addresses with colons (:).

Another security feature. The purpose is prevent extension addresses from backing up the file tree using "..". By replacing them with colons, qmail ensures that all .qmail files for a user are under their home directory. Documented in the qmail-local man page.

G.5. qmail converts uppercase characters in extension addresses to lowercase.

This is another result of the fact that qmail lowercases the entire local part of addresses. Documented in the qmail-local man page.

G.6. qmail doesn't use /etc/hosts.

qmail never uses /etc/hosts to determine the IP address associated with a host name. If you use names in control files, qmail must have access to a name server.

It is possible to run qmail on systems without access to a name server, though. Hosts in control files can be specified by IP address by enclosing them in square brackets ([]), e.g.:


Actually, the square brackets aren't always necessary--but it's a good idea to use them anyway.

G.7. qmail doesn't log SMTP activity.

For a number of reasons, qmail doesn't log SMTP connections, rejections, invalid commands, or valid commands. tcpserver can be used to log connections, and recordio can be used to log the entire SMTP dialogue. recordio is part of the ucspi-tcp package. The procedure is documented in the FAQ at http://cr.yp.to/qmail/faq/servers.html#recordio.

G.8. qmail doesn't generate deferral notices.

If Sendmail is unable to deliver a message within a few hours, typically four, it sends a deferral notice to the originator. These notices look like bounce messages, but don't indicate that the delivery has failed permanently, yet.

qmail doesn't send such warnings. An undeliverable message will only be returned to the originator after it spends queuelifetime in the queue.

G.9. qmail is slow if /var/qmail/queue/lock/trigger is gone/has the wrong permissions/is a regular file.

qmail-queue and qmail-send communicate via a named pipe called /var/qmail/queue/lock/trigger. If this pipe gets messed up, qmail-send doesn't notice new messages for a half hour or so.

The best way to ensure that it's set up right is to run "make check" from the source directory. If that's not possible, make sure it looks like:

# ls -l /var/qmail/queue/lock/trigger

prw--w--w-   1 qmails   qmail           0 Jul  5 21:25 /var/qmail/queue/lock/trigger

Pay particular attention to the "p" at the beginning of the line (says it's a named pipe), the mode (especially world writable), and the owner/group.

H. Frequently Asked Questions about Life with qmail

H.1. What version is Life with qmail?

This is LWQ version 2000-09-23.

H.2. Who owns Life with qmail?

Life with qmail is Copyright 1999 and 2000 David E. Sill


H.3. How is Life with qmail licensed?

Life with qmail is covered by the OpenContent License, version 1.0. See http://www.opencontent.org/opl.shtml for the full license. Basically, you can copy, redistribute, or modify Life with qmail provided that modified versions, if redistributed, are also covered by the OpenContent License.

H.4. How can I be notified when new releases of LWQ are made available?

Join the lwq-announce mailing list by sending a message to lwq-announce-subscribe@sws1.ctd.ornl.gov.

H.5. Where can LWQ contributors and fans talk about it?

Join the lwq mailing list by sending a message to lwq-subscribe@sws1.ctd.ornl.gov.

H.6. Has Life with qmail been translated to language?

Yes, LWQ has been translated to Spanish:


And Korean:


Other translations are in the works.

If you're interested in translating Life with qmail, let me know so I can coordinate and prevent duplication of effort. I can also provide translators a copy of the SDF source document so translations can also be done in SDF. (See the next question for one reason why that's important.)

I also recommend that people translating LWQ join the lwq mailing list (see the previous question) so they can discuss translation issues and make announcements.

H.7. Is Life with qmail available in PostScript, PDF, plain text, or any other format beside HTML?

Yes, alternative formats can be found at http://Web.InfoAve.net/~dsill/qmail.html.

H.8. I used Life with qmail and it crashed my system/erased my hard disk/turned my hair gray/killed my dog/etc.

I'm sorry. Really sorry. But Life with qmail comes with no warranty. See the OpenContent License mentioned above. I didn't get paid to write it, I just wanted to contribute something useful to the qmail community.

Actually, this isn't a FAQ. In fact, I hope it's a NAQ (Never Asked Question).

H.9. How can I contribute to LWQ?

Please send corrections, suggestions, complaints, etc. to lwq@sill.org.

If you'd like to make a larger contribution, such as a new subsection or appendix, that's great! Just check with me first to make sure the topic is something I want to cover in LWQ and that nobody else is already working on it.

If you'd like to donate cash, that's always welcome, too. :-) Contact me to make arrangements, or use the PayPal e-payment system. Using PayPal, you can "beam" e-money to the e-mail address paypal@dave.sill.org in amounts as small as $0.01 at no cost to you or me--even using a credit card. And, if you're not already registered with PayPal, I'll get a $5 referral bonus and you'll get a $5 sign-up bonus. You could give me $10 without spending a penny. In order for me to get the referral bonus, you'll need to sign up using this link: https://secure.paypal.com/refer/pal=paypal%40dave.sill.org.

Another way to support LWQ at no cost to yourself is to shop at Amazon.com using this link: http://www.amazon.com/exec/obidos/redirect-home/davesill.

Take One!