Saturday, October 11, 2008

Using Groovy to connect to GMail

Lately, I've been working on a project where I want to allow someone (namely, my wife) to email to-do items to my GMail account, which an automated process would then read, find the relevant items, then add them to this really useful GTD app I've been using, Tracks. The language I've been using over the last year or so to automate things like this is Groovy, and Groovy actually makes a task like this fairly easy

GMail also has made it easier if you want to automate some of your mail handling like I do: they provide access via regular POP3 and IMAP. IMAP is particularly useful because, if you have created labels in GMail (and I only know one person who hasn't ;)), GMail IMAP will treat those labels as IMAP folders. So there are basically two parts to this task: actually connecting to the GMail IMAP server, then interacting with the labels/folders in your account.

Connecting to GMail

GMail requires you to use SSL to connect to their servers, so the first thing I had to do was get GMail's certificate into a Java keystore. Based in part on the instructions in this blog post by Vincent Liu, here's what I did:

First, I connected to GMail's IMAP service with openssl:

openssl s_client -connect imap.gmail.com:993 -showcert


From the output of that session, I copied the lines from "-----BEGIN CERTIFICATE-----" to "-----END CERTIFICATE-----" (inclusive), to a text editor and saved it as the file gmail.pem. To make the certificate usable by Groovy, I then used openssl again to convert the PEM file to a DER format that I could import via Java's keytool utility.

openssl x509 -in gmail.pem -inform PEM -out gmail.der -outform DER


Just to make sure things were on the up-and-up, I viewed the resulting certificate:

keytool -printcert -file gmail.der

Then I imported the certificate into my keystore:

keytool -import -alias gmail.imap -file gmail.der


Interacting with GMail

Once the certificate was taken care of, I could get down to actually connecting to GMail with Groovy. One of the best things about Groovy is that it can make use of all the Java libraries that already exist for doing things like connecting to mail servers. I used the JavaMail libraries to do the real work of connecting to GMail, and there is some good documentation out there on how to use it. Here are some of the basics, though:

First off, you need to import the JavaMail classes (as well as java.util.Properties for initiating a JavaMail connection):

import javax.mail.*
import java.util.Properties

and then set some properties for your mail Session:

String gmailServer = "imap.gmail.com"
int gmailPort = 993

Properties props = new Properties();
props.setProperty("mail.store.protocol", "imaps");
props.setProperty("mail.imaps.host", gmailServer);
props.setProperty("mail.imaps.port", gmailPort.toString());

Note that the "mail.store.protocol" property is "imaps" NOT plain "imap". JavaMail added SSL support to all protocols in version 1.3.2.

Once you have those properties set, you can create a Session and connect to the GMail IMAP server (the Store, in JavaMail terms) via IMAPS:

def session = Session.getDefaultInstance(props,null)
def store = session.getStore("imaps")
store.connect(server, user, password)


With the connection to the Store, the next thing you probably want to do is see what's there. As I mentioned, GMail treats all your labels as IMAP folders. You can list the folders that are available, and then interact with the messages in whatever folder you're interested in:

store.defaultFolder.list().each { folder ->
println folder.name
}

def inboxFolder = "INBOX"
def folder = store.getFolder(inboxFolder)
folder.open(Folder.READ_ONLY)
folder.messages.each { msg ->
println "Subject: ${msg.subject}"
println "Sent on: ${msg.sentDate}"
println "From: ${msg.from}"
println "Content: ${msg.content}"
println "----------------------\n"
}


Once you're connected like this, you can interact with GMail as if it were any regular IMAP server, so check out the JavaMail API to see all the ways you can interact with a mail server.