Context.IO REST API and Google Apps Script Integration

contextio_borderedContext.IO provides a REST email API that makes it easy and fast to integrate your user’s email data in your application. As soon as you connect mailboxes to Context.IO the system index them and makes all the content available through a set of REST API.
Context.IO not only exposes mail messages data but also contacts, files and threads related to the mailbox. One of the most interesting thing about Context.IO is that it abstract all the details about connecting to the mailbox so you have a consistent API available over different mailboxes technologies.

Google Apps Script provides a really useful API to access Gmail service. This API is user centric, allows the script executor or owner to access his own Gmail account and get a lot of informations out of it and even execute a vast set of operations.

Summing Context.IO and Google Apps Script Gmail Service allows you to manage the entire set of domain mailbox in an easy and powerful way. Let’s see how we can leverage the Context.IO advantages inside Google Apps Script.

First you have to get a free API key from Context.IO. Access your Context.IO console and connect the accounts you want to use.

Google Apps Script provides a UrlFetch service that allows you to consume external web services and implements even the oAuth protocol which is employed by Context.IO for authorization and authentication purposes.

/**
 * Get a Context.io account id by the specified email address
 *
 * @param {String} email email address to get the id for
 * @return {String} account id associated to the specified email address
 */
function getAccountIdByMail(email) {

  var consumer = {
     key: "yourkey",
     secret: "yoursecret"
  };

  var options = {
     oAuthServiceName : "context.io",
     oAuthUseToken : "never",
     validateHttpsCertificates: false
  };

  var oauthConfig = UrlFetchApp.addOAuthService("context.io");
  oauthConfig.setConsumerKey(consumer.key);
  oauthConfig.setConsumerSecret(consumer.secret);

  var url = "https://api.context.io/2.0/accounts?email=" + encodeURIComponent(email);
  var response = JSON.parse(UrlFetchApp.fetch(url,options).getContentText());
  return response[0].id;

}

Each account inside Context.IO service has an account id. With this function we are trying to retrieve the Context.IO account id associated to the email address specified. As you can see the result of a Context.IO API calls is JSON, so we can easely parse it to a Javascript object to be used inside our context.

/**
 * Copy email message between Gmail accounts
 *
 * @param {String} source The Context.IO source account id
 * @param {String} destination The Context.IO destination account id
 * @param {String} messageId The Gmail message id to be copied
 */
function copyMessage(source, destination, messageId) {

  var consumer = {
     key: "yourkey",
     secret: "yoursecret"
  };

  var options = {
     oAuthServiceName : "context.io",
     oAuthUseToken : "never",
     validateHttpsCertificates: false
  };  
  var oauthConfig = UrlFetchApp.addOAuthService("context.io");
  oauthConfig.setConsumerKey(consumer.key);
  oauthConfig.setConsumerSecret(consumer.secret);

  // Get the raw email message to be moved
  var url = "https://api.context.io/2.0/accounts/";
  url += source + "/messages/" + messageId + "/source";
  var messageRFC822 = UrlFetchApp.fetch(url,options).getBlob();

  var params={
    "dst_source": getLabelForAccountId(destination),
    "dst_folder": "INBOX",
    "message": messageRFC822                          
    };

  var options_post =
    {
      oAuthServiceName : "context.io",
      oAuthUseToken : "never",
      validateHttpsCertificates: false,
      "method" : "POST",
      "payload" : params
    };

  var url = "https://api.context.io/2.0/accounts/";
  url += destination + "/messages";

  var response = UrlFetchApp.fetch(url, options_post);
}

This function is used to copy messages between Gmail accounts (actually between Context.IO accounts) using the POST method, to be noted how the POST payload is composed, the messages to be moved as to be retrieved as a Blog in this way we will let Google Apps Script determine the correct encoding of the POST method automatically.

Attached to this post you can find contextEngineService.gs that is a Google Apps Script web service created using the Content service that consumes the Context.IO API and gmailEngine.gs that is a Google Apps Script that handles user’s email message moves requests using the Gmail service and consumes the contextEngineService.

contextEngineService.gs

var consumer = {
   key: "yourkey",
   secret: "yoursecret"
};

var options = {
   oAuthServiceName : "context.io",
   oAuthUseToken : "never",
   validateHttpsCertificates: false
};

function doGet(e) {
  var output = ContentService.createTextOutput();

  var action = e.parameter.action;
  var from = e.parameter.from;
  var to = e.parameter.to;
  var messageId = e.parameter.messageId;

  var sourceAccountId = getAccountIdByMail(from);
  var destinationAccountId = getAccountIdByMail(to);

  /**
   * To be able to use the Gmail message id we have to prepend gm-
   * this is required by context.io
   */
  var fixedMessageId = "gm-" + messageId;

  switch(action) {
    case "move":
      copyMessage(sourceAccountId, destinationAccountId, fixedMessageId);
      break;

    default:
      break;

  }

  return output;
}

/**
 * Copy email message between Gmail accounts
 *
 * @param {String} source The Context.IO source account id
 * @param {String} destination The Context.IO destination account id
 * @param {String} messageId The Gmail message id to be copied
 */
function copyMessage(source, destination, messageId) {

  var oauthConfig = UrlFetchApp.addOAuthService("context.io");
  oauthConfig.setConsumerKey(consumer.key);
  oauthConfig.setConsumerSecret(consumer.secret);

  // Get the raw email message to be moved
  var url = "https://api.context.io/2.0/accounts/";
  url += source + "/messages/" + messageId + "/source";
  var messageRFC822 = UrlFetchApp.fetch(url,options).getBlob();

  var params={
    "dst_source": getLabelForAccountId(destination),
    "dst_folder": "INBOX",
    "message": messageRFC822                          
    };

  var options_post =
    {
      oAuthServiceName : "context.io",
      oAuthUseToken : "never",
      validateHttpsCertificates: false,
      "method" : "POST",
      "payload" : params
    };

  var url = "https://api.context.io/2.0/accounts/";
  url += destination + "/messages";

  var response = UrlFetchApp.fetch(url, options_post);
}

/**
 * Get a Context.io account id by the specified email address
 *
 * @param {String} email email address to get the id for
 * @return {String} account id associated to the specified email address
 */
function getAccountIdByMail(email) {
  var oauthConfig = UrlFetchApp.addOAuthService("context.io");
  oauthConfig.setConsumerKey(consumer.key);
  oauthConfig.setConsumerSecret(consumer.secret);

  var url = "https://api.context.io/2.0/accounts?email=" + encodeURIComponent(email);
  var response = JSON.parse(UrlFetchApp.fetch(url,options).getContentText());
  return response[0].id; 
}

/**
 * Get the account label for the specified account id
 * 
 * @param {String} accountId Context.io account id
 * @return {String} Label for the specified account id
 */
function getLabelForAccountId(accountId) {
  var oauthConfig = UrlFetchApp.addOAuthService("context.io");
  oauthConfig.setConsumerKey(consumer.key);
  oauthConfig.setConsumerSecret(consumer.secret);

  var url = "https://api.context.io/2.0/accounts/" + accountId + "/sources";
  var response = JSON.parse(UrlFetchApp.fetch(url,options).getContentText());
  return response[0].label;
}

gmailEngine.gs

/**
 * Scan Gmail account for message move requests
 */
function ScanGmail() {
 var labelsArr = scanLabels();
  for(var i=0; i<labelsArr.length; i++) {
    var threadsArr = getThreadsForLabel(labelsArr[i]);
    for(var j=0; j<threadsArr.length; j++) {
      var messagesArr = getMessagesforThread(threadsArr[j]);
      for(var k=0; k<messagesArr.length; k++) {
        var messageDestination = labelsArr[i].getName().substring(8);
        var messageId = messagesArr[k].getId();
        var messageSource = Session.getUser().getEmail();
        consumeContextEngine("move", messageSource, messageDestination, messageId);
      }
    }
  }
}

/**
 * Find all user's Gmail labels that represent mail message
 * movement requests es: moveto->[email protected]
 *
 * @return {GmailLabel[]} Array of GmailLabel objects
 */
function scanLabels() {
  // logs all of the names of your labels
  var labels = GmailApp.getUserLabels();
  var results = new Array();
  for (var i = 0; i < labels.length; i++) {
    if(labels[i].getName().substring(0,8) == "moveto->") {
      results.push(labels[i]);
    }
  }
  return results;
}

/**
 * Get all Gmail threads for the specified label
 *
 * @param {GmailLabel} label GmailLabel object to get threads for
 * @return {GmailThread[]} an array of threads marked with this label
 */
function getThreadsForLabel(label) {
  var threads = label.getThreads();
  return threads;
}

/**
 * Get all Gmail messages for the specified Gmail thread
 *
 * @param {GmailThread} thread object to get messages for
 * @return {GmailMessage[]} an array of messages contained in the specified thread
 */
function getMessagesforThread(thread) {
  var messages = thread.getMessages();
  return messages;
}

/**
 * Consume a web service made with google apps script
 *
 * @param {String} action action to execute
 * @param {String} messageSource source email address
 * @param {String} messageDestination destination email address
 * @param {String} messageId Gmail message id
 */
function consumeContextEngine(action, messageSource, messageDestination, messageId) {
  // Url of the web service
  var url = "https://script.google.com/a/macros/domain.com/s/XXXXXXXXXXXXXXXXXXXXXXXX/exec"

  // Handle the requested action type
  switch(action) {
    case "move":
      url = url + "?action=" + action + "&from=" + messageSource + "&to=" + messageDestination + "&messageId=" + messageId;
      UrlFetchApp.fetch(url).getContentText();
      break;
    default:
      break;
  }
}

Consultant, Lean Thinker, Agilist, Technology Lover. Dream: Being worth a TED talk. Project Manager in a wide variety of business applications. Particularly interested in innovation projects, as well as close interaction with costumers.

Taggato con: , , ,
Pubblicato in API, Connector, Context.IO, Google Apps Script

Leave a Reply

Your email address will not be published. Required fields are marked *

*

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