Difference between revisions of "Create Google Tasks by sending email to Google GMail"

From Ittichai Chammavanijakul's Wiki
Jump to navigation Jump to search
Line 140: Line 140:
 
     function addTask_(title, message, tasklistId) {   
 
     function addTask_(title, message, tasklistId) {   
 
       //var newTask = Tasks.newTask().setTitle(title);   
 
       //var newTask = Tasks.newTask().setTitle(title);   
       var newTask = Tasks.newTask().setTitle(title).setNotes(message);   
+
       var newTask = Tasks.newTask();
 +
      newTask.setTitle(title);
 +
      newTask.setNotes(message);   
 
       Tasks.Tasks.insert(newTask, getTasklistId_(tasklistId));   
 
       Tasks.Tasks.insert(newTask, getTasklistId_(tasklistId));   
 
     }   
 
     }   

Revision as of 11:06, 30 June 2013

Goals:

  • Send email to a specified address - in this case to Gmail address named yourgmail+task@gmail.com. (If Gmail ID is ittichai, the email address to send to will be ittichai+task@gmail.com.) Read more about the hidden feature with Gmail - http://gmailblog.blogspot.com/2008/03/2-hidden-ways-to-get-more-from-your.html
  • Script will parse that email based on a Gmail label assigned by filter, and grab the email's subject to create a new Google task.

Follow this step-by-step of this page. http://www.pipetree.com/qmacro/blog/2011/10/automated-email-to-task-mechanism-with-google-apps-script/

This is just an overview of what happens:

  1. Create Gmail new labels - newtask and newtaskdone.
  2. Create Gmail filter based on newtask label.
  3. Create script from Google Spreadsheet. Make sure that the name of the task list in TASKLIST variable is changed to yours.
  4. Integrate the script with Google API.
  5. Schedule it via the time-driven even trigger.

Pay attention to the *Integrate the script with Google API* in the *Script Code* section especially if this is your first time coding this. You will have to enable Google API service to allow access the Task API - https://developers.google.com/apps-script/articles/google_apis_reading_list. If not doing so, you will receive an error message saying "Tasks - not defined" when running the script.

In addition to above sample, I'd like to add the email's body into the G! task's note.

Here is what I do:

  • Add a new variable to grab the email's body
        // Grab the task data  
        // This email's subject will be task's title.
        var taskTitle = thread.getFirstMessageSubject();  

        // This email's body will be task's body. Most email message now is HTML-based.
        // It is desirable to remove all HTML tags so that only actual content will be populated.
        // Use a custom function getTextFromHtml to strip out all HTML tags.
        // In addition, the string size will be limited to 3000 characters in case an email is very long.
        var taskNote = getTextFromHtml((thread.getMessages()[0]).getBody()).substring(0,3000);

Most email message now is HTML-based. Without stripping out the HTML tags, the task's note will be populated with many useless tags. I use functions mentioned on this web site http://stackoverflow.com/questions/8936092/remove-formatting-tags-from-string-body-of-email to get only text message. Basically, add these two functions in the script.

function getTextFromHtml(html) {
  return getTextFromNode(Xml.parse(html, true).getElement());
}

function getTextFromNode(x) {
  switch(x.toString()) {
    case 'XmlText': return x.toXmlString();
    case 'XmlElement': return x.getNodes().map(getTextFromNode).join('');
    default: return '';
  }
}
  • Add new parameter of task's note to addTask_
        // Insert the task  
        //addTask_(taskTitle, TASKLIST);  
        addTask_(taskTitle, taskNote, TASKLIST);  
  • Update the addTask_ to include setNotes
    function addTask_(title, message, tasklistId) {  
      //var newTask = Tasks.newTask().setTitle(title);  
      var newTask = Tasks.newTask();
      newTask.setTitle(title);
      newTask.setNotes(message);  
      Tasks.Tasks.insert(newTask, getTasklistId_(tasklistId));  
    }  

This is the whole modified script.

// Original Source: http://www.pipetree.com/qmacro/blog/2011/10/automated-email-to-task-mechanism-with-google-apps-script/
    // -----------------------------------------------------  
    // Globals, contants  
    // -----------------------------------------------------  
    TASKLIST = "Ittichai's list";  
    LABEL_PENDING = "newtask";  
    LABEL_DONE = "newtaskdone";  
      
    // -----------------------------------------------------  
    // getTasklistId_(tasklistName)  
    // Returns the id of the tasklist specified  
    // Oddly, we should be able to use:  
    // Tasks.Tasklists.get(tasklistName)  
    // but it always gives an error "Invalid Value".  
    // -----------------------------------------------------  
    function getTasklistId_(tasklistName) {  
      var tasklistsList = Tasks.Tasklists.list();  
      var taskLists = tasklistsList.getItems();  
      for (tl in taskLists) {  
        var title = taskLists[tl].getTitle();  
        if (title == tasklistName) {  
          return taskLists[tl].getId();  
        }  
      }  
    }  
      
    // -----------------------------------------------------  
    // processPending(sheet)  
    // Process any pending emails and then move them to done  
    // -----------------------------------------------------  
    function processPending_(sheet) {  
      
      var label_pending = GmailApp.getUserLabelByName(LABEL_PENDING);  
      var label_done = GmailApp.getUserLabelByName(LABEL_DONE);  
      
      // The threads currently assigned to the 'pending' label  
      var threads = label_pending.getThreads();  
      
      // Process each one in turn, assuming there's only a single  
      // message in each thread  
      for (var t in threads) {  
        var thread = threads[t];  
      
        // Grab the task data  
        // This email's subject will be task's title.
        var taskTitle = thread.getFirstMessageSubject();  
        
        // This email's body will be task's body. Most email message now is HTML-based.
        // It is desirable to remove all HTML tags so that only actual content will be populated.
        // Use a custom function getTextFromHtml to strip out all HTML tags.
        // In addition, the string size will be limited to 3000 characters in case an email is very long.
        var taskNote = getTextFromHtml((thread.getMessages()[0]).getBody()).substring(0,3000);
      
        // Insert the task  
        //addTask_(taskTitle, TASKLIST);  
        addTask_(taskTitle, taskNote, TASKLIST);  

        // Set to 'done' by exchanging labels  
        thread.removeLabel(label_pending);  
        thread.addLabel(label_done);  
      }  
      
      // Increment the processed tasks count  
      var processedRange = sheet.getRange("B1");  
      processedRange.setValue(processedRange.getValue() + threads.length)  
    }  
      
    // -----------------------------------------------------  
    // addTask_(title, taskListId)  
    // Create new task and insert into given tasklist  
    // -----------------------------------------------------  
    function addTask_(title, message, tasklistId) {  
      //var newTask = Tasks.newTask().setTitle(title);  
      var newTask = Tasks.newTask();
      newTask.setTitle(title);
      newTask.setNotes(message);  
      Tasks.Tasks.insert(newTask, getTasklistId_(tasklistId));  
    }  
      
    // -----------------------------------------------------  
    // main()  
    // Starter function; to be scheduled regularly  
    // -----------------------------------------------------  
    function main_taskconverter() {  
      
      // Get the active spreadsheet and make sure the first  
      // sheet is the active one  
      var ss = SpreadsheetApp.getActiveSpreadsheet();  
      var sh = ss.setActiveSheet(ss.getSheets()[0]);  
      
      // Process the pending task emails  
      processPending_(sh);  
      
    }  

// Strip out all HTML tags.
// Source: http://stackoverflow.com/questions/8936092/remove-formatting-tags-from-string-body-of-email
function getTextFromHtml(html) {
  return getTextFromNode(Xml.parse(html, true).getElement());
}

function getTextFromNode(x) {
  switch(x.toString()) {
    case 'XmlText': return x.toXmlString();
    case 'XmlElement': return x.getNodes().map(getTextFromNode).join('');
    default: return '';
  }
}