Jott and OmniFocus

Although I recently decided that Jott’s iPhone app was of no use to me, I still like and use the service. I recently made some changes to my OmniFocus and Mail setup to allow me to add tasks to OmniFocus via Jott. With these changes, I can call Jott, dictate a new task, and see it in my OmniFocus Inbox minutes later.

OmniFocus has a set of preferences that allows you to create and activate a Mail rule that takes certain email messages and turn them into actions. I have it set to handle email messages sent to my regular address with a “+omnifocus” inserted just before the @ symbol. (Many email servers, including GMail, will deliver these messages to your regular address; the “+something” addition helps you filter the messages before you read them.)

Configuring OmniFocus this way creates a new mail filtering rule, called “Send to OmniFocus,” which you can see by opening Mail’s preferences. Clicking the Edit button reveals the four steps of the rule:

The most important step is the third one, which passes the message through an AppleScript that’s buried within the OmniFocus application package at

/Applications/OmniFocus.app/Contents/Resources/MailAction.applescript.

This AppleScript works quite well with messages you type up and send to yourself. At the most basic level, it makes a new, uncategorized task with a title taken from the subject of the message and an attached note taken from the body of the message. You can get much fancier than this—including the project, context, or due date— by following some simple formatting rules described in the Mail section of the OmniFocus manual.

Getting Jott to send email to your new “+omnifocus” address is simple: go to your Jott Contacts page, click the Add Contact link, and add a new contact with the special “+omnifocus” address.

The configuration above would work for someone whose regular address is “johndoe@gmail.com.” I like to use “focus” as the name of this special address because it’s easy for me to remember and easy for Jott’s voice recognition to understand. It’s what I say when the Jott lady asks “Who do you want to Jott?”

Unfortunately, the default AppleScript doesn’t work so well with the emails that Jott sends. The subject line of a Jott message starts with a parenthetical announcement that the message is from Jott and finishes with an abbreviated version of your dictated message. The full transcription—which is what I want as the task’s title—is buried in the middle of the body of the message. So sending a Jott-transcribed email through the filter creates a task that needs serious editing, which defeats the purpose.

Fortunately, the solution is pretty straightforward. I made a copy of the AppleScript in the OmniFocus package, made a few changes to accommodate the way Jott messages are formatted, saved the result in my ~/Library/Scripts/Applications/Mail folder (the same folder FastScripts uses), and modified the Mail rule to run this new script instead of the old one.

The full path to the new script is ~/Library/Scripts/Applications/Mail/MailActions.scpt. It’s saved as a script, rather than as a text file as the original is.

Here’s the new AppleScript:

 1  -- Copyright 2007 The Omni Group.  All rights reserved.
 2  -- Additions for Jott handling by Dr. Drang, 2008
 3  -- $Header: svn+ssh://source.omnigroup.com/Source/svn/Omni/branches/OmniFocus/1.x/OmniGroup/Applications/Focus/App/Preferences/MailAction.applescript 100519 2008-05-15 21:12:32Z bungi $
 4  
 5  using terms from application "Mail"
 6    -- Trims "foo <foo@bar.com>" down to "foo@bar.com"
 7    on trim_address(theAddress)
 8      try
 9        set AppleScript's text item delimiters to "<"
10        set WithoutPrefix to item 2 of theAddress's text items
11        set AppleScript's text item delimiters to ">"
12        set MyResult to item 1 of WithoutPrefix's text items
13      on error
14        set MyResult to theAddress
15      end try
16      set AppleScript's text item delimiters to {""} --> restore delimiters to default value
17      return MyResult
18    end trim_address
19    
20    
21    on process_message(theMessage)
22      tell application "OmniFocus"
23        log "OmniFocus calling process_message in MailAction script"
24      end tell
25      -- Allow the user to type in the full sender address in case our trimming logic doesn't handle the address they are using.
26      set theSender to sender of theMessage
27      set trimmedSender to my trim_address(theSender)
28      tell application "OmniFocus"
29        set AllowedSender to allowed mail senders
30        if AllowedSender does not contain trimmedSender and AllowedSender does not contain theSender then
31          return
32        end if
33      end tell
34      
35      set theSubject to subject of theMessage
36      set theContent to content of theMessage
37      set singleTask to false
38      if theSubject starts with "(Jott from" then
39        set theText to paragraph 3 of theContent
40      else
41        if (theSubject starts with "Fwd: ") then
42          -- Whole forwarded messages shouldn't split.
43          set singleTask to true
44          set theSubject to text 6 through -1 of theSubject
45        end if
46        set theText to theSubject & return & theContent
47      end if
48      tell application "OmniFocus"
49        tell default document
50          parse tasks with transport text theText as single task singleTask
51        end tell
52      end tell
53    end process_message
54    
55    on perform mail action with messages theMessages
56      try
57        set theMessageCount to count of theMessages
58        repeat with theMessageIndex from 1 to theMessageCount
59          my process_message(item theMessageIndex of theMessages)
60        end repeat
61      on error m number n
62        tell application "OmniFocus"
63          log "Exception in Mail action: (" & n & ") " & m
64        end tell
65      end try
66    end perform mail action with messages
67  end using terms from

The new logic is in Lines 38-40 and 47. Basically, I’ve wrapped an if-then-else block around some of the original logic. The conditional tests the subject line to see whether the message is from Jott. If it is, the text that gets parsed by OmniFocus into a new task is simply the transcription of what I said, which comprises the third paragraph of the body of the message. If the message is not from Jott, the original logic is followed.

So far the filter is working great. Even though I have OmniFocus on my iPhone and could type new tasks into it directly, it’s often much easier and faster to just dictate the task to Jott and let the automation do its magic. It would, no doubt, be even more valuable to someone with another brand of cell phone.

Update 1/26/09
I’ve been informed by reader Erik Courtney that the script as written above no longer works, as Jott has apparently changed the format of the emails it sends out. Since I no longer use Jott, but use Dial2Do instead, I didn’t have the tools I would have liked to debug the script. But with Erik’s help, I was able to determine that changing Line 39 from

39        set theText to paragraph 3 of theContent

to

39        set theText to paragraph 2 of theContent

is all that’s needed to get the script working again. (At least it’s working for Erik.)

If Jott changes its message format again, Line 38, which is where the message is identified as having come from Jott, and Line 39, which plucks out the part you dictated, are the lines that will need to be updated to fit the new format.

Tags: