########################################################################### # Qmail Notes # # Anuradha Weeraman, 22 June 2002 # # Adapted from "Life with Qmail" # # $Id: qmail.txt,v 1.1 2004/06/02 21:17:54 anuradha Exp $ # ########################################################################### Qmail by Dan Bernstein is a secure, reliable, modular MTA. comparison with other MTAs MTA Maturity Security Features Performance Sendmailish Modular ......... ......... ......... ......... ......... ......... ......... qmail medium high high high addons yes Sendmail high low high low x no Postfix medium high medium high yes yes exim medium low high medium yes no Courier low medium high medium optional yes The qmail distribution comes with a complete set of man pages. After installation, they're in /var/qmail/man. You'll probably need to add that directory to your MANPATH environment variable. The web FAQ is at http://cr.yp.to/qmail/faq.html Due to qmail's restrictive licensing regarding the distribution of prebuilt packages, qmail is usually installed from a source code distribution. The first step is to download the source code for qmail and any other add-ons. They are : qmail daemontools ucspi-tcp You could do the following to prepare for a qmail install. mkdir /var/qmail ln -s /usr/man /var/qmail/man mkdir /etc/qmail ln -s /etc/qmail /var/qmail/control ln -s /usr/sbin /var/qmail/bin Add the following groups: qmail:*:2107: nofiles:*:2108: Add the following users: alias:*:7790:2108::/var/qmail/alias:/bin/true qmaild:*:7791:2108::/var/qmail:/bin/true qmaill:*:7792:2108::/var/qmail:/bin/true qmailp:*:7793:2108::/var/qmail:/bin/true qmailq:*:7794:2107::/var/qmail:/bin/true qmailr:*:7795:2107::/var/qmail:/bin/true qmails:*:7796:2107::/var/qmail:/bin/true Make sure the UIDs and GIDs aren't duplicated. Compile qmail: cd /usr/local/src/qmail-1.03 make setup check ./config if config can't find your hostname in DNS, run: ./config-fast the.full.hostname ./config-fast dolphin.example.com Compile ucspi-tcp: cd /usr/local/src/ucspi-tcp-0.88 make make setup check Compile daemontools: cd /package/admin/daemontools-0.76 package/install On BSD systems (no /etc/inittab), you'll need to reboot at this point to start svscan, the master service control daemon. Use "ps -ef | grep svscan" or "ps waux | grep svscan" to verify that svscan is running. The /var/qmail/boot directory contains example qmail boot scripts for different configurations: /var/spool/mail vs. $HOME/Mailbox, using procmail or dot-forward, and various combinations of these. Feel free to examine these, but for our installation, we'll use the following script: #!/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`" Note: This script uses backquotes (`), not single quotes ('). For best results, copy and paste the scripts in this guide instead of retyping them. Use your editor to create the above /var/qmail/rc, then execute these commands: chmod 755 /var/qmail/rc mkdir /var/log/qmail At this point you need to decide the default delivery mode for messages that aren't delivered by a .qmail file. The following table outlines some common choices. Mailbox Name Location defaultdelivery Comments format ............. ............. ............. ............. ............. mbox Mailbox $HOME ./Mailbox most common, works with most MUA's maildir Maildir $HOME ./Maildir/ more reliable, less MUA support mbox username /var/spool/mail See traditional INSTALL.vsm UNIX mailbox To select your default mailbox type, just enter the defaultdelivery value from the table into /var/qmail/control/defaultdelivery. E.g., to select the standard qmail Mailbox delivery, do: echo ./Mailbox >/var/qmail/control/defaultdelivery If you were to manually execute the /var/qmail/rc script, qmail would be partially started. But we want qmail started up automatically every time the system is booted and we want it shut down cleanly when the system is halted. This script is available via http://www.lifewithqmail.org/qmailctl-script-dt70. On Linux and System V systems, you'll also need to link the script into the init.d directory and a couple of "rc" directories. The init.d is probably one of the following: o /etc/init.d o /sbin/init.d o /etc/rc.d/init.d Your rc directories will probably be in one of: o /etc o /sbin o /etc/rc.d Create the appropriate links: ln -s /var/qmail/bin/qmailctl INITDIR/qmail ln -s ../init.d/qmail RCDIR/rc0.d/K30qmail ln -s ../init.d/qmail RCDIR/rc1.d/K30qmail ln -s ../init.d/qmail RCDIR/rc2.d/S80qmail ln -s ../init.d/qmail RCDIR/rc3.d/S80qmail ln -s ../init.d/qmail RCDIR/rc4.d/S80qmail ln -s ../init.d/qmail RCDIR/rc5.d/S80qmail ln -s ../init.d/qmail RCDIR/rc6.d/K30qmail On all systems, make the qmailctl script executable and link it to a directory in your path: chmod 755 /var/qmail/bin/qmailctl ln -s /var/qmail/bin/qmailctl /usr/bin Now create the supervise directories for the qmail services: mkdir -p /var/qmail/supervise/qmail-send/log mkdir -p /var/qmail/supervise/qmail-smtpd/log Create the /var/qmail/supervise/qmail-send/run file: #!/bin/sh exec /var/qmail/rc Create the /var/qmail/supervise/qmail-send/log/run file: #!/bin/sh exec /usr/local/bin/setuidgid qmaill /usr/local/bin/multilog t /var/log/qmail Create the /var/qmail/supervise/qmail-smtpd/run file: #!/bin/sh QMAILDUID=`id -u qmaild` NOFILESGID=`id -g qmaild` MAXSMTPD=`cat /var/qmail/control/concurrencyincoming` if [ -z "$QMAILDUID" -o -z "$NOFILESGID" -o -z "$MAXSMTPD" ]; then echo QMAILDUID, NOFILESGID, or MAXSMTPD is unset in echo /var/qmail/supervise/qmail-smtpd/run exit 1 fi exec /usr/local/bin/softlimit -m 2000000 \ /usr/local/bin/tcpserver -v -R -l 0 -x /etc/tcp.smtp.cdb -c "$MAXSMTPD" \ -u "$QMAILDUID" -g "$NOFILESGID" 0 smtp /var/qmail/bin/qmail-smtpd 2>&1 Note: Under Solaris, the normal id program won't work right in this script. Instead of id, use /usr/xpg4/bin/id, e.g.: QMAILDUID=`/usr/xpg4/bin/id -u qmaild` NOFILESGID=`/usr/xpg4/bin/id -g qmaild` Note: The memory limit specified in the softlimit command may need to be raised depending upon your operating system and hardware platform. If attempts to connect to port 25 fail, or remote systems are unable to send you mail, try raising it to 3000000 or 4000000. Create the concurrencyincoming control file: echo 20 > /var/qmail/control/concurrencyincoming chmod 644 /var/qmail/control/concurrencyincoming Create the /var/qmail/supervise/qmail-smtpd/log/run file: #!/bin/sh exec /usr/local/bin/setuidgid qmaill /usr/local/bin/multilog t /var/log/qmail/smtpd Make the run files executable: chmod 755 /var/qmail/supervise/qmail-send/run chmod 755 /var/qmail/supervise/qmail-send/log/run chmod 755 /var/qmail/supervise/qmail-smtpd/run chmod 755 /var/qmail/supervise/qmail-smtpd/log/run Then set up the log directories: mkdir -p /var/log/qmail/smtpd chown qmaill /var/log/qmail /var/log/qmail/smtpd Finally, link the supervise directories into /service: ln -s /var/qmail/supervise/qmail-send /var/qmail/supervise/qmail-smtpd /service Note: The qmail system will start automatically shortly after these links are created. If you don't want it running yet, do: qmailctl stop Allow the local host to inject mail via SMTP: echo '127.:allow,RELAYCLIENT=""' >>/etc/tcp.smtp qmailctl cdb Lastly, replace any existing /usr/lib/sendmail with the qmail version: mv /usr/lib/sendmail /usr/lib/sendmail.old # ignore errors mv /usr/sbin/sendmail /usr/sbin/sendmail.old # ignore errors chmod 0 /usr/lib/sendmail.old /usr/sbin/sendmail.old # ignore errors ln -s /var/qmail/bin/sendmail /usr/lib ln -s /var/qmail/bin/sendmail /usr/sbin Note: It's important to create the sendmail links, regardless of the previous MTA, if any. The sendmail command is invoked by many applications for sending mail. There are three system aliases that should be created on all qmail installations: Alias Purpose .................................. .................................. postmaster RFC 2821 required, points to the mail adminstrator (you) mailer-daemon de facto standard recipient for some bounces root redirects mail from privileged account to the system administrator To create these aliases, decide where you want each of them to go (a local user or a remote address) and create and populate the appropriate .qmail files. For example, say local user dave is both the system and mail administrator: echo dave > /var/qmail/alias/.qmail-root echo dave > /var/qmail/alias/.qmail-postmaster ln -s .qmail-postmaster /var/qmail/alias/.qmail-mailer-daemon chmod 644 /var/qmail/alias/.qmail-root /var/qmail/alias/.qmail-postmaster See INSTALL.alias for more details. If you stopped qmail above after creating the links in /service, you should restart it now: qmailctl start qmail should now be running. First run qmailctl stat to verify that the services are up and running: # qmailctl stat /service/qmail-send: up (pid 30303) 187 seconds /service/qmail-send/log: up (pid 30304) 187 seconds /service/qmail-smtpd: up (pid 30305) 187 seconds /service/qmail-smtpd/log: up (pid 30308) 187 seconds messages in queue: 0 messages in queue but not yet preprocessed: 0 All four services should be "up" for more than a second. Next, follow the instructions in TEST.deliver and TEST.receive to verify that it's working correctly. Note that using these instructions, logging will be accomplished by multilog, not splogger. Configuration Files ------------------- All of qmail's system configuration files, with the exception of the .qmail files in ~alias, reside in /var/qmail/control. The qmail-control man page contains a table like the following: Control Default Used by Purpose ................. ................ ................. ................ badmailfrom none qmail-smtpd blacklisted From addresses bouncefrom MAILER-DAEMON qmail-send username of bounce sender bouncehost me qmail-send hostname of bounce sender concurrencylocal 10 qmail-send max simultaneous local deliveries concurrencyremote 20 qmail-send max simultaneous remote deliveries defaultdomain me qmail-inject default domain name defaulthost me qmail-inject default host name databytes 0 qmail-smtpd max number of bytes in message (0=no limit) doublebouncehost me qmail-send host name of double bounce sender doublebounceto postmaster qmail-send user to receive double bounces envnoathost me qmail-send default domain for addresses without "@" helohost me qmail-remote host name used in SMTP HELO command idhost me qmail-inject host name for Message-ID's localiphost me qmail-smtpd name substituted for local IP address locals me qmail-send domains that we deliver locally me FQDN of system various default for many control files morercpthosts none qmail-smtpd secondary rcpthosts database percenthack none qmail-send domains that can use "%"-style relaying plusdomain me qmail-inject domain substituted for trailing "+" qmqpservers none qmail-qmqpc IP addresses of QMQP servers queuelifetime 604800 qmail-send seconds a message can remain in queue rcpthosts none qmail-smtpd domains that we accept mail for smtpgreeting me qmail-smtpd SMTP greeting message smtproutes none qmail-remote artificial SMTP routes timeoutconnect 60 qmail-remote how long, in seconds, to wait for SMTP connection timeoutremote 1200 qmail-remote how long, in seconds, to wait for remote server timeoutsmtpd 1200 qmail-smtpd how long, in seconds, to wait for SMTP client virtualdomains none qmail-send virtual domains and users Disabling relaying ------------------ If you follow the official directions for installing qmail, relaying will be turned off by default. This is accomplished by populating the file /var/qmail/control/rcpthosts with the fully-qualified domain names listed in locals and virtualdomains (the local hosts). The name of the control file, rcpthosts, comes from the SMTP RCPT (recipient) command. In an SMTP session, RCPT is used to specify the addresses of the recipients of a message. rcpthosts, then, lists the valid hostnames that can appear in a RCPT address. Allowing selective relaying --------------------------- Most single-user and small workgroup servers can disable relaying completely, but if you have to support a distributed user community, you'll need a way to allow your users, and only your users, to use your system as a relay. This is accomplished by using tcpserver to set the RELAYCLIENT environment variable, which tells qmail-smtpd to override the rcpthosts file. If you follow the installation instructions in this document, selective relaying will be enabled by default. To give a client relay access, add an entry to /etc/tcp.smtp like: IP address of client:allow,RELAYCLIENT="" Then rebuild the SMTP access database by doing: qmailctl cdb or: tcprules /etc/tcp.smtp.cdb /etc/tcp.smtp.tmp < /etc/tcp.smtp chmod 644 /etc/tcp.smtp* Multiple host names ------------------- If your system is known by more than one name, e.g., all addresses of the form user@host1.example.com can also be written as user@example.com or user@mail.example.com, then you need to tell qmail this so it'll know which addresses it should deliver locally and which messages it should accept from remote systems. To do this, just add all of the names to two control files: o rcpthosts, which tells qmail-smtpd to accept mail addressed to these hosts, and o locals, which tells qmail-send that addresses on these hosts are to be delivered locally. Virtual domains --------------- Virtual domains are similar to the multiple host names discussed in the previous section, but there are some important differences. First, if example.net hosts the virtual domain virtual.example.com, it's generally not true that messages sent to joe@example.net will end up in the same mailbox as messages sent to joe@virtual.example.com. The namespace for each virtual domain is distinct. With qmail, virtual domains are configured in the virtualdomains file, which consists of one or more entries of the form: user@domain:prepend qmail converts user@domain to prepend-user@domain and treats the result as if domain was local. The user@ part is optional. If it's omitted, the entry matches all @domain addresses. Returning to the example scenario above, if the example.net mail administrator wanted to create a virtual domain, virtual.example.com, under the administrative control of user john, the following entry in virtualdomains would accomplish that: virtual.example.com:john An incoming message to joe@virtual.example.com would be rewritten as john-joe@virtual.example.com and delivered locally. See the .qmail section, and the extension addresses subsection for more information about how john can manage his virtual domain. As with multiple host names, all virtual domains must be listed in rcpthosts so qmail-smtpd will know to accept messages addressed to them. However, unlike multiple host names, virtual domains must not be added to locals. Note: Domain name server (DNS) mail exchanger (MX) records must be set up to direct messages for virtual domains to the appropriate mail server. This is a job for the name server administrator and is beyond the scope of this guide. Aliases ------- qmail's standard aliasing mechanism is a natural outgrowth of qmail's local delivery mechanism. qmail-local attempts to deliver a message addressed to localpart@host to a local user named localpart. If no matching user is found, the message is delivered to the alias user, a pseudo-user on all qmail systems whose home directory is /var/qmail/alias. For example, say you want to create an info@example.com alias that forwards messages to user tom. On example.com, do, as user root: echo tom > /var/qmail/alias/.qmail-info The .qmail section and extension addresses subsection describe how to create .qmail files that specify which aliases exist, and what to do with messages sent to them. Note that because of the way aliases are implemented in qmail, an alias can never override a valid user's deliveries. E.g., if rachel is a normal user, ~alias/.qmail-rachel will not be used. The fastforward package provides an alternative aliasing mechanism that puts multiple aliases in a single file compatible with Sendmail's alias database. The next section, qmail-users, describes another mechanism that can be used to implement aliases. qmail-users ----------- qmail-users is a system for assigning addresses to users. A series of configuration files resides under /var/qmail/users. The assign file is a table of assignments. There are two kinds of assignments: simple and wildcard. Note: assign contains a series of assignments, one per line, followed by a line containing a single dot (.). If you create assign manually, don't forget the dot line. Simple assignment ----------------- A simple assignment looks like: =address:user:uid:gid:directory:dash:extension: What this means is that messages received for address will run as user user, with the specified uid and gid, and the file directory/.qmaildashextension will specify how the messages are to be delivered. Wildcard assignment ------------------- A wildcard assignment looks like: +prefix:user:uid:gid:directory:dash:prepend: What this means is that messages received for addresses of the form prefixrest will run as user user, with the specified uid and gid, and the file directory/.qmaildashprependrest will specify how the messages are to be delivered. qmail-user programs ------------------- qmail-user has two helper programs: qmail-newu and qmail-pw2u. qmail-newu processes the assign file and generates a constant database (CDB) file called cdb in /var/qmail/users. CDB is binary format that can be accessed quickly by qmail-lspawn, even when there are thousands of assignments. qmail-pw2u converts the system user database, /etc/passwd, into a series of assignments suitable for assign. qmail-pw2u uses a set of files to modify the translation rules. o include: users to include o exclude: users to exclude o mailnames: alternative "mailnames" for users o subusers: extra addresses handled by a user, with an optional .qmail extension o append: miscellaneous assignments Note: If you use qmail-pw2u, don't forget to re-run qmail-pw2u and qmail-newu whenever you add users, remove users, or change UID's or GID's. A typical sequence would be: qmail-pw2u /var/qmail/users/assign qmail-newu Spam Control ------------ Chris Hardie has written an excellent qmail Anti-Spam HOWTO. It's available from http://www.summersault.com/chris/techno/qmail/qmail-antispam.html. .qmail files ------------ Delivery of a user's mail is usually controlled by one or more ".qmail" (pronounced dot kyoo mail) files--files in the user's home directory with names beginning with .qmail. The dot-qmail man page describes .qmail file usage. .qmail files contain a list of delivery instructions, one instruction per line. The first character of the line determines what kind of delivery is involved: Character Delivery Type Value ...................... ....................... ...................... # none (comment) ignored | program command to be run by shell / or . mbox (if last char pathname of mbox isn't a /) (including the / or .) / or . maildir (if last char pathname of maildir is a /) (including the / or .) & forward address to forward message letter or number forward address to forward message (including the first char) program delivery ---------------- When a program delivery instruction is encountered, qmail starts a shell (/bin/sh) to execute the command and feeds the command a copy of the incoming message on standard input. The qmail-command man page documents the details of this process. Program delivery is very powerful, and can be used to implement a wide range of functionality such as message filtering, automatically responding to messages, and delivery via third-party delivery agents such as procmail. E.g.: |preline /usr/ucb/vacation djb This causes qmail to start preline, pass it /usr/ucb/vacation and djb as arguments, and provide a copy of the message on standard input. mbox delivery ------------- "Mbox" is qmail-speak for the standard UNIX mailbox format, in which multiple messages are stored in a single file and messages are headed with a "From " line. This line looks like a header field, but it isn't one: it's just something the delivery agent adds so mail readers can tell where each message begins. E.g.: ./Mailbox This causes messages to be appended to $HOME/Mailbox, with a "From " line prepended. A simple mbox mailbox with a single message looks like: From user1@example.net Thu May 13 18:34:50 1999 Received: (qmail 1287205 invoked from network); 13 May 1999 18:34:49 -0000 From: user1@example.net To: user2@example.com Subject: hey What's up? The first line was added at delivery by qmail. maildir delivery ---------------- "Maildir" is a mailbox format created by Dan Bernstein to address the shortcomings of the mbox format. A maildir mailbox is a directory containing three subdirectories, new, cur, and tmp. Each message in a maildir mailbox is in a separate file in one of the subdirectories, depending upon its status: new is for unread messages, cur is for messages that have been seen, and tmp is for messages in the process of being delivered. The maildir man page describes the format of a maildir in detail. One of the benefits of the maildir format is that, even though it doesn't use locking to prevent simultaneous updates from different delivery agents, it's reliable. This means maildir mailboxes can safely reside on NFS-mounted filesystems. E.g.: ./Maildir/ This causes messages to be saved in $HOME/Maildir, a maildir-format mailbox. Note: qmail-local can deliver mail to maildir mailboxes, but it can't create them. Maildir mailboxes should be created with the maildirmake program that comes with qmail. E.g., "maildirmake ~/Maildir". Be sure to run maildirmake as the owner of the maildir, not as root. Your useradd or adduser command might support a "skeleton" directory, e.g. /etc/skel, where you can create a maildir that will be copied for all new users. forward delivery ---------------- Forward deliveries causes the message to be resent to the specified address. Addresses specified in .qmail files can't contain comment fields or extra spaces. E.g.: &user@example.com user@example.com &user extension addresses ------------------- qmail supports user-controlled extension addresses. In addition to the base address, username@hostname.domain, users can receive mail at username-extension@hostname.domain. For the remainder of this section, I'll leave off the "@hostname.domain" part since we're considering actions that take place on the local system. The delivery instructions for username-extension are in ~username/.qmail-extension. For example, dave-lwq@sparge.example.com is controlled by ~dave/.qmail-lwq on host sparge. Extensions can have multiple fields, e.g., dave-list-qmail, controlled by ~dave/.qmail-list-qmail. In this example, dave-list-qmail is subscribed to the qmail mailing list, and ~dave/.qmail-list-qmail files the list messages in a separate mailbox. .qmail files can be wildcarded using -default. So dave-list-qmail could also be handled by ~dave/.qmail-list-default. This would allow one catch-all .qmail file to handle all dave-list-whatever addresses. Note that dave-list wouldn't be handled by ~dave/.qmail-list-default because it doesn't match the "-" after "list". qmail uses the closest match it finds. E.g., when a message comes in addressed to dave-list-qmail, it'll use the first one of the following that it finds: .qmail-list-qmail .qmail-list-default .qmail-default If no matching .qmail file is found, the delivery fails and the message bounces back to the sender. Sending messages ---------------- Mail users don't usually use the MTA directly to send messages. Typically, messages are composed and sent using a Mail User Agent (MUA) such as pine or mutt, which then calls the MTA to deliver the message. The process of handing a message to the MTA is called injection. There are two ways to inject messages into most MTA's: via the Simple Mail Transfer Protocol, SMTP, or using a program provided by the MTA for that purpose. SMTP ---- MUA's can open a TCP connection to port 25, the standard SMTP port, on the local host or a designated mail server. The MUA and the MTA then engage in a dialogue that results in either: o the message being transfered to the MTA, or o a error status being returned to the MUA SMTP has no mechanism for authentication, so no username or password is required to send a message. However, many MTA's refuse to accept messages that don't appear to be either from or for a local user. If a properly formatted message is rejected, relaying restrictions are the most likely cause. See the Relaying section for more information about relay configuration. /var/qmail/bin/sendmail ----------------------- For many years, Sendmail was theUNIX MTA. It was so ubiquitous, that many programmers just assumed that it was the MTA. As a result, Sendmail's local injection mechanism became the standard Application Programmer's Interface (API) for local mail injection. qmail and other non-Sendmail MTA's provide a sendmail program that works the same way as the real Sendmail's sendmail for local injection. The qmail sendmail, which is normally in /var/qmail/bin/sendmail, usually replaces the Sendmail sendmail on qmail systems. Typical locations of the sendmail program include: o /usr/lib/sendmail o /usr/sbin/sendmail qmail-inject ------------ In addition to emulating the sendmail API, qmail has its own injection program: qmail-inject. In fact, sendmail is just a wrapper around qmail-inject. As an API, sendmail is probably better because it's much more widely available. The qmail API provided by qmail-inject will only work on systems with qmail, but the sendmail interface is nearly universal. For example, to send a blank message to joe@example.com: echo To: joe@example.com | /var/qmail/bin/qmail-inject procmail -------- procmail is a popular Message Delivery Agent (MDA). The function of an MDA is to accept a message from the MTA for a specific user or mailbox, and deliver the message according to the user's desires. procmail can be used to "filter" messages by the content of various header fields or the body of the message. For example, messages from a particular person can be directed to a mailbox for just that person. There are a couple tricks to running procmail with qmail. First, procmail is usually built to deliver to an mbox mailbox in /var/spool/mail. You can rebuild procmail to default to $HOME or you can instruct users not to rely on procmail to default the location of the mbox. Unless you patch it for $HOME delivery, procmail will still use /var/spool/mail for temporary files. Another problem is that qmail-command and procmail don't have a common understanding of which exit codes mean what. procmail uses the standard UNIX exit codes: zero means success, nonzero means failure, and the cause of the failure is indicated by /usr/include/sys/errno.h. qmail-command uses certain nonzero codes to indicate permanent errors and the rest are considered temporary. A small shell script wrapper can be used to translate the exit codes for qmail-command. Such a wrapper was posted to the qmail list and is available from the archives at http://www.ornl.gov/its/archives/mailing-lists/qmail/1998/04/msg00487.html. Also, older versions of procmail (prior to 3.14) don't deliver directly to maildir-format mailboxes. Your best bet is to upgrade to the current version of procmail. Another approach is safecat, a program that writes a message on standard input to a specified maildir. Users can write procmail recipes (delivery instructions) that use safecat to file the message. You can also skip procmail altogether, and use maildrop. Finally, procmail expects the messages it receives to be in mbox format. Normal qmail program deliveries include only the actual mail message, not including a "From " line. The preline command can be used to format the message as procmail expects. The wrapper linked above includes preline. For example, let's say user "dave" wants his mail to be processed by procmail. His system administrator has built procmail to deliver to $HOME by default, and has provided the exit code wrapper linked above, called /usr/local/bin/qmail-procmail. His .qmail file should look like: |/usr/local/bin/qmail-procmail dave qmail-pop3d ----------- qmail-pop3d is the POP server included with qmail. It's a fine POP server, and many qmail sites use it. It's modular, and supports multiple authentication schemes via alternative authentication modules. Note: qmail-pop3d supports only maildir-format mailboxes, so if you have users logging into the POP server and running MUA's locally, they all have to support maildir. If all of your users read mail via POP, the mailbox format on the server is not an issue. Architecture of qmail-pop3d --------------------------- A qmail-pop3d server consists of three modules: o qmail-popup--gets username/password o checkpassword--authenticates username/password o qmail-pop3d--the POP daemon Typically, qmail-popup is run via inetd or tcpserver, listening to port 110, the POP3 port. When a connection is made, it prompts for the username and password. Then it invokes checkpassword, which verifies the username/password and invokes qmail-pop3d if they match. Installation of qmail-pop3d --------------------------- 1. Completely install and test qmail. If you want all users to have POPable mailboxes, make sure defaultdelivery is set to ./Maildir/. If you installed the /var/qmail/rc script from the Installation section, this is configured in control/defaultdelivery. If not, it's probably in /var/qmail/rc on the qmail-start command line. 2. Download a checkpassword program from http://www.qmail.org/top.html#checkpassword. The standard checkpassword, http://cr.yp.to/checkpwd.html, is a good choice if you don't need anything fancy. 3. Compile and install checkpassword according to the directions. Make sure you install it as /bin/checkpassword. 4. Create a /var/qmail/supervise/qmail-pop3d/run script containing: #!/bin/sh exec /usr/local/bin/softlimit -m 2000000 \ /usr/local/bin/tcpserver -v -R -H -l 0 0 110 /var/qmail/bin/qmail-popup \ FQDN /bin/checkpassword /var/qmail/bin/qmail-pop3d Maildir 2>&1 where FQDN is the fully qualified domain name of the POP server you're setting up, e.g., pop.example.net. 5. Create a /var/qmail/supervise/qmail-pop3d/log/run script containing: #!/bin/sh exec /usr/local/bin/setuidgid qmaill /usr/local/bin/multilog t \ /var/log/qmail/pop3d 6. Set up the log directory and permissions on the run scripts, and link the service into /service: chmod +t /var/qmail/supervise/qmail-pop3d # if daemontools < 0.75 mkdir /var/log/qmail/pop3d chown qmaill /var/log/qmail/pop3d chmod 755 /var/qmail/supervise/qmail-pop3d/run chmod 755 /var/qmail/supervise/qmail-pop3d/log/run ln -s /var/qmail/supervise/qmail-pop3d /service 7. Add the following to qmailctl's "start" section: if svok /service/qmail-pop3d ; then svc -u /service/qmail-pop3d else echo qmail-pop3d supervise not running fi 8. Add the following to qmailctl's "stop" section: echo " qmail-pop3d" svc -d /service/qmail-pop3d 9. Add the following to qmailctl's "stat" section: svstat /service/qmail-pop3d svstat /service/qmail-pop3d/log 10. Add the following to qmailctl's "pause" section: echo "Pausing qmail-pop3d" svc -p /service/qmail-pop3d 11. Add the following to qmailctl's "cont" section: echo "Continuing qmail-pop3d" svc -c /service/qmail-pop3d 12. Add the following to qmailctl's "restart" section: echo "* Restarting qmail-pop3d." svc -t /service/qmail-pop3d 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. 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%. Processes --------- A properly-running, complete, but minimal qmail installation should always have the following four processes: o qmail-send running as user qmails o qmail-clean running as user qmailq o qmail-rspawn running as user qmailr o qmail-lspawn running as user root 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. 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: o /var/log/syslog o /var/adm/SYSLOG o /var/log/maillog 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 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: 209.85.127.177_accepted_message. /Remote_host_said:_250_CAA01516_Message_accepted_for_delivery/ 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@sill.org 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. Big Servers ----------- See also qmail-ldap. 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. 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. 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. 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 &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. 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 maildirsmtp 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), maildirqmtp 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. mess822 ------- mess822 is a library and set of applications for parsing RFC 822 compliant mail messages. The applications include: o ofmipd: a daemon that accepts messages from clients and rewrites From fields based on a database. o new-inject: a qmail-inject replacement that supports user-controlled hostname rewriting. o iftocc: a .qmail utility for checking whether a message was sent to a specific address. o 822header, 822field, 822date, and 822received: extract information from a message. o 822print: pretty-prints a message. 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. More information ---------------- For information about how Internet mail works, see one or more of the following: o Internet mail, by the author of qmail. http://cr.yp.to/im.html o SMTP, by the author of qmail. http://cr.yp.to/smtp.html o Internet mail message header format, by the author of qmail. http://cr.yp.to/immhf.html 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. 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 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. conf-split must be a prime number. 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. 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 Infrequently Asked Questions ---------------------------- 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. 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 djbdns. 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 qmailctl script from the Installation section, that can be done by: qmailctl stop If you don't have the qmailctl 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. 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.: [10.1.2.219] 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.10. DNS or IDENT lookups can make SMTP slow --------------------------------------------- If qmail-smtpd is slow to respond to connections, the problem is probably due to DNS reverse lookups or IDENT lookups. If you're starting qmail-smtpd with tcpserver, remove the "-h", "-p", and "-r" options and add "-H", "-P", "-R", and "-l 0" (ell zero).