Linux notebook / qmail
Description: Documents various Linux or *nix programs and concepts, including qmail, djbdns, emacs, Perl, hardware, bash, TCP/IP, DNS, etc...
Keywords: find djbdns system dns typical bash less gdb daemontools mirrordir math tables mysql qmail isdn make http ezmlm shell pppd cftp regexps intro awk dhcp test hardware ucspi-tcp apache html perl php3 fetchmail versions emacs email peripherals

Apache Awk Bash C cftp daemontools DHCP djbdns DNS Emacs Email ezmlm Fetchmail find GDB Hardware HTML HTTP Intro ISDN less Make Math mc mirrordir MySQL Peripherals Perl PHP3 pppd qmail Regexps Shell System Tables test To do Typical ucspi-tcp Versions Index TCP/IP slides
qmail |
.qmail | qmail data flow | qmail queue structure | Control files | env vars cross-ref | qmail-send | qmail-inject | qmail-remote | qmail-qmqpc | qmail-smtpd
| top

> How to recreate the trigger pipe

> Qmail requires a pipe, named /var/qmail/queue/lock/trigger, with the correct permissions. If absent or with the wrong permissions, qmail does not detect new mail in a fast way. The pipe must have 0622 permissions ( thus showing up as prw--w--w- in ls -l ), and ownership qmails.qmail. To recreate the pipe, use the commands:

> > rm -f /var/qmail/queue/lock/trigger
> > mkfifo -m 0622 /var/qmail/queue/lock/trigger
> > chown qmails.qmail /var/qmail/queue/lock/trigger

> It's a good idea to restart qmail after this.

> How to clean the outbound queue

> The only safe operation that can be done over the queued messages is to change the date. Therefore, one way to clean the message queue is to touch the messages to a timestamp that makes qmail think that they have been too long in the queue, and bounce them. This can be done as follows:

> > find /var/qmail/queue -type f -name '[0-9]*' -exec touch -d 19900101 '{}' ';'

> Then, manually run the queue, as per instructions below. This line can be made into a shell script, of course.

> How to define a upstream SMTP server

> > cp /var/qmail/control/me /var/qmail/control/helohost
> > echo :smtp.server > /var/qmail/control/smtproutes
> > /etc/init.d/qmail restart

