Automate Gmail Email to Remember the Milk Task

Every once in a while I spend a bit of time reviewing and streamlining my GTD process. This time I hit on a pretty big win — automating a connection between Gmail and Remember the Milk so that collecting actions from across all of my Gmail accounts is one-click easy. This automation makes it a breeze to process email on my phone. Woohoo – GTD on the can!

Remember the Milk has been at the core of my GTD stack for several years now. I’ve looked into other systems, even trying  Astrid for a month, but RTM still wins for my requirements set. It’s got a scriptable API, a command line interface, a solid Android app, and a nice web interface that’s keyboard friendly. Of course it has it quirks and annoyances (why can’t I move tasks between lists using the keyboard?), but it’s the best that I’ve found.

For email, Gmail has wormed its way into being my primary mechanism. It too has it quirks and annoyances, but the network effects are strong and the price is right (well, was right for business accounts). I still use Thunderbird too, but now primarily as a local Gmail client.

For this round of streamlining the challenge I set was to enable keyboard-based creation of a RTM task from a Gmail email that includes a link back to the original thread for quick action. This is now possible using a Google App Script. Here’s the code:

/*
This script watches a gmail account for any thread labeled with 'rtm'. When such a thread is found it
sends a task-creation email to Remember the Milk that includes a link back to the original thread.
To follow the link back to the email you have to be logged in to the originating Gmail account (which
is only an issue if you have multiple gmail accounts). Otherwise Google claims the email cannot be
found.
To install it go into Google Drive and create a new "Script" (the link is a bit hidden in the create submenu).
Copy this code into the new project and set a time-based trigger.
Copyright 2013, Jesse Heitler <jesseh i-iterate.com>
@
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
var LABEL_NAME = 'rtm'; // This string is the Gmail label that triggers a task to be created.
var TARGET_EMAIL = 'CHANGE_ME_TO_INBOX_ADDRESS@rmilk.com'; // From your RTM settings.
var RTM_LIST = ''; // Use to post the message to a specific RTM list
var RTM_TAGS = ''; // Use to add tags to the task in RTM
/**
* Process all the threads with a given label and remove that label
* and archive it so that it is not processesed again.
**/
function processLabel(labelName) {
var label = GmailApp.getUserLabelByName(labelName);
var threads;
var thread;
if (label) {
threads = label.getThreads();
for (var i = 0; i < threads.length; i++) {
thread = threads[i];
handleThread(thread);
thread.removeLabel(label);
thread.moveToArchive();
}
}
};
/**
* Get from whom was the most recent unread, or the latest message in a thread.
**/
function threadFrom(thread) {
var message;
var messages = thread.getMessages();
var from = messages[messages.length 1].getFrom();
for(var i = 0; i < messages.length; i++) {
message = messages[i];
if (message.isUnread()) {
from = message.getFrom();
}
}
return from;
};
function emailTask(details) {
var recipient = TARGET_EMAIL;
var subject = "Reply to '" + details['subject'] + "' " + details['from'] + " (" + details['count'] + ')';
var body = "";
if (details['priority']) {
body += "Priority: 3\n";
}
if (RTM_TAGS) {
body += "Tags: " + RTM_TAGS + "\n";
}
// body += "URL:" + details['permalink'] + "\n";
body += "URL:https://mail.google.com/mail/?view=cv&fs=1&th=&quot; + details['threadId'] + "&search=all\n"
if (RTM_LIST) {
body += "List: " + RTM_LIST + "\n";
}
Logger.log("Sent email with subject: " + subject + "\nBody:\n" + body);
GmailApp.sendEmail(recipient, subject, body)
};
function handleThread(thread) {
var details = {
threadId: thread.getId(),
subject: thread.getFirstMessageSubject(),
count: thread.getMessageCount(),
permalink: thread.getPermalink(),
priority: thread.hasStarredMessages(),
from: threadFrom(thread)
};
emailTask(details)
};
function main() {
var labelName = LABEL_NAME;
processLabel(labelName);
};

view raw
Gmail_to_RTM.js
hosted with ❤ by GitHub

Please feel free to form the gist and improve it!

  1. #1 by Colby on March 12, 2013 - 12:23 pm

    I have tried several different ideas to make this connection, including rather simplistic scripts of my own. I think this might be what I have been looking for. One tweak I think I will make is to make the link back to the email use the mobile version so that the email loads faster.

    • #2 by Jesse Heitler on March 12, 2013 - 12:29 pm

      Sounds like it good be a good improvement.

      What’s the url template for the mobile version? Does it improve the mechanism?

  2. #3 by Dan on March 23, 2013 - 11:18 am

    I would recommend checking out Gtdagenda for an online GTD manager.

    You can use it to manage your goals, projects and tasks, set next actions and contexts, use checklists, and a calendar.
    Syncs with Evernote, and also comes with mobile-web version, and Android and iPhone apps.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s