Plan Finder Complete Guide Articles and Reviews Downloads About Us
Email Service Guide

Making Facebook’s messaging system IMAP compatible

1 Comment »
January 26th, 2010
Viktor Petersson

imapbookI’m actually surprised nobody has posted anything about this online, but it’s more or less possible to write an IMAP proxy for Facebook using their API. Sure, you could not write a full-fledge IMAP implementation, but you could get it to perform the most basic tasks, like reading messages (and therefore also store them locally).

I got the idea of making an IMAP proxy (or bridge, parser or whatever you want to call it) back in in August when Facebook announced new API calls to access the mailbox. Upon reading them, I realized that it could be used for a lot new things, such as this. Since then, I’ve been waiting for someone take on the challenge. I’ve been keeping an eye open for a projects in this area, but haven’t seen any. Therefore, I thought I might at least raise some interest and perhaps someone will take on the challenge.

Please note that this is in no way a complete guide on how to write this software, nor am I sure that it works — it just outlines some of the basic concept I’ve had on my mind for a while.

In this article I’ll try to outline the basics of writing this software. There are primarily three API calls that we need to work with to accomplish this:

  • Threads
  • Message
  • Mailbox folder

We also need to read up on RFC 1064, RFC 2342 and RFC 3501, as they outline the IMAP protocol.

Logging in

Logging in might be one of the trickier parts. The way you login to an IMAP server is to use the following command:

LOGIN username password

Facebook’s API is not quite as simplistic. I’m not quite sure what the best approach is here, but one way would be to have two-sided service. The first part is a web-interface. In order to use the proxy/bridge, you’d need to visit the website and approve the service using Facebook Connect (it would also require something called Extended Permissions as pointed out in the documentation for the Message API).

Once you have approved the web service using the web-interface, you would be able to connect to the second part of the equation, namely the IMAP server. Since you have previously approved the web-service, you should be able to replicate the IMAP login command above.

Listing folders

One important feature in IMAP is the ability to list folders. Luckily, Facebook’s structure looks very similar to a minimalistic IMAP setup. However, since you cannot add or delete folders in Facebook’s messaging system (yet), we can fake this response (since the structure is always the same).

The command you’d issue to the IMAP server is:

LIST "" *

Since we know from the Mailbox folder API description, there are only three folders. These folders are:

  • Inbox (folder_id 0)
  • Outbox (folder_id 1)
  • Updates (folder_id 4)

With this in mind, we can hard code the following response to the list command:

LIST (\HasChildren) "/" Inbox
LIST (\HasChildren) "/" Outbox
LIST (\HasChildren) "/" Updates

Selecting a folder

In IMAP, you use the following command to select a folder:

SELECT folder-name

Given Facebook’s query-based API, the closest thing to ‘selecting a folder’ in Facebook’s API is to add ‘WHERE folder_id = 0′ to the query. One way to implement this is if the server stores the latest SELECT command and automatically appends ‘WHERE folder_id = 0′ to the end of each query (since 0 is for Inbox, we’d append this string if the users the user previously issued ‘SELECT Inbox’)

Getting message content

The key in getting messages trough IMAP is a command named FETCH. The FETCH command comes with a lot of different modes, but we’ll focus on the most fundamental ones. These are (AFAIK) FLAGS, RFC822, RFC822.HEADER, RFC822.TEXT, RFC822.SIZE and UID. Since RFC822 is just RFC822.HEADER and RFC822.TEXT combined, we have one less variable to worry about.

One thing I haven’t really figured out yet is how to deal with the message number. Since we cannot assume that you will receive the message in the same sequence between queries, we probably need to always sort the list by message_id and then just give each message a number based on this list.

FETCH UID

Let’s start with UID, as this is the easiest one. You’d issue this command as follows:

FETCH 1:6 (UID)

The expected result would look something like this:

1 FETCH (UID 1029955483)
2 FETCH (UID 1029955484)
3 FETCH (UID 1029955485)
4 FETCH (UID 1029955486)
5 FETCH (UID 1029955487)
6 FETCH (UID 1029955488)

The equivalent command in Facebook’s API would be something like this (I’m not sure if it’s possible to combine queries like this, but you get the idea):

SELECT message_id FROM message WHERE thread_id IN (SELECT thread_id FROM thread WHERE folder_id = 0)

You would then use that output as the UID.

FETCH FLAGS

Flags are pretty simple too (since we don’t care much about the actual result). You’d issue the command as follows:

FETCH 1:2 (flags)

And the result would look like this:

* 1 FETCH (FLAGS (\Seen))
* 2 FETCH (FLAGS (\Seen))

As I mentioned above, we don’t really care much for the result here (as it’s not implemented on Facebook’s side), all we need to know is the number of messages in total (so that you cannot issue FETCH 1:999999999999 and get 999999999999 entries back if there are only 15 messages available). Since we already know how to get the message count, we simply use that and return ‘FLAGS (\Seen)’ to each message.

I suppose you could implement the \Seen flag properly as described in RFC 3501 in the IMAP server itself, but that is beyond the scope of this article.

FETCH RFC822.SIZE

The same goes for RFC822.SIZE as for FLAGS. Since we do not know the message size, the best thing we can do is to just define it to be an arbitrary (or perhaps a random) value.

You’d issue the FETCH RFC822.SIZE as follows:

FETCH 1:6 (RFC822.SIZE)

The expected result would look something like this:

1 FETCH (RFC822.SIZE 2401)
2 FETCH (RFC822.SIZE 2935)
3 FETCH (RFC822.SIZE 2214)
4 FETCH (RFC822.SIZE 2165)
5 FETCH (RFC822.SIZE 551351)
6 FETCH (RFC822.SIZE 1359)

FETCH RFC822.TEXT

RFC822.TEXT is also fairly easy. It’s simply the content of the message. The result from FETCH RFC822.TEXT command would look something like this:

FETCH 1 (RFC822.TEXT)

Where the server would respond with:

This is the body of the message

The Facebook equivalent would be:

SELECT body FROM message WHERE message_id=[the message_id the message number 1]

RFC822.HEADER

Ok, this is the tricky part. Now we need pull out quite a bit of data from Facebook and arrange it according to the IMAP RFC.

Here’s an example of how it would look in IMAP:

FETCH 1 (RFC822.HEADER)

The server would then return something like this for a message with a very minimalistic header:

Date: 27 Aug 76 0932 PDT
From: Ken Davis
Subject: Re: The Syntax in the RFC
Reply-To: Sam.Irving@Reg.Organization
To: George Jones
Message-ID: <4231.629.XYzi-What@Other-Host>

(Copied from RFC822)

With that in mind, all we need to do is to look up those values in Facebook’s API and rewrite them to match the example above.

