[Imap-protocol] Where to start?

Pete Maclean imap at maclean.com
Sun Jun 5 12:24:13 PDT 2011

At 01:37 PM 6/5/2011, Lynn W. Taylor wrote:

>P.S. I'm not looking for a complete roadmap, I can fill in most of the detail.


>Tags and UIDs are not a big deal.


>What I want to do is get enough IMAP working that I can start

>testing with a client, even if the server isn't 100% practical,

>instead of implementing some critical command last, and finding out

>that I made some critical mistake very early in the process.

Here are 10 tips based on my own experience. From what you say, some
of these may not be relevant to your case but I will be inclusive. I
am also assuming both that you are not starting out intimately
familiar with the protocol and that messages are stored in
RFC2822-MIME format. A general guideline is that, while books may
help you get a feeling for IMAP -- they did for me, when actually
implementing it is vital to pay full attention to the relevant RFCs.

1). You will need a fairly sophisticated message parser, notably for
extracting MIME parts and generating BODYSTRUCTURE information. If
you do not start out with such a parser ready-made then you might
well choose to begin by building one.

2). If your mailstore does not have UIDs (or something that can be
suitably mapped into UIDs) then decide how you will create and store
UIDs. Incidentally IMAP specs refer to a UID command; I find it
easier to view this as a command qualifier.

3). Decide what permanents flags to support and how. Decide what
hierarchy delimiter to use; I believe that most servers use slash,
backslash or dot but I have not seen a problem using even a
non-graphic character such as Rubout (ASCII 127). By the way, I
think that RFC 3501 does not make this clear but the hierarchy
delimiter must be a 7-bit ASCII character.

4). Decide what data to keep in memory for each message in an open
mailbox. (By "open", I mean one for which a session is in progress,
that is opened as the result of a SELECT or EXAMINE command.) A
likely minimum would be UID, IMAP message flags, message size and, of
course, a reference to the message itself. I am assuming that this
information is indexed by message number and hence that that is not
explicitly stored. You may find reason to add more data such as a
flag indicating if the message is matched in a current SEARCH.

5). I don't recall if I did this when I wrote my server, but I would
probably start now by implementing the LIST command. This involves a
number of elements including modified UTF-7 encoding and
understanding the distinction between the two arguments of the
command. I wrote unit test programs for my backend LIST code (and
that of several other commands) and I highly recommend doing the
same. These were simple console programs each of which took a set of
IMAP command arguments as input and emitted the results as
output. In the early stages, testing with actual IMAP connections
(be they from a client or a test program) is unnecessarily
awkward. (I am assuming here that there are other means, outside of
the IMAP server, to create mailboxes; if this does not hold then you
may want to implement CREATE first.)

6). Next I would implement SELECT and EXAMINE. There are intricacies
here such as checking what rights the user in question has to the
mailbox and ensuring coordination among threads (and, if relevant,
with other programs) that are simultaneously accessing the mailbox.

7). Next I would implement FETCH. This is a biggie because of the
range of data items, macros, dealing with literals, and so on.

8). Perhaps at about this point, I would work on the command
processor (recognising commands, checking mode, parsing arguments,
etc.) and, unless I had a ready-made one, the listener. This allows
one to start testing online. I suggest implementing the command
processor at a fairly late stage because, for some commands,
argument-parsing is tricky and you will likely find it easier once
you have implemented the commands themselves and have a good
understanding of how they work -- although the critical thing to do
here is to follow the RFC's grammar very closely. AUTHENTICATION can
be done at any stage since you can fake it until such point as you
choose to made it real.

9). Next I would take care of the "minor" commands: CREATE, LSUB,
NOOP, CLOSE, STORE, CAPABILITY, APPEND, etc. But do not think of
COPY as minor -- it can be a substantial job because of the required atomicity.

10). I would leave SEARCH for last. When I wrote my server, I left
it to last because I feared it would be the most difficult to do. I
was wrong; it proved much easier than I had expected but it is,
nevertheless, a hefty amount of work. It may also be fair to say
that it is the least critical command but, all the same, it has to be
done and done completely (unless of course your client is intended to
work with a strictly limited set of clients that do not use it.) And
testing SEARCH can be hard because few clients implement it well;
indeed, some do not offer it at all. Of course, if your mailstore
manager already has search capabilities then you may be able to
leverage those and make the job a snap.

More information about the Imap-protocol mailing list