Create Google Tasks by sending email to Google GMail

From Ittichai Chammavanijakul's Wiki
Revision as of 15:57, 9 September 2018 by Ittichai (talk | contribs)
Jump to navigation Jump to search

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.

Instructions:

  • Create two new Gmail labels - newtask and newtaskdone.

create_new_label1.jpg create_new_label2.jpg


  • Create a Gmail filter to apply "newtask" label to all incoming yourgmail+task@gmail.com.

filter1.jpg filter2.jpg


  • Create a new Google Sheet. Enter Processed tasks in cell A1. It will be used to display how many tasks have been processed. Start the Script Editor from Tools menu.

GDoc_Script.jpg


  • Create a new blank project.

create_blank_proj.jpg


  • Copy and paste the whole script here. Note below will walk through the codes.
// Original Source: http://www.pipetree.com/qmacro/blog/2011/10/automated-email-to-task-mechanism-with-google-apps-script/
    // -----------------------------------------------------  
    // Globals, constants  
    // -----------------------------------------------------  
    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);  

        // [Optional] Send email for every new task
        //MailApp.sendEmail('ittichai@gmail.com', taskTitle, taskNote);

        // 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 '';
  }
}

  • Make sure that the name of the task list in TASKLIST variable is changed to your primary task list name.
    TASKLIST = "Ittichai's list";  
    LABEL_PENDING = "newtask";  
    LABEL_DONE = "newtaskdone";  


  • Integrate the script with Google API.

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.

g_api1.jpg g_api2.jpg


  • Confirm whether or not it is working by forwarding the email to yourgmail+task@gmail.com, then manually running the script.

run_gtask.jpg


  • If it works, you can now schedule to run this script via the time-driven even trigger.

schedul1.jpg schedule2.jpg

eZAZxHJuxs14NXwEahpLJlV8njDJtEZEzPBURr0XW1-zQiD-SNlsf9HFNqM81_UL0HrqpTb8ag0cnEZsVgD3bvoxlyO2MMdbLc2e6L1LPA08lo92ad-RtRXBW_vLQvrU2h8WEVO26wQzbecS-0sXmD6MzCjjw1yvqXwYZFHlIUtbeRaYi6qCo_MvMeFRcF0S1crlBU4SAVUOyIdA7JHRSV6R9_9nuBPiZIjGDXqCVoxvMxyZMEgXuQN0vdbEZaFi3ZmC2zXpRntZc_5fjCwg4gx9mfrV--NDlJwPEa6SwYFKFDvluaSHFWjSBvamc5wwUE1vPchgccvoi5WZiWhInUHkuEjUqLlWhbDV1cWGGmfcrMzp96DdokdMGaj-7aeSG8r6qflDza7tzpxHyp21cbQ-PbI1gUzYM-MWLvT2Ub7odSpnd_0sGlp_5nmbtvB1brQXXdtk4IYiwjQrRzoXjbFUPoFFAVuHHolgDWAHP3R2kEXgvLSeLHk6uyFgTg-AQE8qzV218EHY3ndc1kZ46rXIFZbZ2T_xCcjqUIgcy3NxV8kmpoU8ETqD-j67FSgOk9JsM_lh9LtzA7znUNMKZmLz3AIpXOAo1pa5gKBfLGo5a3bJ1PZdGC4NMJqw164PEAyGr2shsdvNOdLHl-mWDYQsNpNgnbjyxyaWEqCHjkFw8_GCmUkQ-GwO-A=w848-h257-no.jpg

https://photos.app.goo.gl/jA7S9gYauXTJQLY88 END


Notes

Here is just a quick walk through explaining what I've done differently from the original codes.

  • Add the email's body in addition to email's subject.
        // 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);
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

Thanks Bernard Goldberger (http://www.linkedin.com/profile/view?id=204142846) for updating script to fix some recent setNotes issue by separating setTitle and setNotes into separate lines.

    function addTask_(title, message, tasklistId) {  
      //var newTask = Tasks.newTask().setTitle(title);  
      //var newTask = Tasks.newTask().setTitle(title).setNotes(message); // 2013-06 .setTitle concatenated with.setNotes Failed
      var newTask = Tasks.newTask();
      newTask.setTitle(title);
      newTask.setNotes(message);  
      Tasks.Tasks.insert(newTask, getTasklistId_(tasklistId));  
    }  
  • Optionally, an email can be sent out for every new task.

        // [Optional] Send email for every new task
        MailApp.sendEmail('ittichai@gmail.com', taskTitle, taskNote);


Reference: http://www.pipetree.com/qmacro/blog/2011/10/automated-email-to-task-mechanism-with-google-apps-script/