Apple Mail on the Desktop with GeekTool
With all of my TaskPaper and Django reminders on the Desktop, I realized I’d better get my Inbox on the Desktop too, or it would start filling up—out of sight, out of mind. I long ago started keeping my inbox empty; letting it accumulate again would not be good.
I found a rudimentary AppleScript on MacWorld hints that shows unread mail. It was also a programmer’s first AppleScript, so it did all sorts of programmer things I don’t personally like in an AppleScript.
I’ve reworked it to look more like what I think AppleScript should look like; just to make it easier for me to update. And I also flipped the read status. I don’t want to see unread messages, I want to see messages that I know I want to deal with. So I only show read messages, and I don’t leave it in my inbox if I don’t want to see it on my Desktop.
[toggle code]
- set messageList to {}
-
tell application "Mail"
-
repeat with pendingMessage in (messages of inbox whose read status is true)
-
tell pendingMessage
- --get sender's name
- set senderName to extract name from sender
- --if there is no name, or the address line is malformed, better to show just the address
-
if senderName is equal to sender then
- set senderName to extract address from sender
- end if
- --mark flagged messages specially
-
if pendingMessage is flagged status then
- set bullet to "» "
-
else
- set bullet to "• "
- end if
- copy bullet & senderName & tab & subject & linefeed to end of messageList
- end tell
-
tell pendingMessage
- end repeat
-
repeat with pendingMessage in (messages of inbox whose read status is true)
- end tell
- messageList as text
It’s fairly simple: it tells the Apple Mail application to get all “messages of Inbox whose read status is true”, i.e., all messages that have been read and are in the inbox. Then it tells each message to get information about itself.
If the message is flagged, it uses a right-pointing double angle as the bullet, otherwise it uses a standard bullet. I’ll sometimes use the flag to remind myself that, hey, this is the one you want to do next.
It compiles an array of lines with the bullet, the subject, and the sender’s name if it can find it. And finally, it converts that list to text.
It uses a neat trick that Mail can do, which I learned from Rob de Jong at MacWorld hints, which is to “extract name from” an address line; you can also “extract address from”; it works with any text that looks like a To or From line. For example:
[toggle code]
-
tell application "Mail"
- extract address from "John Hobo <jhobo@hoboes.com>"
- extract name from "\"John Hobo\" <jhobo@hoboes.com>"
- end tell
The terminology’s a bit weird; it pretty much requires using “set” instead of “copy” because “copy extract name from sender to senderName” scans horribly. On the other hand, “set variable name to extract name from sender” is only marginally better. I expect it made more sense when they tested in very simple cases and were able to use “the result”.
I saved the script as “text” in my personal bin folder, and named it “Inbox”; this gives it a file extension of “applescript”. By saving it as text, changes to it can be tracked by Mercurial.
The command to use it in GeekTool is:
- /usr/bin/osascript ~/bin/Inbox.applescript
You can run that line on the command line, too.
AppleScript Editor does not support UTF-8, only, as far as I can tell, Mac OS Roman; however, the osascript command does. UTF-8 is better for tracking in Mercurial and provides more bullet options; AppleScript Editor is better for AppleScript. It’s a tossup, but currently I’m using Mac OS Roman because editing AppleScript outside of AppleScript Editor is painful, and I don’t use AppleScript enough to justify buying a third-party editor dedicated to AppleScript.
A couple of other things I ran into:
- It would be nice if GeekTool could set tab stops. That would make the results more readable.
- There does not appear to be any way of getting all flagged messages, even through a smart mailbox. There does not, in fact, appear to be any way to select smart mailboxes. This means that my old trick of flagging messages and using a smart mailbox to collect important messages all in one place isn’t as useful. If I want to act on something, I need to move it into my inbox.
- I also don’t see a way of specifying the order of the messages (without changing their order in the mailbox, and I don’t want the script to interfere with my inbox). Something like “messages of inbox sorted by descending date received” would be nice.
Another nice thing about this, is that I don’t need a separate geeklet for iCal, since iCal emails me anything important and the email lands on the Desktop as soon as I decide not to delete it (or doesn’t land on the Desktop if I do choose to delete it). If you do want to work more closely with iCal, you may find icalBuddy useful.
- March 28, 2011: AppleScript, Mail, and deleted messages
-
One thing I’ve noticed happen occasionally—but not often—with this script is that I sometimes see ghost messages: messages I’ve deleted from my inbox, and no longer appear in my inbox, but do get picked up by AppleScript.
I’m not sure exactly what’s going on here, because the messages do eventually disappear. They just don’t disappear immediately. What appears to be happening is that OS X Mail keeps trashed messages, in its internal SQLite database, in the folder they were trashed from.1 And my guess is that when AppleScript asks for all messages from the inbox, Mail just returns a query on that database.
This is easy to check for in the AppleScript, however. Each message has a “deleted status” on it. If it’s true, the message has been deleted.
So replace the “repeat with pendingMessage…” line with:
- repeat with pendingMessage in (messages of inbox whose read status is true and deleted status is false)
It seems more than a little weird to be asking Mail specifically to ignore messages that don’t appear to be there in the first place. As far as I can tell, however, they are there, but the OS X Mail GUI is hiding them from you.
- Extract name and email from Mail via AppleScript: Rob de Jong
- “When writing Applescripts for Mail, it’s extremely easy to fetch the name and e-mail address of a sender.”
- icalBuddy: Ali Rantakari
- “icalBuddy is a command-line utility that can be used to get lists of events and tasks/to-do’s from the OS X calendar database (the same one iCal uses).”
- Original Inbox Zero Articles (2006): Merlin Mann at Inbox Zero
- “These links point to the original Inbox Zero Series that Merlin wrote for 43 Folders in 2006. They cover the skills, tools, and attitudes that can help empty your email inbox—and then keep it that way. You can visit each of the posts by clicking the title.”
- Use GeekTool to see new Mail messages on the desktop
- “I use GeekTool a lot, and one of the things I use it for is to display my new email messages on the desktop. To do that, I use this AppleScript.”
More AppleScript
- Find all parent mailboxes in macOS Mail
- The macOS Mail app seems to want to hide the existence of mailboxes and any sense of hierarchical storage. These two AppleScripts will help you find the full path to a selected message and open the message’s mailbox.
- JXA and AppleScript compared via HyperCard
- How does JXA compare to the AppleScript solution for screenshotting every card in HyperCardPreview?
- Using version control with AppleScripts
- AppleScripts aren’t stored as text, which makes it impossible to track changes in AppleScript files using version control software such as Mercurial or Git.
- Save clipboard text to the current folder
- Use the Finder toolbar to save text on the current clipboard directly to a file in the folder that Finder window is displaying.
- Adding parenthetical asides to photograph titles on macOS
- Use Applescript to append a parenthetical to the titles of all selected photographs in Photos on macOS.
- 17 more pages with the topic AppleScript, and other related pages
More GeekTool
- Bluetooth battery early warning system
- Use GeekTool, or crontab or launchd and notifications, to know when your bluetooth batteries need recharging.
- icalBuddy and eventsFrom/to
- Ali Rantakari’s icalBuddy has an error in the documentation for the “eventsFrom/to” command-line option. Rather than “tomorrow at time” use “time tomorrow”.
- Put a relative clock on your Desktop with GeekTool
- There are a lot of desktop clocks that show the absolute time. But sometimes you just want to know if the time is today, or yesterday, or two days ago. Here’s how to do it with Python and GeekTool.
- GeekTool, TaskPaper, and XML
- A script to convert a TaskPaper file to XML so as to filter it for specific tags and display the results on the Desktop.
- GeekTool, Perl, and ANSI color codes
- GeekTool is a great way to display the results of little scripts on your desktop. Using ANSI color codes can make those scripts even more useful. You can also change the status of the status button from “success” to “failure” depending on your script’s exit code.
- One more page with the topic GeekTool, and other related pages
i've been playing with this script; and granted i'm a complete novice to the applescript stuff; but i'm trying to do a couple of things:
show a list of the 4-5 most recent messages with the bullet marker if the message is read or unread;
i found a geeklet that did this, but it the script would fail constantly and wouldn't look at multiple mailboxes.
any help?
Cory at 3:39 p.m. April 6th, 2011
ujOlg
The first item: a list of the 4-5 most recent messages with the bullet for unread, you could use this script for, but only for one mailbox at a time (such as the inbox), not for multiple mailboxes or for a smart mailbox to combine them; I still haven’t found a way to handle smart mailboxes.
You would have to remove “ whose read status is true” (but keep the new “whose deleted status is false” from the update); and then change “ if pendingMessage is flagged status then” to “ if pendingMessage is read status then” to give a different bullet for read vs. unread mail.
But as I said, that will only give you one mailbox at a time.
capvideo at 12:23 a.m. April 7th, 2011
tVAhq
here's what i've got in the script file:
set messageList to {}
tell application "Mail"
repeat with pendingMessage in (messages of inbox whose deleted status is false)
tell pendingMessage
--get sender's name
set senderName to extract name from sender
--if there is no name, or the address line is malformed, better to show just the address
if senderName is equal to sender then
set senderName to extract address from sender
end if
--mark flagged messages specially
if pendingMessage is (read status is false) then
set bullet to "• "
else
set bullet to " "
end if
copy bullet & senderName & tab & subject & linefeed to end of messageList
end tell
end repeat
end tell
but for some reason, i'm only getting 1 message now
Cory at 6:09 p.m. April 8th, 2011
ujOlg
Make sure you've got the last line:
messageList as text
otherwise, all you'll get is the last message you added to messageList.
capvideo at 2:12 p.m. April 12th, 2011
tVAhq