2009-03-21

Gmail4J - Gmail API for Java



Seems that Google has no Gmail API available, so I made a small Java library called Gmail4J. The library is designed to be extensible, allowing various implementations. Currently the only available implementation allows getting new unread messages from their RSS feed. That's not much, but it's a start.

Here is the example code (updated to conform with Gmail4J 0.2):

GmailClient client = new RssGmailClient();
GmailConnection connection = new HttpGmailConnection("user", "pass".toCharArray());
client.setConnection(connection);
final List<GmailMessage> messages = client.getUnreadMessages();
for (GmailMessage message : messages) {
System.out.println(message);
}

Next implementation will probably be based on JavaMail IMAP functionality. It should be able to do more than getting unread messages.

15 comments:

  1. init() is ugly. If you know something is going to be in two states, just use two types. Makes runtime errors compile-time ones.

    ReplyDelete
  2. @Dimitris, I don't see why initialization is ugly. It's common for setter based configuration and it allows additional flexibility that may be required in future implementations.

    Concerning runtime vs compile time exceptions - I believe it's developers right to choose whether to check for an exception or to keep the code minimal without unnecessary try/catch blocks.

    ReplyDelete
  3. Tomas, Dimitris said why. It makes runtime errors compile time errors. Javas ONE benefit over everything else at the moment is catching potential runtime errors.

    This would be much nicer:

    GmailClient x = ...

    GMailConnection connection = new GMailConnection(x);
    for( GmailMessage g : connection )
    ...

    ReplyDelete
  4. Ah, now I got the point. I'll look forward into this. Thanks for the tip.

    ReplyDelete
  5. Cool, Tomas!
    Waiting for next version with more functions implemented.

    ReplyDelete
  6. Tomas,
    I failed to run Gmail4J for my Gmail account. the exception I get:

    Exception in thread "main" com.googlecode.gmail4j.GmailException: Failed getting unread messages
    at com.googlecode.gmail4j.rss.RssGmailClient.getUnreadMessages(RssGmailClient.java:110)
    at my.test.GMail4jTest.main(GMail4jTest.java:406)
    Caused by: java.net.ProtocolException: Server redirected too many times (20)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1180)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:234)
    at com.sun.syndication.io.XmlReader.<init>(XmlReader.java:237)
    at com.sun.syndication.io.XmlReader.<init>(XmlReader.java:213)
    at com.googlecode.gmail4j.rss.RssGmailClient.getUnreadMessages(RssGmailClient.java:100)
    ... 1 more

    ReplyDelete
  7. @asolntsev
    Are you behind some proxy? Currently using proxies is quite tricky, I'm going to fix that soon. And there is a possibility that you have entered your user/pass incorrectly

    ReplyDelete
  8. There is probably a good reason there isn't a Gmail api such as it supports industry standard apis like IMAP and POP3.

    ReplyDelete
  9. @Anonymous
    Some people would rather use something simple and straightforward instead of bloated all-purpose enterprise libraries like JavaMail.

    ReplyDelete
  10. This comment has been removed by the author.

    ReplyDelete
  11. By the way, I had also built a very, very simple API to send emails through gmail: http://139.91.183.8:3026/hudson/job/EasyMail/javadoc/

    (remove "javadoc/" to get to the software)

    MailSession session = MailSessionFactory.gmail("user", "pass");

    HtmlMail mail = session.newHtmlMail();
    //HtmlMail is from apache.org

    mail.setTo(...)
    mail.setSubject(...)
    mail.setText(...)
    Attachments.zip(new File("folderToZip/"), "myFolder.zip").attachTo(mail);

    mail.send();

    All this, because I just hate trying to find the "right" configuration each time for using JavaMail (which usually ends with a googling marathon), and this allows me to send mails with attachments in 5 or so lines, without any thinking.

    I would be interested in an API that simplifies retrieving mails too, of course.

    By the way, my initial comment perhaps wasn't too clear. init() implies that the GmailClient object is in two states, uninitialized and initialized. Presumably, calling methods that assume initialization would fail *at runtime*. The mechanical way to fix it is to define two types. A type that only defines "init()" and returns a second type, which define the methods that assume initialization. This simple and powerful design technique would make such runtime errors simply impossible.

    Yet, it is obviously an overkill here: the one of two states seems totally useless. Why put the burden of calling init to the user, and not simply create a properly initialized GmailClient, removing init() *and* the possibility of runtime errors due to uninitialized state, simplifying significantly the api. The previous advice would be applicable if both states were actually useful.

    ReplyDelete
  12. I've done some changes, now use case looks like this:

    GmailClient client = new RssGmailClient();
    GmailConnection connection = new HttpGmailConnection(user, pass);
    client.setConnection(connection);
    for (GmailMessage message : client.getUnreadMessages()) {
    System.out.println(message);
    }

    ReplyDelete
  13. Does anyone have any idea why gmail is STILL down? I haven't been able to access my gmail account since mid afternoon Central Europe Time...

    ReplyDelete
  14. Hello everybody,
    I have the follow code, but I got a error at line with method getContentText(). Please could someone help me? Best regards.
    package readgmail;

    import com.googlecode.gmail4j.GmailClient;
    import com.googlecode.gmail4j.GmailConnection;
    import com.googlecode.gmail4j.GmailMessage;
    import com.googlecode.gmail4j.auth.Credentials;
    import com.googlecode.gmail4j.javamail.ImapGmailClient;
    import com.googlecode.gmail4j.javamail.ImapGmailConnection;

    public class ReadGmail {

    public static void main(String[] args) {

    GmailConnection conn = new ImapGmailConnection();
    conn.setLoginCredentials(new Credentials("username", "password".toCharArray()));
    GmailClient client = new ImapGmailClient();
    client.setConnection(conn);
    for (GmailMessage message : client.getUnreadMessages()) {
    System.out.println(message.getFrom());
    System.out.println(message.getSubject());
    System.out.println(message.getContentText()); /* got error at this line as follow below:

    Exception in thread "main" java.lang.UnsupportedOperationException: This GmailMessage implementation does not provide getContentText()
    at com.googlecode.gmail4j.GmailMessage.getContentText(GmailMessage.java:199)
    at lergmail.LerGmail.main(LerGmail.java:28)
    Java Result: 1
    */
    }
    }
    }

    ReplyDelete
  15. Can you please describe the steps to use it in eclipse ? Will it require both email id and password ?

    ReplyDelete

Spam comments (i.e. ones that contain links to web development services) will be reported along with user profiles!

Note: only a member of this blog may post a comment.