Getting unread mail details from Google Apps via 2-legged OAuth in .NET
Don’t get me wrong, I’m very glad that the Google Apps .NET API library exists. Unfortunately, the documentation can be a little obscure, and there isn’t a lot in the way of example code around for it, especially when it comes to OAuth. Even the official documentation page has only a single .NET example, and that uses an API call that is deprecated in the latest version.
To make matters worse, getting user data out of Gmail isn’t really supported at all by the Google Apps API. You can change settings and provision accounts, but not get any actual email. However, there is a single feed for Gmail to retrieve unread email details in Atom format, and you can use it with 2-legged OAuth. This isn’t mentioned at all on the page that lists the API scopes, and there’s no official support for it. But it works.
The big advantage of using 2-legged OAuth, in case you’re unaware, is that you (as the Google Apps administrator) can create an application which retrieves data for your users without them having to supply their credentials or go through the standard OAuth approval mechanism. This is especially advantageous in, say, a web portal application in a school. You need to set up 2-legged OAuth in the control panel to get your consumer key and secret, but that’s the easy part.
“So… no example code, and no documentation. Sounds like fun.”
Not really, no. But it’s actually quite simple once you figure it out, and in fact only needs a single object from the official API – everything else can be done with standard .NET 2.0 functions. Here’s a very basic implementation that retrieves the total number of unread messages:
Imports Microsoft.VisualBasic Imports Google.GData.Client Imports System.Net Imports System.IO Imports System.Xml Dim sAppName As String = "domain.com" Dim sConsumerKey As String = "domain.com" Dim sConsumerSecret As String = "mysecretstring" Dim sUser As String = "test" Dim sDomain As String = "domain.com" Dim oURI As New Uri("https://mail.google.com/mail/feed/atom/") Dim oToken = New OAuth2LeggedAuthenticator(sAppName, sConsumerKey, sConsumerSecret, sUser, sDomain) Dim oReq As HttpWebRequest = oToken.CreateHttpWebRequest("GET", oURI) Dim oReader As New StreamReader(oReq.GetResponse.GetResponseStream) Dim oDoc As New XmlDocument oDoc.LoadXml(oReader.ReadToEnd)
OAuth2LeggedAuthenticator is the only object we’re using from the Google API here. The above example loads the entire feed into a System.Xml.XmlDocument object, from which you can browse the DOM using method calls such as .Item() (as in the above example) or using XPath via the .SelectSingleNode() or .SelectNodes() calls. If you choose the latter, you’ll need to use a namespace with your XPath queries due to the fact that the feed specifies the http://purl.org/atom/ns# namespace. Here’s an example where I grab the modified date of the first unread email:
Dim sNS As String = oDoc.DocumentElement.Attributes("xmlns").Value Dim oNsMgr = New XmlNamespaceManager(oDoc.NameTable) oNsMgr.AddNamespace("gm", sNS) Dim MostRecent As DateTime = DateTime.Parse(oDoc.SelectSingleNode("gm:feed/gm:entry/gm:modified", oNsMgr).InnerText)
In the example, I’ve used gm as my namespace prefix, but you can use whatever you want so long as it’s unique in the document.
A third method, which is particularly useful if you’re coding in Visual Web Developer, is to throw the entire raw XML back out via the .OuterText() call and into a System.Web.UI.WebControls.Xml control, where you can then parse it with an XSLT. I use this to present users with a tabular summary of their unread messages on our intranet portal, complete with direct links into the messages in their inbox.