EximWan'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.

Flattr this
Mail, Exim, Linux, Mobile, MacOSX, CLI, queryprogram, and location :: 03 Sep 2009 :: e-mail

Comments

blog comments powered by Disqus