» Remotely controlling a Mac at home: e-mail style!

Wouldn’t it be great if you could restart your Mac at home or find its IP address just by sending an e-mail?  I got the idea for this from Cory Bohon’s article at TUAW (read) written back in April on the same subject.  I liked the idea of being able to send a simple e-mail message and having my Mac mini do some task.  It’s a lot quicker than firing up a VNC or SSH session and doing it the long way.

First I would like to begin by explaining the problems I had that needed resolution:

  1. My Dyndns Dashboard widget is supposed to automatically update Dyndns with the public IP address at home where my Mac mini lives.  Sometimes (rarely [only once]) the widget will hang and Dyndns will not get my latest IP address resulting in 404 when I try to access the various sites running on the mini.
  2. I have an applescript application that will remotely update my Plex library as well as a cron job on the mini that will do the same thing locally.  Occasionally running this script, either remotely or as a cron job, will cause Plex to crash – no idea why.
  3. Sometimes I just need the blasted thing to restart.  It’s OS X, not God.

I’m going to go through these in order of the easiest to tackle to the most difficult.  Also, I’m only going to cover the scripts I created themselves, you can read Cory’s article for setting up the mail rules; he does a lot better job than I at explaining it.

Here is the script I used to call up Plex.  It’s incredibly simple and really speaks to the ease of Applescript.
tell application "Plex"
end tell

Yup, that’s it.  Simple, yet powerful.  All I have to do is send off an email and boom Plex launches.  Definitely quicker than loading up VNC and doing it through the GUI remotely.  This is especially true given that VNC is somewhat bandwidth heavy and can be slow to respond if the client or server have a lot of network traffic with which to compete.

The article I referenced above has a script for restarting a remote Mac; however, things can go haywire if you have an app that won’t quit.  Some people commented on Cory’s article and mentioned his script would not work if Safari was open with multiple tabs, and they are correct.  In my case I have Transmission running and it wants the user to confirm a “quit” before complying.  I had to find a way around that as it was preventing the script from being useful.  Without further adieu here is the script:
set pwd to "YourPassw0rd"
set cmd to "shutdown -r NOW"
do shell script cmd password pwd with administrator privileges

Pretty cool, only three lines for this piece of magic.  The first line creates a variable “pwd” for storing your password.  This is necessary because OS X only allows a user with administrative privileges to run the shutdown command.  The next line creates a veriable “cmd” that stores the Termainal (UNIX shell) script we will run in line 3.  If you open up Terminal.app and type in “shutdown -r NOW” you will be told the command cannot complete because you aren’t a super user (sorry mate).  Luckily, though, in the terminal you can append “sudo” to the beginning of the shutdown command to run it as an administrator.  The result is that the shutdown command will reboot (-r flag) the Mac at a specified time (NOW).  For information on sudo and shutdown check out here and here, respectively.  The last line is a whirlwind of coding genius; actually, not really.  It basically runs “sudo shutdown -r NOW” and passes in the password we used on the first line.  Thanks go to Cory for helping me to figure out passing in the password for another script I have.

The last problem, getting my IP address e-mailed back to me, was the hardest to figure out and is the “kludgiest” of the three.  The short version is that an Applescript calls another Applescript, fancy.  Actually, it’s Leopard’s fault; Mail 3 does not process mail rules with Applescripts the way it did previously in Tiger and earlier versions of OS X.  It used to be that the Applescript that gets called could actually reply to the message which triggered the rule; however, that is no longer the case and Mail limits what can and cannot be done in the Applescript.  Unfortunately, I don’t know what these limits are sufficed to say that what I need to do is not permitted.

OK, here we go; the Mail rule calls a script which looks like this:
do shell script "osascript /Users/Aron/Scripts/HomeIP.scpt"
That script says run the Applescript found at this location.  The script it calls, the one that gets the IP address and emails it, is here:
set cmd to "curl -s http://www.whatismyip.com/automation/n09230945.asp"
set my_ip to (do shell script cmd)
set my_dest to "youraddress@somedomain.com"
set my_subj to "My IP at home"

tell application "Mail"
GetURL ("mailto:" & my_dest & "?subject=" & my_subj & "&body=" & my_ip)
tell application "System Events" to keystroke "D" using command down
end tell

So this one is a little meatier, but if you’ve made it this far I would be remiss to not go further.  The first line is fairly obvious, it stores a Terminal command we’re going to use later; if you copy that command into the terminal and run it the output will be you current public IP address.  It atually took me awhile to find out whatismyip.com provided that neat little service.  Before I finished the script I was using a combination of sed and awk to format my curl output.  Anyways, my loss is your gain.  The next line takes the standard output from the command that we called “cmd” in line 1 and stores it as a variable called “my_ip”.  Next, we initialize and set two more variables – “my_dest” gets the e-mail address to which you want your IP address sent and “my_subj” stores the subject of e-mail which will be sent.  I could have used my_ip as the subject of the email, but for my purposes I prefer a pretty subject with the IP address in the body of the message.

The next part of this script launches Mail (if it is not already launched) and has it load a “mailto:” URL.  The URL gets dynamically created based on the variables we used above so the URL actually ends up looking like this:
"mailtoo:youraddress@somedomain.com?subject="My IP at home"&body=someIPaddress".
When Mail loads that URL it actually creates a new mail message with the properties (recipient, subject, body) we specified.  After that it uses Universal Access to automagically press “shift+command+D” to send the message we just created.

All in all, a pretty useful set of scripts if I do say so myself.  Hopefully someone will find this helpful to them.  If you know of a better way to make Mail send an e-mail any way other than my kludge-tastic Universal Access method feel free to let me know!