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.


iTunes customer service

One of the less tangible aspects of shopping online is the lack of any face-to-face contact in the inevitable case that something goes wrong. I haven’t had much experience with online shopping in general, but I have had a couple of things go wrong for me on iTunes. And I’m happy to report that, in Australia at least, their customer support is excellent.

My problems

The worst of my problems occurred quite some time ago when iTunes was periodically crashing on me. Not really sure how or why, and iTunes these days is fairly reliable, but back then it was rather a pain in the ass. Playing music over wireless was fraught with embarrassment (“aren’t Apple products supposed to just work?”), and buying music online a risky business. Once or twice, iTunes crashed midway through an iTunes download and a song or two from the purchased album was lost in the æther. (Usually this problem can be fixed with the Store > Check for Purchases… menu item — but not in this particular case.)

Another time, I simply bought the wrong album, due to the ridiculous setup where iTunes will often sell both an AU$18 basic album as well as an AU$22-ish album with music videos or live or bonus tracks — generally I buy the more expensive version, but in this case the link from the iTunes main page was for the basic version and I bought it before checking for the other.

Finally, just the other day I bought the “iTunes Live” Nick Cave and the Bad Seeds EP and found that the last track ended abruptly, mid-chorus, at 5:13. Clearly something had gone wrong with the encoding of this track, and the one review of that album mentioned the anomaly in rather negative terms.

Reporting those problems

In each case, the response from Apple was swift and appropriate. I had to look around for a little while before I worked out how to report a problem. Recently, Apple’s been sending email receipts on all purchases, and these emails make the “Report a Problem” links rather more prominent. Through iTunes, however, here’s how you do it. In your iTunes account, access your purchase history:


You can then select any of your purchases with the little circled arrows:


Thus, each item that passes through your iTunes account can be separately reported upon.

Apple’s response

As previously mentioned, I have been completely satisfied with Apple’s response for each of the small number of problems I’ve had over the last few years. After a very short interval and despite the very brief exchange of words on both sides, I’ve always received a full “refund” to fix the problem by re-downloading the content. (As you would expect considering the cost to them is negligible, and you get to keep what you originally purchased, so it’s more of a “credit” than a “refund”. Whatever.) Apple claims to reply within 24 hours, and I think that’s about right (the most recent one certainly was). It even only took them a couple of days to fix the clipped Nick Cave track, restoring the missing ninety-odd seconds.

To conclude, how they cope with failure is a pretty important measure of the customer service of a business. Any misstep could result in alienating their very customers, especially when the business is as faceless as the iTunes store. (I wonder if this sort of thing can be fixed in the bricks’n’mortar Apple Stores in the U.S.) Disregard for now the causes of the problems that I had, which could probably be blamed in various measures on iTunes itself — that’s a rant for another time. In my own experience, iTunes’ customer service is very satisfactory and reassures me against any further problems down the road.


Make (in)visible Applescripts

John Gruber’s latest fireball discusses invisibility in Mac OS X. He rightly comments that using the SetFile command line utility (which is bundled with the Developer Tools) is probably not that convenient when dealing with the visibility of items in the Finder.

For simple cases, however, I find the use of programs like “Super Get Info” to be overkill to an extent. Many years ago, I wrote two Applescripts for the exact purpose of using SetFile in a user-friendly way in the Finder.

The first, Make-invisible.scpt, is pretty simple; just select the items you want made invisible and run the script.

The second, Make-visible.scpt, obviously can’t be used by first selecting the invisible items! On run, it will display a list of currently invisible items in the frontmost folder window, from which you can select items to make visible.

To use these, you’ll want to use either the system-wide Applescript menu bar, Red Sweater Software’s FastScripts, Waffle Software’s ThisService, or something else again.

So, there it is.

One thing I just noticed is that the admin privileges no longer work;

do shell script … with administrator privileges

is failing with

Finder got an error: A privilege violation occurred.

Uh, isn’t that the sort of thing with administrator privileges is supposed to avoid? Oh well — I don’t have time to debug this (in my experience, Applescript support from Apple products tends to be a minefield of poorly tested functionality literally riddled with bugs) so if anyone can help with this I’d be greatly appreciative.

Update: this error comes about because the do shell script (with admin privileges) is situated inside the tell application "Finder" scope. Please find new versions of the scripts that fix this error in the links above.

Useless proposal #1

This is an idea that requires way too much engineering, but I wish it could happen: How cool would it be if Mac OS X had a concept of “subscribed RSS feeds”, so that no matter which browser or feedreader you used, viewing a site’s webpage would not offer you the “subscribe” link if you already were indeed subscribed to it.

At present this would require browsers parsing the formats of whichever feedreader the user was using, which is clearly a rather unscalable approach. If all feedreaders used a common format file (ahem, not OPML) then this would be a lot easier :)


Twitterrific notes

I’ve been using Twitterrific for a while now as my Twitter client. There’s no huge reason, really, that the web interface isn’t just fine, but a dedicated client is nice for a few reasons, such as: polling for updates, albeit bad for productivity; shortcuts for replying; a more compact interface; and so on.

I don’t have time to write extensively about any of my wish-list, so a bulleted list will have to do. Here are a few of features that, individually or together, could make Twitterrific even better:

  • Own posts are automatically marked as “read”.
  • “Favourited” tweets are indicated visually (or at the very least the action of favourite-ing them is indicated; I’ve got many favourite posts by mistake trying to hit CMD-2 to reply and missing).
  • Last read message is remembered so that relaunching Twitterrific doesn’t result in 40-odd unread tweets. (Alternatively, simply zero-ing the unread counter on launch.)
  • On that note, it would be even better if it could track back through the pages of unread tweets until it found where I was up to; currently when I wake up my ’puter in the morning there’ll be way more tweets that I’ve missed than Twitterrific gives me.
  • The input text box grows with my text rather than fixed to a certain height.
  • Less UI preferences. You guys are good designers! No need to ask us if the window should have a drop shadow or not.
  • Auto tinyurl (or snurl, or …) of pasted links.
  • Auto-expanding tinyurl-ed links.
  • Auto-completion of followers’ handles when manually typing replies to them (say there aren’t any of their actual tweets currently visible).
  • Perhaps: ability to un-follow people.

Now, I’m sure some of these suggestions are technically unfeasible due to network latency/efficiency. But without thinking too hard about the underlying technicalities, I think it’s not a bad list. So what have I left off?