Monday, May 9, 2011

Accessing Gmail accounts from App Engine with Context.IO

This is part of our on going series of blog posts from guest authors highlighting success stories from applications and services built on or targeting App Engine developers. Today, we have a post from Bruno Morency of Context.IO. Bruno has been involved in startups since graduating from McGill Engineering in 2001. And since being introduced to Pine on UNIX terminals, he’s had a love-hate relationship with email.

Email mailboxes contain years of important conversations and business information yet there are no easy ways for App Engine developers to find and use that information. This is what Context.IO does. It’s the missing email API that turns mailboxes into a data source developers can leverage. This is particularly interesting for Google App Engine developers since it makes content of Gmail accounts (and any other IMAP accessible email account) available through a set of HTTP calls.

In this post, we’re going to walk you through using Context.IO to build an app that lets users search for contacts from their inbox then easily get the history of recent emails and attachments exchanged with these contacts. A working demo is available at http://contextio-demo.appspot.com. The code for this application is available on Context.IO’s GitHub account.

Querying the mailbox

Our demo is quite simple in its functionality: there’s a search box used to find contacts, and once a contact has been found, we list recent emails and attachments associated with the contact. To do this, the application offers 3 urls that are called by the JavaScript running in the browser to obtain the data: search.json, messages.json and files.json.

The actual UI formatting is all implemented in the JavaScript running in the browser, but our focus here is how we get that data out of the mailbox and return it to the browser.

Let’s see how we respond to the request to get message history for a given contact. This is done by calling /messages.json which accepts an email address as a GET parameter. Note, this functionality requires an authentication step not shown here. The code behind that call is as follows:

class MessagesHandler(webapp.RequestHandler):
    def get(self):
        current_user = users.get_current_user()
        current_email = current_user.email()

        emailAddr = self.request.get('email')
        contextIO = ContextIO(api_key=settings.CONTEXTIO_OAUTH_KEY,
                              api_secret=settings.CONTEXTIO_OAUTH_SECRET,
                              api_url=settings.CONTEXTIO_API_URL)
        response = contextIO.contactmessages(emailAddr,account=current_email)
        self.response.out.write(simplejson.dumps(response.get_data()))

The code simply uses the contactmessages.json API call of and returns all the messages including the subject, other recipients, thread ID, and even attachments in JSON format. Check the documentation for a complete breakdown of the response.

You can see how we handle the other cases similarly in handlers.py. To get a complete overview of other calls offered by Context.IO, please refer to the documentation available here http://context.io/docs/latest.

Building your own email based application

The complete code for this demo application has been made available by the Context.IO team on our GitHub account. Feel free to use it as the base for your own application. To get started, you’ll need to setup your application with your own Google API authorization and Context.IO API keys.

If you have questions about using Context.IO to embed your user’s email in your app, feel free to contact us through http://support.context.io.

Posted by Bruno Morency, Co-founder of Context.IO

6 comments:

Michael said...

How does this work for IMAP accounts? To access an IMAP server I would think you need sockets, which GMail doesn't support.

Bruno said...

Hi Michael. Context.IO will work great with standard IMAP accounts. Since it exposes the mailbox through HTTP calls, you basically by-pass the sockets limitation.

To configure standard IMAP accounts, you still add the mailbox using the http://context.io/docs/1.1/imap/addaccount call instead of using OAuth, you set it up with credentials.

Michael said...

Whoops! In my previous comment I meant to say that GAE doesn't support sockets, not that gmail doesn't. Given that, I'm guessing that Context.IO is not built on top of GAE, it's just meant for GAE developers.

I logged in and this seems very cool. Will definitely investigate further when I get the chance.

huangwei said...

hi, why i can't be authed by oauth in google appengine apps when i send a post request with request body. but get request works. link http://stackoverflow.com/questions/5943562/oauth-issue-in-google-appengine-developing

Spike said...

Traceback (most recent call last):
File "/base/python_runtime/python_lib/versions/1/google/appengine/ext/webapp/__init__.py", line 700, in __call__
handler.get(*groups)
File "/base/python_runtime/python_lib/versions/1/google/appengine/ext/webapp/util.py", line 68, in check_login
handler_method(self, *args)
File "/base/data/home/apps/contextio-demo/1.350227693224167483/imapoauth.py", line 87, in get
gdocs.auth_token = gdocs.get_access_token(request_token)
File "/base/data/home/apps/contextio-demo/1.350227693224167483/gdata/client.py", line 610, in get_access_token
response, RequestError, response_body)
RequestError: Unable to upgrade OAuth request token to access token: 400, The request token is invalid.

Kaipa Kartik said...

How do I get the info if my application is deployed on Google App Engine with no domain. How do I register my application in that case and get the APPENGINE_CONSUMER_KEY = ''
APPENGINE_CONSUMER_SECRET = ''
Thanks a lot. I really need some help on this.