Applescripting Mail.app

Applescript support for Apple’s own applications has typically been absent or poorly implemented. Leopard’s Mail.app is no exception, which is a pity because there are many nice things that a functioning scripting interface could perform. In this post, I’ll expound a couple of irritating bugs I have quickly run into while trying to write Applescripts for Mail.app; I’ll finish up with a useful Applescript that actually works and that I frequently use.

Bug the first

This one’s easy to sum up: get the properties of just doesn’t work. This works fine:

tell application "Mail"
    get the front message viewer
end tell

The usual way I write Applescripts is to just bung in a the properties of after the get to receive a nice list of, well, properties that I can extract and set for the object. Sure, I can get this sort of information (in the abstract) from the documentation, but querying the object with Applescript is easier and much more useful for debugging purposes. Alas, Mail does not support this, despite claiming to be able to:

properties inherited from item [snip] properties (record) : All of the object’s properties.

Here’s an example of the fail:

tell application "Mail"
    get the properties of (the front message viewer)
end tell

Update: this is Bug ID# 5981534.

Bug the second

I find Mail’s “Inbox” to be largely useless, because I filter much of my mail into sub-mailboxes as it arrives. Only unfiltered Mail is shown in the Inbox, which isn’t very helpful when there’s no “jump to next unread message in any mailbox” feature.

To work around this perceived problem, I have a “Smart Mailbox” to collect all Mail that needs my attention:


The “Message is in Sent” is so that I file/delete my own messages rather than let my Sent mailbox accumulate to thousands and thousands of emails.

Now, I really like Mail.app’s ⌘1 shortcut to select the “Inbox” mailbox. But since I don’t use the Inbox, I’d much rather it select my “Attention!” mailbox instead. This is the perfect case for Applescript, and should be a one-liner:

tell application "Mail"
    set the selected mailboxes of the front message viewer to {mailbox "xxx" of application "Mail"}
end tell

where xxx is the name of the mailbox. Well, sure, that works fine for a regular old static mailbox. But for a smart mailbox? Not a chance.

tell application "Mail"
    get the selected mailboxes of the front message viewer
end tell

With a selected Smart Mailbox the result is {application "Mail"}, and trying to set the selected mailboxes to a Smart Mailbox just gives an unhelpful error. Not very helpful at all, in the end.

Update: this is Bug ID#5981547.

Bug the third

This bug is less major because it can be obviated by using GUI scripting. I’m not really a fan of GUI scripting, though. Not very elegant (says the Applescript user).

Anyway, I’d like to be able to customise the template used to construct “Reply” emails (as you could in Mac OS X 10.2 or so by tweaking some hidden system files); specifically, I find the line

On 02/04/2008, at 9:13 PM, Will Robertson wrote:

terribly verbose and overly detailed. There’s a couple of other things that could be improved, too (cf. this year-old post by John Gruber in a similar vein; by the way, I’m a staunch bottom-posting advocate — although I prefer a top poster than a bottom poster who doesn’t snip).

The main problem is that Mail’s reply Applescript command has buggy side-effects:

tell application "Mail"
    set sel to the selected messages of the front message viewer
    set repl to reply (first item of sel)
    set repl_contents to the content of repl
end tell

Two reply windows are opened, only one of which is the actual reply. More often as not, the message repl is the other one, which is simply an empty Mail message. To add insult to injury, the empty reply requires a save/discard confirmation when the window is closed, whereas the actual reply lets you close its window (and destroy its content) with nary a warning in sight.

Finally, adding to reply the boolean without opening window doesn’t do what it claims.

I’ll probably adapt Gruber’s script, in the end, to do what I want. But this stuff is supposed to be quick and easy — and it’s not.

Update: this seems to have been fixed in Mac OS X 10.5.3; it's necessary to call `reply (first item of sel) with opening window` to get the reply window to appear.

A nice script I use

Okay, I don’t want to complain too much — when it works, Applescript can make life much easier and I bug report because I care. Now I’d like to share a script, Next-message.scpt, that I use many times in Mail on a daily basis (with the help of FastScripts to assign it the convenient keyboard shortcut ⌘\ ).

This script exists to make it easy to jump to the next message when you’re not using Mail’s three-paned interface (I greatly prefer having to open the message in a new window). To quote from the blurb at the top of the script:

This script is designed to open the next message in a thread when Mail is used in two-paned mode. To elucidate the problem, when viewing messages in the third pane below the mailbox list of messages, the space bar does a great job of jumping to the next unread message. When the message pane is hidden and messages are opened in their own window to be viewed, there’s no way to get to the next message without switching to the message list, selecting the next message, and opening it. This script automates this process, closing the original message and placing the next message in a window of the same size, in the same location.

The script currently does not detect if the next message is part of the same thread as the current. In fact, I don’t think it’s possible within Applescript to detect that (especially as their subjects will not necessarily be the same). Besides, sometimes you want to jump to the next message even if it’s not in the same thread as the one you’re reading.

As soon as I can I’ll write these up formally for Apple’s bug reporter. I needed to get them off my chest before doing that, however.

In closing, I really appreciate the power that Applescript can give, especially for cross–application tasks that would be otherwise impossible to achieve. For example, running a script in TeXShop to highlight uncited references in BibDesk.

I’m happy to see even lacklustre support despite the frustrations when it doesn’t work; I hope that, over time, Applescript support improves for all Mac OS X applications.