Wan’t to pop off a quick e-mail on your laptop? Are you on a
train, in a hotel, at a customer site, or at home? Depending on your location,
you may want to use a distinct smart host for getting your e-mail off your
device. Improving on an answer I gave on the Exim mailing-list the other
day, I’d say a good solution to routing messages from a mobile device (in my
case an Apple Mac Book Pro) is by using a queryprogram router.
As the documentation states, a queryprogram router
routes an address by running an external command and acting on its output. This is an expensive way to route, and is intended mainly for use in lightly- loaded systems
The word expensive refers to the “cost” of launching an external program, capuring and interpreting its output, but this “cost” is negligeable on a laptop because
- modern systems have power enough anyway, and
- the volume of mail sent from such devices is typically quite low.
The queryprogram router is very easy to describe in the Exim configuration file. I put mine quite far up on the list of routers, where I’d typically configure a smart host router:
mobile_supersmart:
driver = queryprogram
domains = !+local_domains
command = /usr/exim/where-to '$local_part' '$domain'
command_user = exim
When Exim evaluates this router, it runs the specified program /usr/exim
/where-to
, passing it the local-part (i.e. the bit before the @
character)
and the domain portion of the e-mail address.
The program invoked by the queryprogram router must return a single line of
text, which begins with ACCEPT
, DEFER
, FAIL
, or any of the other
keywords allowed. (Read the documentation.)
So, for example, if the where-to
program returns a line containing the
single word
DEFER
Exim will defer the message – it will queue it and attempt to route it at a later time. (This keyword can be followed by an arbitrary text which is logged.)
If, on the other hand, Exim sees the line
ACCEPT TRANSPORT=remote_smtp HOSTS=192.168.1.20
it accepts the message for transport, passing it to the specified transport
remote_smtp
using the specified list of hosts, which in this case, is a
literal IP address.
Another example line that can be returned by the where-to
program used in
the queryprogram router is:
ACCEPT TRANSPORT=smtp_auth HOSTS=smtp.gmail.com/MX LOOKUP=bydns
Here I return a different transport (one that uses outgoing SMTP AUTH for the
target host) and I specify the HOSTS
to be looked up in the DNS.
All this – and more – is part of a normal Exim installation if you have built it with
ROUTER_QUERYPROGRAM=yes
Let me now give you an example for the where-to
program. I’m using a shell
script to make it as simple as possible. The script will determine what
“state” my laptop is in:
- Am I connected to the Internet so I can use my default MTA for relaying messages?
- Am I at a customer’s site and must use their gateway with SMTP AUTH?
- Am I connected wirelessly?
- Am I on my home network so I can use my SOHO MTA?
Depending on your infrastructure and environment, you may have to tweak how you go about deciding “where you are”.
#!/bin/sh
LOCALPART="$1"
DOMAIN="$2"
DEFERMSG="Don't know how to get there from here; deferring"
TRANSPORT="remote_smtp" # default transport
myhost="`hostname`"
function defer() {
echo "DEFER ${*:-$DEFERMSG}"
exit
}
#myhost=x9001.megacorp.biz
#myhost=jmbp.mens.de
#myhost=z
case "${myhost}" in
jmbp.local)
defer "I'm offline";;
jmbp.mens.de)
HOSTS="192.168.1.20";; # At home
x9001.megacorp.biz) # At Cust
TRANSPORT=smtp_auth;
HOSTS="megacorp.biz/MX LOOKUP=bydns";;
esac
# If transport and hosts is set, accept the message
if [ -n "$TRANSPORT" -a -n "$HOSTS" ]; then
echo "ACCEPT TRANSPORT=${TRANSPORT} HOSTS=${HOSTS}"
else
defer
fi
In the example above, I’m checking the value of hostname
only because that’s
enough for me, but you can use whatever is best for you. I don’t use
$LOCALPART
nor $DOMAIN
either, but you could to determine whether you
should defer or route depending on the target domain; this could be used to
avoid sending bulk messages to your account when you’re connected over and
expensive Internet connection (e.g. UMTS).
Exim: that’s all.