Once upon a time, I was totally going to write a phat (and fat) HOWTO explaining the myriad details of my elegantly functional mail server; and one day, the draft may yet be sufficiently polished to publish. In the meantime, I've added a pleasing new bit of functionality worth posting about.

qmail hasn't been updated in years, and to some extent it shows. Its overall design remain impressively secure and powerful (and has influenced the design of Postfix and Sendmail X). Remarkably expressive and adaptable, too. But some of the ways in which the Internet has changed since 1998 have outflanked qmail's flexibility. Its native facilities for filtering unwanted mail, for instance, were designed at a time when spam was relatively rare and uncreative. And the way people use mail servers these days makes encrypted authentication a must — but qmail knows nothing of SMTP AUTH.

In the absence of officially blessed updates, up has sprung a cottage industry of third-party qmail patches. Some are of general utility, some esoteric; some are of high quality, some dubious. In my experience, very little patching is necessary or advisable. The popular TLS and SMTP AUTH patches offend my minimalist sensibility: they're large, not terribly easy to read, and cause qmail to be linked with OpenSSL, itself not the most trustworthy code. The UCSPI-TLS approach looks rather more elegant, but still requires some patching. So when I needed a secure way to send mail through my server, I looked elsewhere, and found TMDA.

TMDA began life as a challenge-response tool, but it's grown to be many things to many people. Thus far, I use it exclusively as an ofmipd which supports SMTP AUTH. Using tmda-ofmipd and stunnel, my server has been providing old-style SSL-wrapped SMTP on port 465 for several years. How this works:

  1. /usr/local/bin/create-tmda-key-if-needed is called from /etc/profile and /etc/csh.login and says
    • #!/bin/sh
    • [ -f ~/.tmda/crypt_key ] && exit 0
    • mkdir -p ~/.tmda && tmda-keygen -b > ~/.tmda/crypt_key && chmod 600 ~/.tmda/crypt_key
  2. /etc/services says
    • smtps 465/tcp # SSL-wrapped SMTP
    • tofmipd 8025/tcp # TMDA ofmipd
  3. /etc/tmda/tmdarc says
    • ACTION_OUTGOING = "bare"
    • MAIL_TRANSFER_AGENT = "qmail"
  4. tmda-ofmipd starts at boot and binds to localhost on port 8025
  5. /etc/stunnel/stunnel.conf says
    • cert = /etc/openssl/certs/mycert.pem
    • key = /etc/openssl/private/mycert.key
    • debug = mail.info
    • setuid = tofmipd
    • setgid = tofmipd
    • pid =
    • [smtps]
    • accept = smtps
    • connect = localhost:tofmipd
  6. stunnel starts at boot and binds to all addresses on port 465

This has always worked reliably with Thunderbird, Mail.app, mutt, you name it. My Treo with VersaMail, however, could never manage to send a message. Today I wanted to fix that. Assuming VersaMail needed a less antiquated SMTP encryption technique, I decided to modernize a bit, and provide TLS-enabled (and TLS-requiring) message submission on port 587.

I first tried TMDA's provided examples; they failed because stunnel dumped core. This turned out to be a bug in 4.15, so I updated the package to 4.20, and then TMDA's examples worked. They appeared unnecessarily complicated, though: tmda-ofmipd was spawned by stunnel was spawned by xinetd (I used tcpserver) via a pair of wrapper scripts and a separate stunnel config file. I already have stunnel and tmda-ofmipd configured and running, I thought. Surely I can do this more elegantly? A few minutes later, I figured out how. Append these lines to stunnel.conf:

[submission]
accept = submission
connect = localhost:tofmipd
protocol = smtp

Restart stunnel. That's it. Using no additional resources, I now have authenticated and TLS-encrypted SMTP submission on port 587. SMTPS on port 465 still works — and there's no reason to turn it off — so clients can migrate at their leisure.

Satisfied with myself, I migrated my Treo. VersaMail gives a different error message now.