Automatically update SMTP servers depending on the network location

published on November 28, 2008

It has bothered me since day one at university that I can only use the university’s SMTP server. I got by, by just letting sent messages fail, because then I’d get a pop-up which would let me pick another SMTP server. This was of course far from perfect: sometimes I thought a message was sent while it really wasn’t … so it would sit in my outbox for a day.

Possible solutions

The only real solution is for the university’s network to be improved: they should find a way to limit network traffic and abuse in ways that don’t affect the user so severely. (On the bright side: the wireless network was incredibly unreliable the first 2 years but is superb since this year!)
Until that happy day, I needed an interim solution. The best solution would involve an SSH tunnel to keep using the correct SMTP server. It also requires you to have a server somewhere with SSH access. I don’t want to maintain that too, so I chose for a simpler solution.

My solution

I wrote a PHP script (Mac OS X only, sorry Windows/Linux users) that will change the SMTP servers of your e-mail accounts depending on the SSID of the wireless network you’re currently connected to. This is sufficient in my case, but it could easily be extended to also change the default printer or change your “network location” (each “network location” in Mac OS X can have its own per-network interface settings).
Whenever your network settings change, this script will run (thanks to launchd). This means it will work completely transparently.
I found the crucial parts in this similar tutorial. I think my code is much easier to understand and adapt, not in the least because mine isn’t written in Perl.

First, the actual script: download it below and update it to suit your needs. The part you’ll want to update is this one:

//----------------------------------------------------------------------------
// Configuration. You should update this.


// Default location.
$locations[FALLBACK] = array(
  SMTP => array(
    'private' => 'smtp.gmail.com:private@example.com',
    'work' => 'smtp.gmail.com:work@example.com',
  ),
);

// UHasselt.
$uh_smtp = 'student.uhasselt.be:0623800';
$locations['UH'] = array(
  SSID => 'UHasselt-Public',
  SMTP => array(
    'mail' => $uh_smtp,
    'work' => $uh_smtp,
  ),
);

Obviously, you can update the configuration to as many accounts as you want.
The SMTP server identifier is of the format <server>:<username>. Now put this in ~/scripts/ (or wherever you store your scripts) and chmod +x it to make it executable. Then test it: ~/scripts/locationchanger. In case your PHP interpreter cannot be found, use type -a php to find out its location and update this in the first line of the script.

Finally we want this script to run automatically whenever our network environment changes. This is possible through the power of launchd’s watchpaths:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN"
    "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>wimleers.com.locationchanger</string>
    <key>ProgramArguments</key>
    <array>
        <string>/Users/wimleers/scripts/locationchanger</string>
    </array>
    <key>WatchPaths</key>
    <array>
        <string>/Library/Preferences/SystemConfiguration</string>
    </array>
 </dict>
</plist>

You’ll want to put this file (can also be downloaded below) in ~/Library/LaunchAgents. To make it work, either reboot or use launchctl load ~/Library/LaunchAgents/LocationChanger.plist

I hope this proves useful to some people that share the same frustrations. If you’ve made improvements to the script, let me know in the comments or through pingbacks so I can update this post!