Sunday 14 September 2008

Working with Protocols ...

Since my graduation, one of the things that fascinates me most is the technique that is followed to establish communication between two systems - "protocol". A protocol is like a language that the computers use to communicate between/among themselves.

Implementing protocols for a client/server based model is very interesting.Most of the times, we end up writing clients for existing servers. For example, we develop an FTP client (like Filezilla) or a POP3/IMAP client (like Thunderbird) or the most frequently used client - the HTTP client or the browser (like IE, Firefox, Google Chrome).

In this post, I would like to brief on what it takes to implement a client (like the ones above) based on a given protocol.

Of late, I have had a requirement in which I had to check a mailbox for the existence of an email (from a specific user and with a particular subject line), parse the subject and content of the email and do some processing based on the these two values. The processing part is a piece of cake, but what is a bit challenging is writing an email client that can log on to a given mailbox, check the messages and retrieve the subject and body of the email.Isn't it interesting?

To start with, I chose to go for an IMAP client and like any other protocol, the first thing that needs to be understood is the RFC (Request for Comment). An RFC is where the nitty-gritties of the protocol are documented.From the RFC, we get the commands that an IMAP server accepts and the response that the server sends to the client and this is the key information required to develop a client.

Here are a bunch of request-response scenarios in conjunction with IMAP (excerpts from http://bobpeers.com/technical/telnet_imap.php) :

Login:

. login accountname@myserver.com *********
. OK User logged in


LIST mailboxes:


. list "" "*"
* LIST (\HasChildren) "." "INBOX"
* LIST (\HasNoChildren) "." "INBOX.Drafts"
* LIST (\HasNoChildren) "." "INBOX.Sent Items"
* LIST (\HasNoChildren) "." "INBOX.Trash"
* LIST (\HasNoChildren) "." "INBOX.test1"
* LIST (\HasNoChildren) "." "INBOX.test2"
. OK Completed (0.460 secs 7 calls)


EXAMINE and SELECT commands:


. examine INBOX.test2
* FLAGS (\Answered \Flagged \Draft \Deleted \Seen)
* OK [PERMANENTFLAGS ()]
* 0 EXISTS
* 0 RECENT
* OK [UIDVALIDITY 1138801117]
* OK [UIDNEXT 1]
. OK [READ-ONLY] Completed


. select INBOX.test2
* FLAGS (\Answered \Flagged \Draft \Deleted \Seen)
* OK [PERMANENTFLAGS (\Answered \Flagged \Draft \Deleted \Seen \*)]
* 0 EXISTS
* 0 RECENT
* OK [UIDVALIDITY 1138801117]
* OK [UIDNEXT 1]
. OK [READ-WRITE] Completed



FETCH command:

Fetching flags on first and second messages:


. fetch 1:2 flags
* 1 FETCH (FLAGS (\Seen hasatt))
* 2 FETCH (FLAGS (\Seen hasatt))
. OK Completed


Fetch headers:


. fetch 1 rfc822.header
* 1 FETCH (RFC822.HEADER {824}
Return-Path: <nobody@server2.messagingengine.com>
Received: from web2.internal (web2.internal [10.202.2.211])
by server2.messagingengine.com (Cyrus v2.3-alpha) with LMTPA;
Wed, 01 Feb 2006 08:37:23 -0500
X-Sieve: CMU Sieve 2.3
X-Attached: This_is_how_attachments_appear.txt
X-Resolved-to: accountname
X-Mail-from: nobody
Content-Transfer-Encoding: 8bit
Content-Type: multipart/mixed; boundary="_----------=_1138801039165120"
MIME-Version: 1.0
X-Mailer: MIME::Lite 5022 (F2.73; T1.15; A1.64; B3.05; Q3.03)
Date: Wed, 1 Feb 2006 13:37:19 UT
From: "Email Administrator" <bounce@myserver.com>
Reply-To: webmaster@myserver.com
To: "Joe Bloggs" <accountname@myserver.com>
Subject: IMPORTANT: Click here to begin using your account
Message-ID: <cmu-lmtpd-28871-1138801043-0@server2.messagingengine.com>

)
. OK Completed (0.000 sec)


Fetch body:


. fetch 2 rfc822.text
* 2 FETCH (RFC822.TEXT {11658}
This is a multi-part message in MIME format.

--_----------=_1138865560223950
Content-Disposition: inline
Content-Length: 5194
Content-Transfer-Encoding: binary
Content-Type: text/plain

more text here.............

. OK Completed (0.000 sec)


LOGOUT command:


. logout
* BYE LOGOUT received
. OK Completed


Given the request-response pattern above, all that is left is to write code to open a network connection to the server @ port 143, send the requests out and read and interpret the responses :-) It's so simple !

1 comments:

FireMan said...

good post, first i not speak English, well
when i use . login user ******
my password have withspace and imap throw
bad command