> (replace smtp.server by ISP's SMTP server)

> How to forward messages

> To forward messages for a specific user, eg. to other@somewhere.com, edit the user's ~/.qmail file, and add:

> > &other@somewhere.com

> How to forward unrecognized user names

> To forward unrecognized user names to another host (eg. turkopolis.com), edit ~alias/.qmail-default and add:

> > | /var/qmail/bin/forward "$LOCAL@turkopolis.com"

> How to manually run the mail queue

> Send an ALRM to the qmail-send process, as mentioned below.

> How to check the queue contents

> Use qmail-qread. It scans the outgoing queue, printing information for each message waiting for being sent.

> .qmail

> The qmail system follows delivery instructions based on the user's .qmail file.

> Note that the name .qmail may be followed by dash separated sub-addressing. For example, given the user someone at someserver.com, the file ~someone/.qmail controls delivery for the address someone@someserver.com; the file ~someone/.qmail-logs controls delivery for the address someone-logs@someserver.com; a file ~someone/.qmail-default controls delivery for any address in the form someone-xxxx@someserver.com, that is, default acts as a wildcard.

> Within a .qmail file, each line starts by a character that is a command, and the following commands are interpreted:

> .qmail commands
> prefix | example | meaning
> --- | --- | ---
> # | # this is a comment | Comment: the line is ignored
> | | | /var/qmail/bin/forward "$LOCAL@turkopolis.com" | Program: the given command is called, with a number of environment variables, and the message is delivered trough the program's stdin. See below for the environment settings
> & | &otherguy@otherplace.com | Forwarding: the message is forwarded to the given address
> /xxxxx .xxxxx | /home/guy/mailbox | Mailbox: the line defines the mailbox style file where the message should end up. Note that the line does not end in a slash. The line may start by a dot (in which case the address is taken relative to the .qmail file's location), or by a slash, in which case it is a absolute pathname
> /xxxxx/ .xxxxx/ | ./Maildir/ | Maildir: the line defines the maildir style directory where the message should end up. Note that the line ends with a slash. The starting dot or slash have the same meaning as in the Mailbox line

> For the "Program" commands (the ones starting with a pipe), the message is fed trough stdin, and the return code of the program has the following meaning:

> .qmail pipe error codes
> code | meaning
> --- | ---
> 0 | Delivery successful
> 99 | Delivery successful, but the rest of the .qmail file should be ignored
> 100 | Delivery failed permanently (hard error)
> 111 | Delivery failed temporarily (soft error)

> For the "Program" commands, the following environment variables are made available

> .qmail pipe environment variables
> variable | contents
> --- | ---
> $SENDER | Envelope sender address
> $NEWSENDER | Forwarding envelope sender address
> $RECIPIENT | Envelope recipient address (local@domain)
> $USER | The user
> $HOME | The home directory
> $HOST | The domain part of the recipient address
> $HOST2 | The portion of $HOST preceding the last dot
> $HOST3 | The portion of $HOST preceding the second-to-last dot
> $HOST4 | The portion of $HOST preceding the third-to-last dot
> $LOCAL | The local part of the recipient address
> $EXT | The address extension
> $EXT2 | The portion of $EXT following the first dash
> $EXT3 | The portion of $EXT following the second dash
> $EXT4 | The portion of $EXT following the third dash
> $DEFAULT | The portion corresponding to the default part of the .qmail-... filename This is not set if the .qmail-... does not end in default
> $DTLINE | The Delivered-To: line, including newline
> $RPLINE | The Return-Path: line, including newline
> $UFLINE | The UUCP style From_ added to the mbox-format files

> The qmail data flow

> qmail-inject and qmail-smtpd send their output directly to qmail-queue, which places the messages in the output queue.

> qmail-send scans the queue, locating messages that are to be sent. Messages are sent to qmail-lspawn if they are destined to the local host, or to qmail-rspawn if they are destined to a remote host.

> qmail-lspawn passes the messages to be delivered locally to qmail-local, which places them in the appropriate maildir.

> qmail-rspawn passes the messages to be delivered remotely to qmail-remote, which calls the remote hosts SMTP server.

> qmail-clean is then called from qmail-send to clean the queue of messages already sent, or that have aged past queuelifetime.

> qmail queue structure

> Subdirectory of /var/qmail/queue | Contents
> --- | ---
> bounce | Permanent delivery errors
> info/* | Envelope sender address, after preprocessing
> intd | Envelope under construction by qmail-queue
> local/* | Local envelope recipient addresses, after preprocessing
> lock | Lock files
> mess/* | The message
> pid | Used by qmail-queue to get a PID from which a i-node number is obtained
> remote/* | Remote envelope recipient addresses, after preprocessing
> todo | Envelopes, from where the message came, where it is going

> Control files

> The qmail system is controlled by control files, as follows

> qmail control files
> control file | default | used by
> --- | --- | ---
> badmailfrom | (none) | qmail-smtpd
> bouncefrom | MAILER-DAEMON | qmail-send
> bouncehost | me | qmail-send
> concurrencylocal | 10 | qmail-send
> concurrencyremote | 20 | qmail-send
> defaultdomain | me | qmail-inject
> defaulthost | me | qmail-inject
> databytes | 0 | qmail-smtpd
> doublebouncehost | me | qmail-send
> doublebounceto | postmaster | qmail-send
> envnoathost | me | qmail-send
> helohost | me | qmail-remote
> idhost | me | qmail-inject
> localiphost | me | qmail-smtpd
> locals | me | qmail-send
> control file | default | used by
> --- | --- | ---
> morercpthosts | (none) | qmail-smtpd
> percenthack | (none) | qmail-send
> plusdomain | me | qmail-inject
> qmqpservers | (none) | qmail-qmqpc
> queuelifetime | 604800 seconds (7 days) | qmail-send
> rcpthosts | (none) | qmail-smtpd
> smtpgreeting | me | qmail-smtpd
> smtproutes | (none) | qmail-remote
> timeoutconnect | 60 seconds | qmail-remote
> timeoutremote | 1200 seconds (20 minutes) | qmail-remote
> timeoutsmtpd | 1200 seconds (20 minutes) | qmail-smtpd
> virtualdomains | (none) | qmail-send

> Environment variables cross-reference and description

> Variable | Description | Produced by | Used by
> --- | --- | --- | ---
> $DATABYTES | Overrides databytes, maximum number of bytes (as stored in disk) that a message is allowed, 0 if no limit |  | qmail-smtpd
> $DEFAULT | The portion corresponding to the default part of the .qmail-... filename, not set if the .qmail-... does not end in default | qmail-local | pipe environment in .qmail
> $DTLINE | The Delivered-To: line, including newline | qmail-local | pipe environment in .qmail
> $EXT2 | The portion of $EXT following the first dash | qmail-local | pipe environment in .qmail
> $EXT3 | The portion of $EXT following the second dash | qmail-local | pipe environment in .qmail
> $EXT4 | The portion of $EXT following the third dash | qmail-local | pipe environment in .qmail
> $EXT | The address extension | qmail-local | pipe environment in .qmail
> $HOME | The destination home directory | qmail-local | pipe environment in .qmail
> $HOST2 | The portion of $HOST preceding the last dot | qmail-local | pipe environment in .qmail
> $HOST3 | The portion of $HOST preceding the second-to-last dot | qmail-local | pipe environment in .qmail
> $HOST4 | The portion of $HOST preceding the third-to-last dot | qmail-local | pipe environment in .qmail
> $HOST | The domain part of the recipient address | qmail-local | pipe environment in .qmail
> $LOCAL | The local part of the recipient address | qmail-local | pipe environment in .qmail
> $NEWSENDER | Forwarding envelope sender address | qmail-local | pipe environment in .qmail
> $PROTO | The string "TCP" | tcp-env tcpclient tcpserver | qmail-smtpd
> $QMAILDEFAULTDOMAIN | Overrides defaultdomain, added to any host name without dots |  | qmail-inject
> $QMAILDEFAULTHOST | Overrides defaulthost, added to any address without host name |  | qmail-inject
> $QMAILIDHOST | Overrides idhost, host name for message IDs |  | qmail-inject
> $QMAILPLUSDOMAIN | Overrides plusdomain, added to any host name ending in a plus sign |  | qmail-inject
> $RECIPIENT | Envelope recipient address (local@domain) | qmail-local | pipe environment in .qmail
> $RELAYCLIENT | Overrides rcpthosts, allows relayed message trough and is appended to the incoming recipient address |  | qmail-smtpd
> $RPLINE | The Return-Path: line, including newline | qmail-local | pipe environment in .qmail
> $SENDER | Envelope sender address | qmail-local | pipe environment in .qmail
> $TCPLOCALHOST | The domain name of the local host, with uppercase letters converted to lowercase. If there is no currently available domain name for the local IP address, TCPLOCALHOST is not set. Can contain arbitrary characters | tcp-env tcpclient tcpserver | qmail-smtpd
> $TCPLOCALIP | The IP address of the local host, in dotted-decimal form | tcp-env tcpclient tcpserver | qmail-smtpd
> $TCPLOCALPORT | The local TCP port number, in decimal | tcp-env tcpclient tcpserver | qmail-smtpd
> $TCPREMOTEHOST | The domain name of the remote host, with uppercase letters converted to lowercase. If there is no currently available domain name for the remote IP address, TCPREMOTEHOST is not set. Can contain arbitrary characters | tcp-env tcpclient tcpserver | qmail-smtpd
> $TCPREMOTEINFO | A connection-specific string, perhaps a username, supplied by the remote host via 931/1413/IDENT/TAP. If the remote host did not supply connection information, TCPREMOTEINFO is not set. Can contain arbitrary characters | tcp-env tcpclient tcpserver | qmail-smtpd
> $TCPREMOTEIP | The IP address of the remote host | tcp-env tcpclient tcpserver | qmail-smtpd
> $TCPREMOTEPORT | The remote TCP port number | tcp-env tcpclient tcpserver | qmail-smtpd
> $UFLINE | The UUCP style From_ added to the mbox-format files | qmail-local | pipe environment in .qmail
> $USER | The user | qmail-local | pipe environment in .qmail

> qmail-send

> qmail-send handles messages placed into the outgoing queue by qmail-queue. It uses qmail-lspawn to deliver messages to local recipients and qmail-rspawn to deliver messages to remote recipients. If a message is temporarily undeliverable to one or more addresses, qmail-send leaves it in the queue and tries the addresses again later.

> If qmail-send receives an ALRM signal, it will reschedule every message in the queue for immediate delivery.

> qmail-send reads its control files only when it starts. If you change the control files, you must stop and restart qmail-send. Exception: If qmail-send receives a HUP signal, it will reread locals and virtualdomains.

> qmail-send control files
> bouncefrom | Bounce username. Default: MAILER-DAEMON
> bouncehost | Bounce host. If a message is permanently undeliverable, qmail-send sends a single-bounce notice back to the message's envelope sender. The notice is From: bouncefrom@bouncehost, although its envelope sender is empty. Default: `me` If not supplied the literal name bouncehost, which is probably not what you want.
> concurrencylocal | Maximum number of simultaneous local delivery attempts. Default: 10 If 0, local deliveries will be put on hold. concurrencylocal is limited at compile time to 120 (unless conf-spawn if changed).
> concurrencyremote | Maximum number of simultaneous remote delivery attempts. Default: 20 If 0, remote deliveries will be put on hold. concurrencyremote is limited at compile time to 120 (unless conf-spawn if changed).
> doublebouncehost | Double-bounce host. Default: `me` If not supplied the literal name doublebouncehost, which is probably not what you want.
> doublebounceto | User to receive double-bounces. Default: postmaster If a single-bounce notice is permanently undeliverable, qmail-send sends a double-bounce notice to doublebounceto@doublebouncehost. (If that bounces, qmail-send gives up.)
> envnoathost | Presumed domain name for addresses without @ signs. Default: `me` If not supplied the literal name envnoathost, which is probably not what you want. If qmail-send sees an envelope recipient address without an @ sign, it appends @envnoathost.
> locals | List of domain names that the current host receives mail for, one per line. Default: `me` If not supplied qmail-send refuses to run. An address user@domain is considered local if domain is listed in locals.
> percenthack | List of domain names where the percent hack is applied. If domain is listed in percenthack, any address of the form user%fqdn@domain is rewritten as user@fqdn. user may contain %, so the percent hack may be applied repeatedly. qmail-send handles percenthack before locals.
> queuelifetime | Number of seconds a message can stay in the queue. Default: 604800 (one week) After this time expires, qmail-send will try the message once more, but it will treat any temporary delivery failures as permanent failures.
> > virtualdomains | List of virtual users or domains, one per line. A virtual user has the form user@domain:prepend, without any extra spaces. When qmail-send sees the recipient address user@domain, it converts it to prepend-user@domain and treats it as local. A virtual domain has the form domain:prepend. It applies to any recipient address at domain. For example, if nowhere.mil:joe-foo is in virtualdomains, and a message arrives for info@nowhere.mil, qmail-send will rewrite the recipient address as joe-foo-info@nowhere.mil and deliver the message locally. virtualdomains may contain wildcards:
> >     .fax:uucp-fax:alias-catchall.nowhere.mil:joe-foo-host
> virtualdomains may also contain exceptions: an empty prepend means that domain is not a virtual domain. qmail-send handles virtualdomains after locals: if a domain is listed in locals, virtualdomains does not apply.

> qmail-inject

> qmail-inject reads a mail message from its standard input, adds appropriate information to the message header, and invokes qmail-queue to send the message to one or more recipients.

> qmail-inject options
> -a | Send the message to all addresses given as recip arguments; do not use header recipient addresses.
> -h | Send the message to all header recipient addresses. For non-forwarded messages, this means the addresses listed under To, Cc, Bcc, Apparently-To. For forwarded messages, this means the addresses listed under Resent-To, Resent-Cc, Resent-Bcc. Do not use any recip arguments.
> -A | (Default.) Send the message to all addresses given as recip arguments. If no recip arguments are supplied, send the message to all header recipient addresses.
> -H | Send the message to all header recipient addresses, and to all addresses given as recip arguments.
> -f`sender` | Pass sender to qmail-queue as the envelope sender address. This overrides Return-Path and all environment variables.
> -N | (Default.) Feed the resulting message to qmail-queue.
> -n | Print the message rather than feeding it to qmail-queue.
> qmail-inject control files
> defaultdomain | Default domain name. Default: `me` If not supplied the literal name defaultdomain, which is probably not what you want. qmail-inject adds this name to any host name without dots, including defaulthost if defaulthost does not have dots. (Exception: see plusdomain.) The QMAILDEFAULTDOMAIN environment variable overrides defaultdomain.
> defaulthost | Default host name. Default: `me` If not supplied the literal name defaulthost, which is probably not what you want. qmail-inject adds this name to any address without a host name. defaulthost need not be the current host's name. For example, you may prefer that outgoing mail show just your domain name. The QMAILDEFAULTHOST environment variable overrides defaulthost.
> idhost | Host name for Message-IDs. Default: `me` If not supplied the literal name idhost, which is certainly not what you want. idhost need not be the current host's name. For example, you may prefer to use fake host names in Message-IDs. However, idhost must be a fully-qualified name within your domain, and each host in your domain should use a different idhost. The QMAILIDHOST environment variable overrides idhost.
> plusdomain | Plus domain name. Default: `me` If not supplied the literal name plusdomain, which is probably not what you want. qmail-inject adds this name to any host name that ends with a plus sign, including defaulthost if defaulthost ends with a plus sign. If a host name does not have dots but ends with a plus sign, qmail-inject uses plusdomain, not defaultdomain. The QMAILPLUSDOMAIN environment variable overrides plusdomain.

> qmail-remote

> qmail-remote reads a mail message from its input and sends the message to one or more recipients at a remote host.

> The remote host is qmail-remote's first argument, host. qmail-remote sends the message to host, or to a mail exchanger for host listed in the Domain Name System, via the Simple Mail Transfer Protocol (SMTP). host can be either a fully-qualified domain name:

> > silverton.berkeley.edu

> or an IP address enclosed in brackets:

> > [128.32.183.163]

> The envelope recipient addresses are listed as recip arguments to qmail-remote. The envelope sender address is listed as sender.

> qmail-remote control files
> helohost | Current host name, for use solely in saying hello to the remote SMTP server. Default: `me` If not supplied qmail-remote refuses to run.
> > smtproutes | Artificial SMTP routes. Each route has the form domain:relay, without any extra spaces. If domain matches host, qmail-remote will connect to relay, as if host had relay as its only MX. (It will also avoid doing any CNAME lookups on recip.) host may include a colon and a port number to use instead of the normal SMTP port, 25: inside.af.mil:firewall.af.mil:26 relay may be empty; this tells qmail-remote to look up MX records as usual. smtproutes may include wildcards:
> >     .af.mil::heaven.af.mil
> Here any address ending with .af.mil (but not af.mil itself) is routed by its MX records; any other address is artificially routed to heaven.af.mil. The qmail system does not protect you if you create an artificial mail loop between machines. However, you are always safe using smtproutes if you do not accept mail from the network.
> timeoutconnect | Number of seconds qmail-remote will wait for the remote SMTP server to accept a connection. Default: 60 The kernel normally imposes a 75-second upper limit.
> timeoutremote | Number of seconds qmail-remote will wait for each response from the remote SMTP server. Default: 1200

> qmail-remote returns a number of report strings, 0 terminated, and started by a code letter, as follows:

> Code letter | Type of report | Meaning
> --- | --- | ---
> r | Recipient | Acceptance
> h | Recipient | Permanent rejection
> s | Recipient | Temporary rejection
> K | Message | Success, destination host has taken responsibility for delivering the mail to the recipients
> Z | Message | Temporary failure
> D | Message | Permanent failure

> qmail-qmqpc

> qmail-qmqpc offers the same interface as qmail-queue, but it gives the message to a QMQP server instead of storing it locally.

> qmail-qmqpc control files
> qmqpservers | IP addresses of QMQP servers, one address per line. qmail-qmqpc will try each address in turn until it establishes a QMQP connection or runs out of addresses.

> qmail-smtpd

> qmail-smtpd receives mail messages via the Simple Mail Transfer Protocol (SMTP) and invokes qmail-queue to deposit them into the outgoing queue. qmail-smtpd must be supplied several environment variables; see tcp-environ(5).

> qmail-smtpd is responsible for counting hops. It rejects any message with 100 or more Received or Delivered-To header fields.

> qmail-smtpd supports ESMTP, including the 8BITMIME and PIPELINING options.

> qmail-smtpd control files
> badmailfrom | Unacceptable envelope sender addresses. qmail-smtpd will reject every recipient address for a message if the envelope sender address is listed in badmailfrom. A line in badmailfrom may be of the form @host, meaning every address at host.
> databytes | Maximum number of bytes allowed in a message, or 0 for no limit. Default: 0 If a message exceeds this limit, qmail-smtpd returns a permanent error code to the client; in contrast, if the disk is full or qmail-smtpd hits a resource limit, qmail-smtpd returns a temporary error code. databytes counts bytes as stored on disk, not as transmitted through the network. It does not count the qmail-smtpd Received line, the qmail-queue Received line, or the envelope. If the environment variable DATABYTES is set, it overrides databytes.
> localiphost | Replacement host name for local IP addresses. Default: `me` qmail-smtpd is responsible for recognizing dotted-decimal addresses for the current host. When it sees a recipient address of the form box@[d.d.d.d], where d.d.d.d is a local IP address, it replaces [d.d.d.d] with localiphost. This is done before rcpthosts.
> morercpthosts | Extra allowed RCPT domains. If rcpthosts and morercpthosts both exist, morercpthosts is effectively appended to rcpthosts. You must run qmail-newmrh whenever morercpthosts changes. Rule of thumb for large sites: Put your 50 most commonly used domains into rcpthosts, and the rest into morercpthosts.
> > rcpthosts | Allowed RCPT domains. If rcpthosts is supplied, qmail-smtpd will reject any envelope recipient address with a domain not listed in rcpthosts. Exception: If the environment variable RELAYCLIENT is set, qmail-smtpd will ignore rcpthosts, and will append the value of RELAYCLIENT to each incoming recipient address. rcpthosts may include wildcards:
> >     heaven.af.mil.heaven.af.mil
> Envelope recipient addresses without @ signs are always allowed through.
> smtpgreeting | SMTP greeting message. Default: `me` If not supplied qmail-smtpd will refuse to run. The first word of smtpgreeting should be the current host's name.
> timeoutsmtpd | Number of seconds qmail-smtpd will wait for each new buffer of data from the remote SMTP client. Default: 1200

Links | top

> qmail related links

> - Author's home page
> - Qmail home page
> - The qmail newbie's guide to relaying
> - Life with qmail

Last update: Wed, 2 Nov 2005 10:16:21 GMT | top