Part IV in an apparently ongoing series, “Nifty and Minimally Invasive qmail Tricks.”

In a previous post I tweaked my server in the hopes of getting my Treo to send mail through it, but was thwarted by VersaMail's poor support for encrypted SMTP authentication. At the time, the attempt was just for fun. In a matter of days, however, I'll actually have a data service plan. It's time to try harder.

My server accepts incoming mail destined for the domains it's responsible for, and sends outgoing mail from authorized local users. I now want to be able to send outgoing mail from wherever I am, without being an authorized local user, while not making my server an open relay. Sounds impossible, right?

Happily, it's a solved problem, because this was once a common state of affairs. Five years ago, mail client software that supported SMTP AUTH was the exception, not the rule. ISPs took care of their home- and office-bound users by selectively relaying for hosts in the ISP's netblock. For roaming users, who could be connecting from anywhere on the Internet, the ISP temporarily noted the IP address from which a user checked his mail, then allowed relaying from that IP for a little while. (Not too long, though, to keep spammers from jumping all over it.) This “POP-before-SMTP” technique had the advantage of working with all existing mail software, as long as users remembered to check before sending. Since I had roaming users, I enabled it on my server (where it was actually IMAP-before-SMTP). It worked well.

SMTP AUTH has the advantage of not requiring people to change their behavior, and nowadays enjoys ubiquitous client support. I've been happily using SMTP AUTH exclusively for a few years now. Thanks to VersaMail, however, it's time to turn back the clock and add IMAP-before-SMTP to the mix.

The software I used before — and am now using again — is relay-ctrl. It's in pkgsrc as of a few minutes ago. It's designed to fit in qmail-like command chains and consists of a few small programs. The most important: relay-ctrl-allow runs after a successful POP/IMAP login, recording the client IP and timestamp; relay-ctrl-check runs before the SMTP server, enabling relaying if the client IP has authenticated recently. It sounds simple, and once you figure out how to hook the programs into your existing services, it is. I'll save you the trouble.

relay-ctrl's documentation doesn't mention Dovecot, because relay-ctrl was last updated in April 2002, and Dovecot first appeared a few months later. But relay-ctrl doesn't need much from the POP/IMAP side of things, just a particular environment variable and the ability to insert a command somewhere. Dovecot provides the latter, and a close approximation of the former, which this dovecot-settcpremoteip script (included in pkgsrc) mitigates:

#!/bin/sh
#
# Wrapper for relay-ctrl-allow that sets TCPREMOTEIP.
TCPREMOTEIP="${IP}"; export TCPREMOTEIP
exec "$@"

Edit /etc/dovecot.conf thus (yes, this is a long line):

mail_executable: /usr/bin/env RELAY_CTRL_DIR=/var/spool/relay-ctrl/allow /usr/pkg/bin/relay-ctrl-chdir /usr/pkg/bin/dovecot-settcpremoteip /usr/pkg/bin/relay-ctrl-allow /usr/pkg/libexec/dovecot/imap

Edit /etc/rc.conf thus (if you already have any of these variables set, merge in these values):

qmailsmtpd_postenv="RELAY_CTRL_DIR=/var/spool/relay-ctrl/allow"
qmailsmtpd_pretcpserver="/usr/pkg/bin/relay-ctrl-chdir"
qmailsmtpd_presmtpd="/usr/pkg/bin/relay-ctrl-check /usr/pkg/bin/ifrelayclient /usr/bin/env RBLSMTPD='' --"

ifrelayclient is a script (also included in pkgsrc) which runs the first command only if RELAYCLIENT is set, running the remaining commands regardless. It expects the first command to end with --. This is useful because it lets us hack around the fact that we're abusing regular SMTP on port 25 for mail relaying. For instance, setting an empty RBLSMTPD in the environment prevents rblsmtpd from looking up or blocking an “authenticated” user. If you have other programs wrapping qmail-smtpd, you can mollify them from ifrelayclient as well. In my command chain I also have greetdelay, for which I set an empty GREETDELAY here, and qgreylist, which is already smart enough to short-circuit when RELAYCLIENT is set — which is exactly what relay-ctrl does.

Restart Dovecot and qmail-smtpd. Open your IMAP client. You should see a new mode 666 file with your IP address in /var/spool/relay-ctrl/allow, and no errors in the mail logs. If so, then you should be able to send a message to anyone, anywhere, through your server on port 25.

Update: My Treo 680 arrived today along with data service. Its newer VersaMail still doesn't support STARTTLS, but they fixed SMTP-over-SSL, which is exactly what I've already been using for years. In other words, instead of putting forth any effort whatsoever, I could have just… waited. The Great Orchestrator sure has a sense of humor.