OmniFocus Task Auto-Import via iOS Mail Flags

I live my life through OmniFocus.

Between my iPad, iPhone and my Mac, it’s the place that I store all of my tasks and random project stuff. I subscribe to the ‘trusted system’ theory – by knowing that I won’t lose track of something if it’s in OmniFocus, I don’t stress out about my todo list rattling around in my head.

Despite the great iOS apps, I inevitably have to process a lot of tasks that begin as email. The Mac version uses the Services menu to allow you to capture text and create list items easily. Unfortunately, due to current platform limits, there’s no such convenience on iOS. That means that by default, going through my email inbox and creating OmniFocus tasks isn’t all that doable on iOS. This troubled me.

Yes, Omni does provide their ‘Send to OmniFocus’ email address – you forward your message to it and it returns it back to you with a reply that contains a URL to populate the app with that task. It’s nice that they include this but come on, let’s be honest: it’s a hack. The messages aren’t linked the same way that they are when you use the Mac service and I just generally don’t like the idea of polluting my email with these extra messages.

Since my Mac at home is running 24×7, I wondered if there was a way I could use AppleScript to create my own solution. Here’s what I’m doing now:

In iOS 5, Apple added the ability to flag a message, just as you’ve been able to do on the desktop forever. I created an AppleScript that looks for flagged messages. When it finds them, it adds them to OmniFocus and links them back to Mail.app, just like the Services action does. It then also unflags the message, resetting the state back to normal. This script runs every five minutes.

What this means is that I can now just add a flag to a message on my iPhone or iPad and know that it will be picked up by OmniFocus.

There’s one serious downside – since Google’s Exchange implementation for Gmail is seriously strange (some might say broken), it doesn’t work there. While Exchange ActiveSync supports flags, the Google implementation does not. If you decide to use ActiveSync to access your Gmail account (i.e. to get contact and calendar sync, push, etc…), this will likely not work for you.

Anyway, this script has been so useful to me that I’m sharing it here. Feel free to use / hack on this yourself as it fits your needs.

I’ve never done anything in AppleScript before so if you’re an AS expert, don’t laugh too hard.

https://github.com/HunterHillegas/OmniFocusMailFlags

Comments

