Examining IMAP Messages

The following isn't an example, as much as it explains how message can be accessed via IMAP with aspNetIMAP.


The FetchClient and the MessageClient

The FetchClient and the MessageClient are both properties of the MailFolder object. The FetchClient maps closely to the Fetch command found in the IMAP RFCs. It is used for mainly fetching message data and content. The MessageClient doesn't have an appropriate counterpart in the IMAP RFCs. However, it is used for manipulating copying, deleting, and moving messages, along with manipulating message properties.

Message Numbers
A word about message numbers, and the IMAP message numbering scheme.

There are two numbering systems to reference messages in the mail folder. Messages can be referenced by their ordinal position, or by a unique identifier (UID). Multiple message numbers can be separated by commas or can be designated with a '*', which refers to the highest message number in the mail folder. A pair of numbers, separated by a ':', indicates a contiguous set of messages ranging from the first message number to the second. These ranges of message numbers are called 'message sets'. Message numbers, referenced by their ordinal index, are always ascending and always contiguous.

As an example, here are some message sets, and the respective messages they represent. All of the numbers used in this example, reference the messages by their ordinal index. This example also assumes there are 7 messages in the mail folder.

 

MessageSet Actual Message Numbers
1 1
2, 5 2 5
1:* 1 2 3 4 5 6 7
5:* 5 6 7
1,2,5,7 1 2 5 7
2:5 2 3 4 5
1,3:5,7 1 3 4 5 7
1:3, 5:7 1 2 3 5 6 7
1,3:5,6:* 1 3 4 5 6 7
 

 


These properly formatted message sets can be used when various aspNetIMAP methods accept the messageSet parameter. Although this example uses

Ordinal Indexes, the same technique (using commas ',' and asterisks '*' ) can be used with UID's (Unique Identifiers).


Ordinal Indexes
IMAP uses a 1 based indexing system. Thus a message with index 1 will actually reference the first message in the mail folder. This may be different that what some developers are used too. For example, C# or C++ uses a zero based index, thus the first message in the mail folder will have an index of zero.

The primary difficulty with the ordinal index number scheme is that the message sequence numbers can change as messages are Expunged (MessageClient.PurgeDeletedMessages()). For example, message 5 becomes message 4 after message 2 has been Expunged. Thus all message numbers greater than a deleted messages, are re-numbered, and decremented by the number of messages deleted. Also, as messages are added to the mail folder, they are added to the higher end of the ordinal indexes. For example, if a mail folder has 7 messages in it, and a new message is received, or added, the new message becomes message number 8.

Another problem with ordinal indexes, is that they are valid, only for the session the client is connected to the server. For example, lets say a client is interested in message number 7. If that client disconnects, and another client connects, and Deletes and Expunges the message number 3, message number 7 now becomes message number 6. Thus when the first client reconnects, it has no way of knowing that the messages was renumbered.

 

This led to a second numbering scheme called Unique Identifiers.

Unique Identifiers (UIDs) Index
IMAP assigns a unique identifier to every message found in a mail folder. This is a 32 bit integer, and has to be unique, and constant for a given message, whether or not a new message has been added (%Appended:Append%), received, or %Expunged:PurgeDeletedMessages%. Unique Identifiers are assigned in ascending order, but there is no requirement for them to be contiguous.

Because Unique Identifiers must be ascending numbers in the mail folder, a physical reordering of the mail folder would cause them to be out of sequence. When messages are renumbered with a new set of UIDs, the unique identifiers must be recalculated, invaliding those referenced by the client's cache. To handle this reordering, each mail folder is also assigned a 32 bit integer called a unique identifier validity (UID-validity). If a mail folder's messages are reordered, a new validity value is assigned to the mail folder. This new validity value, MUST be greater than the previous validity value. The validity is also changed, if a mail folder is deleted and recreated.

The combination of Unique Identifiers and mail folder validity provides a mechanism for clients to cache messages, and a way to determine if that cache is valid.

Message Flags
The MessageClient class also deals with Marking,  UnMarking, and SettingFlags, messages with various flags. These flags are discussed below.

Messages often have status information associated with them, such as including whether a message is new, has been answered, seen, or even marked for deletion. It is interesting to note, that when a message is deleted, it is only marked for deletion. It is not until PurgeDeletedMessages() is called, that the messages are removed from the mail folder. Thus a message can be deleted, or undeleted, simply by removing the \deleted flag.

There are two types of flags: system flags and keywords. The MessageClient deals specifically with System flags, System flags are always prefixed with the '\' character, to distinguish them from keywords. At the time of this writing, there are 6 system flags. They are:

 

Flag Description
\answered A message has been replied to.
\deleted A message is marked for deletion, and will be physically removed when Expunge or Purge is called.
\draft A message is incomplete, and has not been fully composed by the user.
\flagged A message is flagged or marked as important
\recent A recent message to arrive in the mail folder.
\seen A message has been read.