From the Message API, we need to pull out the author_id and created_time. Since we’d like to know the name (not just the id of the person who sent the message, we also need to look up the name of the author_id.

Without going into the exact queries, the message header would look something like this:

Date: [created_at from the Message API]
From: [The real name from author_id in Message API] <[author_id from the Message API]@facebookmail.com>
Subject: [subject from Thread API]
Reply-To : no-reply@facebook.com
To: [real name from recipients in Thread API <[recipients from Threads API]@facebookmail.com>
Message-ID: <[message_id from Message API]@facebookmail.com>

That should be enough to make the header of the message compatible with the RFCs.

Folder status

You can get the ‘status’ of a folder in IMAP without having to open it with the STATUS command. There are four variables that can be used with the STATUS command, namely: MESSAGES, RECENT, UIDNEXT and UIDVALIDITY.

The most relevant variable here is the MESSAGES variable, as it gives a message count on the folder. You’d issue the command as follows:

STATUS Inbox (MESSAGES)

The return would look something like:

STATUS Inbox (MESSAGES 2)

This command can be replicated fairly simple with Facebook’s API. We could issue the command:

SELECT message_count FROM thread WHERE folder_id = 0

We would then use the result and replace the ’2′ in the example result above.

Deleting message

Deleting a message is not possible as far as I can tell.

Marking message as read/unread

Not possible either from what I can tell.

Search

Given that Facebook’s API is query based, search is one of the areas where it really excels. However, as the SEARCH command in IMAP is pretty complex, I’m not going to cover that. But just to give you an idea how search works in Facebook’s API, this is an example:

SELECT ... FROM thread WHERE CONTAINS('hello')

Logging out

It’s not necessary to implement any support for logging out in the Facebook side. We do however, need to implement this in the IMAP server. It’s very straight forward. When the client issues

LOGOUT

The remote server closes the connection. Simple as pie.

Conclusion

As I mentioned in the introduction, the intention of this guide is not to create a step-by-step guide on how to write an IMAP proxy for Facebook. It’s more a theoretical proof-of-concept that outlines fundamental features in IMAP and how they can be (with some work) replicated in Facebook’s API.

That said, I’d be happy to see if someone took this guide and continued to work on it and created a final product. I’d be even more happy if the person Open Sourced it.

Happy Hacking!

Be Sociable, Share!
  • Tweet
Tags: Facebook, IMAP Posted in Analysis 1 Comment »

One Response to “Making Facebook’s messaging system IMAP compatible”

  1. Tweets that mention Email Service Guide – Making Facebook’s messaging system IMAP compatible -- Topsy.com says:
    January 26, 2010 at 8:44 PM

    [...] This post was mentioned on Twitter by Email Service Guide, Email Service Guide. Email Service Guide said: Want to access facebook though IMAP? It's possible with some hacking and the API. This is how: http://bit.ly/5GEVfZ #facebook #imap [...]

  • RSS Feed
  • Facebook Fan
  • Twitter Feed

Latest Articles

  • 01/31 - Email Service Guide has been discontinued
  • 05/21 - This blog is more or less deprecated
  • 08/02 - Opolis — Revolutionary or just another email client?
  • 06/03 - Why your company shouldn’t move to Microsoft BPOS
  • 03/05 - reMail goes Open Source! What does it mean?
  • 02/15 - Email Marketing Part 4: 25 Tips To Optimize Your Campaign
  • 02/03 - Email Marketing Pt. 3: MadMimi, Aweber, Benchmark, iContact, CampaignMonitor Reviews
  • 01/28 - Atmail 6.1.3 is out. Now supports LDAP and Active Directory
  • 01/28 - Email Marketing Pt 2: MailChimp, ConstantContact, EmailBrain, LetterPop Reviews
  • 01/26 - Making Facebook’s messaging system IMAP compatible

Sponsored Link: Chronicle.im

The easy way to keep a diary or journal that goes with you wherever you go. All web, no downloads, totally free.
Chronicle.im Journal App


Sponsored Link: YippieMove

Need to transfer email between accounts? The YippieMove email migration tool lets you do that easily online.


Tags

    ActiveSync Android AOL apocalypse Atmail chat client collaboration Exchange Facebook FastMail.FM Gmail Gmail Labs Google Google Apps Google Wave Hotmail Hushmail IBM IMAP iNotes iPhone LotusLive Microsoft mobile Mozilla Open-Xchange Outlook phishing POP3 reMail review SaaS security social network spam T-Mobile threadsy Thunderbird Twitter VMware Windows Live Yahoo Zenbe Zimbra


Archives

  • January 2013
  • May 2011
  • August 2010
  • June 2010
  • March 2010
  • February 2010
  • January 2010
  • December 2009
  • November 2009
  • October 2009
  • September 2009

Connect with us!

  • Suggest an article
Got feedback, questions? Contact us. Advisory information only. Data may not be current or correct, prices and terms are based on our best interpretation of relevant user agreements. Database includes both affiliated and non affiliated providers. © 2009 WireLoad, LLC