22 Comments so far. Leave a comment below.
  1. Hunter,

    For those asking, you can automate AppleScript runs via cron, for example:

    5,15,30,45,55 * * * * osascript “script_name.scpt” >> /dev/null

  2. Steve,

    I really like this concept. Unfortunately, the messages for which this would be most helpful are on an Exchange server, so the script doesn’t work for me yet (it’s coded for IMAP only). I’m trying to tweak the script and I found the applescript dictionary for mail.app, but I’m not seeing anything related to Exchange. (IMAP, POP, and iCloud are the only account types listed.) Do you know if that means applescript can’t tap into the Exchange account at all?

  3. Chris,

    Works well with Keyboard Maestro too on a time trigger, for those of us unfamiliar with cron…

    Nice!!!

    Thanks for the work..

    Picked this up via MacSparky! You are now in my RSS feed…

  4. Carl,

    Dear Hunter,

    many thanks for this great script. I run into problems, as the script found my inbox, but not any flagged messages. OS is Lion and the account is an exchange account. Do you have any idea what the problem might be? Please see below the script’s reply.

    Best,
    Carl
    tell application "Mail"
    count every account
    --> 1
    get name of item 1 of every account
    --> "xxx"
    get mailbox "Inbox" of item 1 of every account
    --> mailbox "Inbox" of account "xxx"
    count every message of mailbox "Inbox" of account "xxx" whose flagged status = true
    --> 0
    end tell

    • Hunter,

      From other feedback I’ve received, Exchange is acting up a little bit. If there’s anyone else out there that knows the answer, please post here!

      • Carl,

        On my Mac I switched from exchange to imap for mail purpose only, i.e. calendar and adressbook are still synchronising over the exchange server resulting in the best of both worlds: Your script is running and the advantages of the exchange-server are still available. The mobile clients (iphone/ipad) are still running on exchange for mail also. Now everything works very smooth.

        Maybe this concept is also a solution for others?

        Again: many thanks for this great script!

  5. Jason Clarke,

    I wonder if a good workaround to Gmail’s IMAP strangeness would be to make a special label (IMAP folder) and monitor it for any new messages that are put in it. When they are, an OmniFocus task is created and the message is removed from the IMAP folder. But would this break Mail’s ability to find the message when you try to navigate to it from the OmniFocus task?

  6. Bill,

    I just flagged a message I received in my gmail account on my iPad and after I checked Mail on the Mac (10.6.8), it showed up as flagged there as well. Unflagging it on the Mac and updating Mail on the iPad cleared the flag there. Maybe there are some cases where it doesn’t work, but it apparently isn’t the case that it never works.

    Did you have some actual basis for the comments about Gmail’s IMAP implementation being the reason for this not working? There’s a big gulf between “I tried it once and it didn’t seem to work (but I only spent 30 seconds and I don’t actually know anything about IMAP but I saw some guy say Gmail has a weird IMAP implementation)” and “This won’t work with Gmail because they don’t implement section 5.3.2.9 of the IMAP spec” :-) I can flag a message on my Gmail IMAP account on one Mac and it will be flagged when I check the account on another Mac set up the same way, though sometimes it takes a little while to update. Maybe the Mail app on your iOS gadget just hadn’t yet written the change back to the server due to your choice of Fetch settings, or Mail on your Mac hadn’t pulled in the change.

    Most unfortunate that the link the script creates doesn’t work with the iOS Mail apps, but that’s Apple’s fault. Thanks for posting the script! I would say anyone reading this who thinks it might be useful should try it, rather than just concluding it won’t work because they use Gmail.

    • Hunter,

      I tested it a dozen times with Gmail and never got it to work reliably. Also, I opened a bug with Apple and Engineering told me it was Gmail’s issue and they closed the bug. From what I’ve been told, when you flag something in Gmail, it assigns the flagged label, it doesn’t set the flagged attribute on the message that other IMAP clients recognize. All of that said, I am not an IMAP expert and I’ve never implemented the RFC. If someone wants to figure out definitively why it doesn’t work reliably, I’d be curious to know.

      If you know different, I’d love to hear more details. I have a couple of Gmail accounts and it’s a pain this doesn’t work with them. Perhaps there’s some sort of setup difference? Mail.app has my Gmail accounts set as IMAP – AFAIK, nothing custom. I’m running Lion on the Desktop, not Snow Leopard. Perhaps that’s a factor.

      I have my various mail apps set to check fairly aggressively and in my tests, even after 60+ minutes I wouldn’t see a state change.

      • Bill,

        Very curious, indeed! My Gmail accounts are all straight out of the box. In fact, I just created another one to test it again after you responded. I’m not an IMAP geek, either, but I can click on the yellow star on the gmail webpage as well as the next guy, and if I do, the flag eventually follows suit on my Macs and iPads, and vice versa. That strongly suggests that they are all using the same signaling mechanism. A friend now at Google used to be an iMAP geek at Apple, I’ll ask him next time I see him. As a former engineer in a big software organization, I’m always a bit skeptical when told by engineering management that the problem was someone else’s fault :-)

    • Hunter,

      Oh, Apple Engineering could be wrong. They’ve certainly closed bug reports of mine in the past erroneously.

      Anyway, if you do get a chance to ask your friend, I’d love to hear the details. It would be awesome if this could all work seamlessly.

      • Bill,

        I spoke to my friend, who said he is unaware of any Gmail implementation details with regards to stars/flagging, but that he uses it all the time without difficulty in conjunction with Mail.app, the gmail web app, and the Mail for iPod touch. Maybe it’s all in the wrist :-)

      • Hunter,

        Just to be clear – for both of you guys, when you use the flag function in the native iOS Mail app, that flag makes it’s way to Mail.app on the Mac? I think that’s what we’re all saying but since it doesn’t work for me at all in either of my accounts, it’s a surprise to hear.

        In talking to a few other people in relation to this script, I’m definitely not alone. I’d love to determine what the other variable is.

      • Hunter,

        Upon closer inspection, I may have figured this out… Turns out, my iPhone was setup to use Gmail as Exchange, not as IMAP. That appears to be where the breakage is (Exchange ActiveSync supports flags but it appears Google’s implementation does not). So, it’s likely true that the IMAP bit works fine and those of us with trouble are using ActiveSync to access Gmail, to access the extra features that come with that option. Sounds like to get push, calendar and contact sync, you have to give up flags… I’ll update the post.

  7. Bill,

    Yes, flag goes from iOS Mail to Mac Mail to gmail web view. I’m using IMAP, I think my friend does also. Sounds like you found the sticking point.

  8. Working with Exchange!
    Exchange accounts are of type “unknown”. Awesome :)
    I’ve been using this for over a month, so it’s about darn time I sent it back to you.

    I have Exchange server side rules moving some messages into different folders. However, I want the flagging to still look in those, so I created a list. I use 0 and 1 to keep certain folders near the top of the pile.
    Secondly, rather than just unflagging the email message, I want to clean up my inbox(es). So any email that’s sent into Omnifocus also gets moved into the 1OMNIFOCUS folder on my Exchange account (even if I flagged it in a different account. I’m weird like that). The mail URL still finds that message but it saves me a step of filtering it. I only want to touch a message once when I’m processing my inbox.


    on run
    set _exchange_interesting_mailboxes to {"Inbox", "0GROUP1", "0GROUP2"}
    set _omnifocus_followup to "1OMNIFOCUS"
    with timeout of 90000 seconds
    -- first find our Exchange account so we only store follow up items there
    tell application "Mail"
    repeat with _acct in accounts
    set _acct_status to enabled of _acct
    if _acct_status is true then
    set _acct_type to account type of _acct
    if _acct_type is unknown then
    set _acct_server to server name of _acct
    set _acct_name to name of _acct
    if _acct_server contains ".SOMETHING TO IDENTIFY YOUR EXCHANGE SERVER" then
    set exchange_account to _acct_name
    end if
    end if
    end if
    end repeat
    end tell

    tell application "Mail"

    repeat with _acct in accounts
    set _acct_status to enabled of _acct
    if _acct_status is true then

    --Look For Flagged Messages in the INBOX
    set _acct_name to name of _acct
    set _acct_type to account type of _acct
    if _acct_type is unknown then
    #set _inbox to _acct's mailbox "Inbox"
    set _mailbox_list to _exchange_interesting_mailboxes
    else
    #set _inbox to _acct's mailbox "INBOX"
    set _mailbox_list to {"INBOX"}
    end if

    repeat with _mbx in _mailbox_list
    set _inbox to _acct's mailbox _mbx

    set _msgs_to_capture to (every message of _inbox whose flagged status is true)
    repeat with eachMessage in _msgs_to_capture

    set theStart to missing value
    set theDue to missing value
    set theOmniTask to missing value

    set theTitle to the subject of eachMessage
    set theNotes to the content of eachMessage

    set theCombinedBody to "message://%3c" & message id of eachMessage & "%3e" & return & return & theNotes

    tell application "OmniFocus"
    tell default document
    set newTaskProps to {name:theTitle}
    if theStart is not missing value then set newTaskProps to newTaskProps if theDue is not missing value then set newTaskProps to newTaskProps if theCombinedBody is not missing value then set newTaskProps to newTaskProps set newTask to make new inbox task with properties newTaskProps
    end tell
    end tell

    set flagged status of eachMessage to false
    move eachMessage to mailbox _omnifocus_followup of account exchange_account
    end repeat
    end repeat
    end if
    end repeat
    end tell
    end timeout
    end run

  9. Phil Collins,

    Hunter

    Have stumbled on your script and if I could get it to work it would complete my workflow!!!

    Problem I have is twofold…

    1. I’m an applescript novice (make that complete novice!!)
    2. have compiled the script and popped it into com.apple.mail
    3. I have then used Mail Act on to call the script for flags – does this run continuoalsy or do I need to put a time mechanism in here?
    3. when I run the cript from applescript editor I get the following error…

    error “Mail got an error: Can’t get item 2 of every message of mailbox \”INBOX\” of account \”Phil Personal\” whose flagged status = true. Invalid index.” number -1719

    Help – any advice guidance gratefully received!

    Cheers

    Phil

    • Hunter,

      AppleScript is not a language I have much experience in myself so I’m not sure if I’ll be able to help. Maybe someone else will see this and knows the answer!

    • Simon Minshall,

      I also got the same error. Traced it to having inactive accounts in my list of accounts that were being processed. The first few items in the list of my accounts were active and were processed. The next one was inactive and Hunter’s script tried to process it and failed raising an exception, terminating the script.

      Two solutions:
      1: Wrap the contents of the first repeat block in a “try” block
      2: Test if the acct is active and only process it of that’s true.

      I went with 2: because AS is slow enough when processing mail. Here’s the revision:


      on run
      tell application "Mail"
      repeat with _acct in imap accounts
      --Look For Flagged Messages in the INBOX
      set _acct_name to name of _acct
      log _acct_name
      if _acct is enabled then
      set _inbox to _acct's mailbox "INBOX"

      set _messages to ¬
      ((every message of _inbox ¬
      whose flagged status is true))

      repeat with eachMessage in _messages

      set theStart to missing value
      set theDue to missing value
      set theOmniTask to missing value
      set theTitle to the subject of eachMessage
      set theNotes to the content of eachMessage
      set theCombinedBody to "message://%3c" & message id of eachMessage & "%3e" & return & return & theNotes

      tell application "OmniFocus"
      tell default document
      set newTaskProps to {name:theTitle}
      if theStart is not missing value then set newTaskProps to newTaskProps if theDue is not missing value then set newTaskProps to newTaskProps if theCombinedBody is not missing value then set newTaskProps to newTaskProps set newTask to make new inbox task with properties newTaskProps
      end tell
      end tell
      set flagged status of eachMessage to false
      end repeat
      end if
      end repeat
      end tell
      end run

  10. Alex,

    This is great. Thank you!

Add Your Comments

Required
Required
Tips

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <ol> <ul> <li> <strong>

Your email is never published nor shared.

Ready?