Getting Gmail labels using javamail

January 29, 2013

I’ve been working with Gmail using javamail library for a long time now, the standard IMAP/SMTP capabilities were quite enough, even to deal with the labels. But recently I decided to also pull the gmail custom attributes: X-GM-THRID and X-GM-LABELS (see Gmail Imap Extensions).

At first it looked like there was no easy way to fetch those custom attributes using the standard javamail FetchProfile mechanism so I went searching in Google.

I found the  java-gmail-imap project which was quite encouraging but after studying it more I figured that I did want to use it:

  1. It incorporated javamail 1.4.4 and I really needed some new 1.5.x functionality
  2. A lot of original javamail classes if not all were extended/re-written which seemed like an overkill
  3. Last release was on Mar 23, 2012

So I went exploring further.

I must say that I really do appreciate that so much code these days is open source. Both java-gmail-imap and javamail sources showed me what was really happening under the hood and I came up with a simpler hack which only requires one extended class.

I’ll explain the hack here and if you want my code let me know.

So, for a list of messages that I am reading from Gmail I now do a standard javamail profile fetch:

folder.fetch(msgs, stdFetchProfile);

followed by my custom fetch using IMAPFolder’s doCommand():

final MessageSet[] mSets = MessageSet.createMessageSets(mns);
((IMAPFolder) folder).doCommand(new IMAPFolder.ProtocolCommand() {

	public Object doCommand(IMAPProtocol p) throws ProtocolException {
		try {
			Response[] r = p.fetch(mSets, "X-GM-LABELS X-GM-THRID");
			for (int i = 0; i < r.length; i++) {
				if (!FetchResponse.class.isInstance(r[i]))

				// Got a FetchResponse.
				GmailFetchResponse gfr = new GmailFetchResponse(
								((FetchResponse) r[i]).toString());
				// Use gfr.getNumber() to get the msg number
				for (int j = 0; j < gfr.getItemCount(); j++) {
					Item item = gfr.getItem(j);
					if (X_GM_LABELS.class.isInstance(item))
						// get the labels
						((X_GM_LABELS) item).x_gm_labels);
		} catch (ProtocolException e) {
			logError(e.getMessage(), e);
		return null;

GmailFetchResponse is the class I had to create by extending Javamail’s Response. It’s aware of the X-GM-* attributes and I make it re-parse the response received in the standard FetchResponse. I used only the required part of the java-gmail-imap’s parse() method:

private void parse() throws ParsingException {
		if (buffer[index] != '(')
			throw new ParsingException(
					"error in FETCH parsing, missing '(' at index " + index);

		Vector v = new Vector();
		Item i = null;
		do {
			index++; // skip '(', or SPACE

			if (index >= size)
				throw new ParsingException(
						"error in FETCH parsing, ran off end of buffer, size "
								+ size);

			switch (buffer[index]) {
			case 'X':
				if (match( {
					index +=;
					i = new X_GM_MSGID(this);
				if (match( {
					index +=;
					i = new X_GM_THRID(this);
				if (match( {
					index +=;
					i = new X_GM_LABELS(this);
			if (i != null)
		} while (buffer[index] != ')');

		index++; // skip ')'
		items = new Item[v.size()];

X_GM_LABELS* classes I copied from java-gmail-imap project, they’re very simple. I only added required UTF-7 conversion:

public class X_GM_LABELS implements Item {

	static final char[] name = { 'X', '-', 'G', 'M', '-', 'L', 'A', 'B', 'E', 'L', 'S' };
	public int seqnum;

	public String[] x_gm_labels;

	public X_GM_LABELS(GmailFetchResponse r) throws ParsingException {
		seqnum = r.getNumber();
		x_gm_labels = r.readAtomStringList();
		if (x_gm_labels != null)
			for (int i = 0; i < x_gm_labels.length; i++)
				try {
					x_gm_labels[i] = new String(
				} catch (UnsupportedEncodingException e) {

That is all. With one additional custom fetch call (which is not a huge overhead) you have read the Gmail attributes for your messages.

I hope this can be useful for others.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s

%d bloggers like this: