The qmail mail transport agent

Home : Linux resources : "Howto" : qmail


qmail is excellent; it's the only server I haven't had to upgrade to fix security issues, and I've been running it for more than four years now -- I first installed version 1.03 on 11-Feb-2000, and am still running the identical version (though I've had to recompile after upgrading the OS). qmail now claims to be the "second most popular MTA on the Internet", and I'm not surprised. Here is how to:
Find out what's currently waiting to be delivered
Run qmail-qread (as root). The output will look something like this:
       [root@rgrjr control]# qmail-qread 
       4 Nov 2002 18:17:55 GMT  #206850  1355  <somebody@rgrjr.dyndns.org>
	       remote	abuse@pubnet.ne.kr
       12 Nov 2002 15:02:58 GMT  #206852  1891  <nobody@rgrjr.dyndns.org>
	       remote	abuse@first.net.jo
       [root@rgrjr control]#
For each message in the queue, a summary line is printed, followed by a status line for each recipient. The summary line starts with the date the message entered the queue, followed by the message ID (preceded by a "#"), the message size in bytes, and the envelope sender. Each recipient line contains a status code, the keyword "local" or "remote", and the recipient address. In the example above, the status is blank because the message is still being delivered; if a message had already been delivered to other recipients, different codes would have appeared for those deliveries. In qmail, all deliveries are made independently, even when the same message has multiple recipients at the same destination server.
Find files in the queue
Do "find /var/qmail/queue -type f" to find all queued message files.
Force a bounce
To force a bounce, you need to make its "info" file older than the maximume queue lifetime (expressed in seconds in /var/qmail/control/queuelifetime, or 7 days if not present). For a message with id 206850, this can be done as follows:
       find /var/qmail/queue/info -name 206850 | xargs touch -d '8 days ago'
See also the "How do I rejuvenate a message?" FAQ item. (To "rejuvenate," just leave off the "-d '8 days ago'" part.)
Force redelivery attempts
Do "kill -ALRM" on the qmail-send process to force redelivery for all queued messages. Alternatively, "/etc/init.d/qmail redeliver" will do this for you. (See also the /root/bin/qmail-redeliver and /root/bin/qmail-restart scripts).
Restart after a network outage
Run qmail-tcpok to get qmail to reexamine its notion of which hosts are responding. -- rgr, 13-Mar-00.
Get around SPAM/relay blockers via smtproutes
When I get a bounce message that looks something like this:
    <abuse@morning.ru>:
    Connected to 195.161.98.12 but sender was rejected.
    Remote host said: 550 5.7.1 Mail from 66.31.124.111 rejected;
       see http://www.five-ten-sg.com/blackhole.php?Search=Search&ip=66.31.124.111
then it probably means that the recipient's ISP is blocking my IP address. In this particular case, Morning Network Ltd. of Krasnoyarsk, Russia has their MTA set up to query the 510 Software Group about whether it should allow connections from any given IP address; since they know that 66.31.0.0/16 is a Comcast residential customer IP netblock, they classify it as the equivalent to a dial-in line, and tell Morningstar to refuse. Rather than bother the 510 folks to have them stop blocking my IP (which is not really fixed in any case), I just added the following line to the /var/qmail/control/smtproutes file:
    morning.ru:smtp.comcast.net
This tells my machine to relay mail for the morning.ru domain through smtp.comcast.net (which will do this for me because I am a customer on their network). This indirect routing trick is becoming necessary for more and more ISPs as they get more sophisticated about blocking SPAM; someday I may have to route everything through Comcast, though that would force me to change /var/qmail/control/smtproutes whenever their servers are unavailable. Note that it is not necessary to restart the server after changing this file, as qmail-remote is forked anew for each remote delivery.
Limit the queue lifetime of bounce messages
Changing the /var/qmail/control/queuelifetime variable would affect the retry lifetime of all messages, which is undesirable. Instead, I use the following crontab entry, which runs twice a day, and only affects bounces:
    # Flush bounce messages older than two days.  These are invariably bounces
    # to fictitious return addresses for spam sent to retired or filtered
    # local addresses.  -- rgr, 13-Oct-03.
    10 0,12 * * *	find /var/qmail/queue/info -type f -mtime +2 -size 2c | xargs -r touch -d '8 days ago'
This finds all bounces ("-type f -size 2c") that are more than two days old ("-mtime +2") and applies the "Force a bounce" recipe from above to make it look like the messages are eight days old; these messages will be bounced the next time the system gets around to retrying them. Bounces will therefore only be retried for two to three days.
Record double-bounces
These are caused by bounces (usually spam addressed to invalid addresses) where the envelope return address is also invalid. I used to look at all of these myself, but that got to be too much trouble since the spam volume started to explode in 2003. I currently do the following:
  1. Define the "dev-null" address by putting something along the following lines into the /var/qmail/alias/.qmail-dev-null file:
        # The ultimate trash bin.  We must literally "cat" to /dev/null because
        # qmail reports failure if we try to write /dev/null as an mbox file, 
        # probably because it can't lock it exclusively.  -- rgr, 1-Oct-03.
        # | cat > /dev/null
        | echo `date '+%F-%T'` `grep -i '^From:' | fgrep -v 'MAILER-DAEMON@rgrjr.dyndns.org'` >> doublebounces.log
    
    It doesn't matter who owns this file, as long at it is world readable.
  2. Put the address "dev-null" in /var/qmail/control/doublebounceto.
This will cause the /var/qmail/alias/doublebounces.log to fill up with lines like this, one per bounce:
    2004-06-06-05:37:33 From: "Mark Forrest" <m_forrest_ad at hotmail.com>
    2004-06-06-05:37:32 From: "Mark Forrest" <m_forrest_ad at hotmail.com>
    2004-06-06-05:37:33 From: "Mark Forrest" <m_forrest_ad at hotmail.com>
    2004-06-06-06:21:10 From: "Russ" <s0ftwarre4allprocuring at care2.com>
    2004-06-06-06:54:07 From: Gina Smearsun <rogers-sns at myjalapi.com>
    2004-06-06-09:19:21 From: "Watches for you" <rcsmz at hotmail.com>
    2004-06-06-09:23:31 From: "Lauri Hernandez" <l.hernandezng at correo.de>
    2004-06-06-09:23:31 From: "Lauri Hernandez" <l.hernandezng at correo.de>
    2004-06-06-11:00:52 From: "Madrid" <zvtmlm at mail15.com>
    2004-06-06-11:11:09 From: Bob Rogers <rogers-netatalk@rgrjr.dyndns.org> From: "Wiley Converse" <KarlisHooke at collegebeat.com>
    2004-06-06-11:11:10 From: Bob Rogers <rogers-navel@rgrjr.dyndns.org> From: "Wiley Converse" <KarlisHooke at collegebeat.com>
    2004-06-06-11:11:10 From: Bob Rogers <rogers-ilisp@rgrjr.dyndns.org> From: "Wiley Converse" <KarlisHooke at collegebeat.com>
The last three are for confirmation messages from TMDA for incoming spam; TMDA makes them look like bounces (which in a way they are), so qmail double-bounces them when the return address fails. The "rogers-foo" addresses are ones I once used to subscribe to mailing lists; the spam was addressed to these, so they are used as the "From:" address for the confirmation message, and the other address is the original spam "From:" header in the quoted message. Note the duplicates sent at almost the same time to multiple addresses at my domain; this is characteristic of high-volume spammers.
Other qmail resources: See also:


Bob Rogers <rogers@rgrjr.dyndns.org>
$Id: qmail.html 102 2005-01-08 22:24:00Z rogers $