qmail

qmail is a toolkit of Unixy programs that can be composed to provide email services. I use it to run my own mail server, and have for a very long time. Sometimes I write about it.

The last version by qmail’s author was in 1998, who released the code into the public domain in 2007. The last community-based netqmail update was also in 2007. It’s safe to say there’s no longer a meaningful upstream. Unmaintained though it is, in 2017 I continue to find that

  1. qmail has remarkable design integrity, and
  2. This confers practical benefits.

Packages

I almost always install qmail from pkgsrc, because it’s packaged according to my taste and offers useful build-time options. A few of the qmail-related pkgsrc packages I’m responsible for:

  • ?daemontools and ?daemontools-run
  • ?djbdns and ?djbdns-run
  • ?qmail and qmail-run

(Here’s the complete list of packages I maintain.)

Patches

acceptutils Offer SMTP AUTH without patch conflicts and with new per-user functionality.
destdir Build as non-root, without hardcoded IDs, to a staging area.
mess822qmailqueue Apply Bruce Guenter’s QMAILQUEUE patch to mess822.
pymsgauth Tag outgoing messages with Charles Cazabon’s pymsgauth using a Unix filter rather than a sendmail wrapper.
qbiffutmpx Detect <utmpx.h> in case the OS no longer provides <utmp.h>.
qfiltergrandparent Correlate qmail-qfilter(1) filters with qmail-smtpd or ofmipd sessions.
remote Wrap qmail-remote with another program (inspired by QMAILQUEUE).
rcptcheck Apply Jay Soffian’s RCPTCHECK patch atop netqmail 1.06 with the TLS + SMTP AUTH combo patch.
rejectutils Reject messages at SMTP according to multiple criteria without patch conflicts.

My approach

If there were a community actively collaborating on a single qmail-derived codebase, I might want to join them. Instead we have a few folks maintaining their own separate forks, none of which feels quite right to me to run in production (or, therefore, to use as a basis for further development).

I’d rather not maintain yet another fork. I prefer to publish purpose-specific patches that hitch a ride via an existing seam in the system, adding small, self-contained code that can be enabled and/or configured at runtime.

When I don’t have to modify qmail to solve my problem elegantly, I don’t. When I do have to modify qmail, I add the simplest new interface that permits the problem to be solved. Then I write small, self-contained, runtime-configurable code to the new interface.

Pretending I’m a maintainer helps me to undertake changes only in response to practical needs qmail doesn’t yet elegantly meet, and then to design those changes to extend qmail’s integrity. I expect, with periodic small doses of careful incremental effort, that qmail’s utility can remain high for me indefinitely.

If any of my efforts are also useful to you, so much the better!

Wishlist

I think qmail would be more useful and/or more like itself if it were augmented in the following ways. I’d be happy to be beaten to the punch implementing any of these.

Submission filters

(These filters would depend on acceptutils, rejectutils, and an ofmipd with nothing but the QMAILQUEUE patch.)

I’d put pymsgauth-tag in control/ofmipfilters. Each submitted message would then be tagged by the authenticated user, so pymsgauth-confirm in that user’s .qmail file would work as designed.

qmail-qfilter-gpgsign would connect to the current user’s gpg-agent to sign a message. I might put it in control/ofmipfilters.

Outbound filters

qmail-rfilter would be to qmail-remote as qmail-qfilter(1) is to qmail-queue(8): an easy way to run filters on outbound messages.

qmail-rfilter-remote would be to qmail-remote as qmail-qfilter-smtpd-queue is to qmail-queue: a wrapper that runs the sequence of filters in control/remotefilters before calling the real qmail-remote. With the QMAILREMOTE patch, I’d use qmail-rfilter-remote by setting QMAILREMOTE in qmail-start(8)’s environment.

qmail-rfilter-dkimsign would be a filter that signs messages with DKIM. I’d list it (last) in control/remotefilters.

qmail-rfilter-srsforward would be a filter that SRS-rewrites envelope senders. I’d list it in control/remotefilters.

Inbound filters

qmail-qfilter-dkimverify would be a filter that verifies DKIM signatures. I’d list it (first) in control/smtpfilters (where qmail-qfilter-smtpd-queue will run it, because I set that as QMAILQUEUE in qmail-smtpd’s environment).

qmail-qfilter-srsreverse would be a filter that SRS-unwraps envelope senders. I’d list it in control/smtpfilters.

qmail-qfilter-headerchecks would be a filter that checks headers in the Postfix style, against a list of regexes in control/headerchecks. I’d list it in control/smtpfilters.

qmail-qfilter-{mimeheaderchecks,nestedheaderchecks,bodychecks} would round out the Postfix-style filters.

qmail-qfilter-milters would be a filter that runs the sequence of milters in control/milters.

Recipient checks

qmail-rcptcheck-cvm would be a RCPTCHECK-compatible program that verifies recipients using Bruce Guenter’s cvm-qmail.

qmail-rcptcheck-greylist would be a RCPTCHECK-compatible greylisting implementation that tracks state using empty files in the filesystem. I’d list it (last) in control/rcptchecks.

qmail-rcptcheck-spamdyke would be a RCPTCHECK-compatible program that verifies recipients using Sam Clippinger’s spamdyke-qrv.