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: