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