Imap E Mail Client

=== l ===

Contents

1 Introduction 7

1.1 Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

1.2 Structure of the thesis . . . . . . . . . . . . . . . . . . . . . 8

2 IMAP and Related Technologies 9

2.1 Basic Concepts . . . . . . . . . . . . . . . . . . . . . . . . . 9

2.2 IMAP-specific Attributes . . . . . . . . . . . . . . . . . . . . 10

2.3 MIME . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

2.3.1 Message as a Container . . . . . . . . . . . . . . . . . 12

2.3.2 International Characters in Messages . . . . . . . . . 13

2.3.3 MIME Support in IMAP . . . . . . . . . . . . . . . . 13

2.4 IMAP Protocol Flow . . . . . . . . . . . . . . . . . . . . . . 14

2.4.1 Commands and responses . . . . . . . . . . . . . . . 14

2.4.2 Mailbox Synchronization . . . . . . . . . . . . . . . . 15

2.4.3 Changes to Mailbox . . . . . . . . . . . . . . . . . . 16

2.4.4 Fetching and Manipulating Messages . . . . . . . . . 17

2.4.5 Queries Against Other Mailboxes . . . . . . . . . . . 18

2.4.6 Searching, Sorting and Threading . . . . . . . . . . . 18

2.4.7 Manipulating Mailboxes . . . . . . . . . . . . . . . . 18

2.4.8 Session termination . . . . . . . . . . . . . . . . . . . 19

2.4.9 IMAP Extensions . . . . . . . . . . . . . . . . . . . . 19

2.5 Other Methods of Mail Store Access . . . . . . . . . . . . . 20

2.5.1 POP3 . . . . . . . . . . . . . . . . . . . . . . . . . . 20

2.5.2 MAPI . . . . . . . . . . . . . . . . . . . . . . . . . . 20

2.5.3 Webmail . . . . . . . . . . . . . . . . . . . . . . . . . 20

2.5.4 IMAP Criticism . . . . . . . . . . . . . . . . . . . . . 21

3

3 Trojita Design 23

3.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23

3.2 Model-View Architecture . . . . . . . . . . . . . . . . . . . . 25

3.3 Parser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26

3.3.1 Low-level Parser . . . . . . . . . . . . . . . . . . . . 26

3.3.2 Parser . . . . . . . . . . . . . . . . . . . . . . . . . . 27

3.4 Cache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28

3.5 Streams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28

3.6 Model in Detail . . . . . . . . . . . . . . . . . . . . . . . . . 29

3.6.1 The Tree . . . . . . . . . . . . . . . . . . . . . . . . . 29

3.6.2 Proxy Models . . . . . . . . . . . . . . . . . . . . . . 32

3.6.3 Offline and Expensive Network Mode . . . . . . . . . 33

3.7 Message View . . . . . . . . . . . . . . . . . . . . . . . . . . 33

3.7.1 Network Manager . . . . . . . . . . . . . . . . . . . . 34

3.7.2 Widget Factory . . . . . . . . . . . . . . . . . . . . . 35

3.7.3 HTML Mail . . . . . . . . . . . . . . . . . . . . . . . 36

3.8 GUI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36

4 Other IMAP Implementations 38

4.1 Alpine 2.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38

4.2 Mutt 1.5.19 . . . . . . . . . . . . . . . . . . . . . . . . . . . 39

4.3 KMail 3.5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39

4.4 Mozilla Thunderbird 2.0 . . . . . . . . . . . . . . . . . . . . 40

4.5 Mailody . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41

4.6 Outlook Express . . . . . . . . . . . . . . . . . . . . . . . . 42

4.7 Windows Live Mail . . . . . . . . . . . . . . . . . . . . . . . 43

4.8 Trojita . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43

5 User’s Guide 45

5.1 About Trojita . . . . . . . . . . . . . . . . . . . . . . . . . . 45

5.2 Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . 45

5.2.1 Prerequisites . . . . . . . . . . . . . . . . . . . . . . . 45

5.2.2 Obtaining source code . . . . . . . . . . . . . . . . . 46

5.2.3 Installing . . . . . . . . . . . . . . . . . . . . . . . . 46

5.3 Using Trojita . . . . . . . . . . . . . . . . . . . . . . . . . . 47

5.3.1 Configuration . . . . . . . . . . . . . . . . . . . . . . 47

5.3.2 Basic usage . . . . . . . . . . . . . . . . . . . . . . . 48

5.3.3 Managing Messages and Mailboxes . . . . . . . . . . 49

4

5.3.4 Message Composition . . . . . . . . . . . . . . . . . . 50

5.3.5 Checking Mail . . . . . . . . . . . . . . . . . . . . . . 50

5.4 Advanced usage . . . . . . . . . . . . . . . . . . . . . . . . . 50

5.4.1 Partial Message Fetching . . . . . . . . . . . . . . . . 50

5.4.2 Offline Mode . . . . . . . . . . . . . . . . . . . . . . 50

5.4.3 Expensive Network . . . . . . . . . . . . . . . . . . . 50

5.4.4 Online Mode . . . . . . . . . . . . . . . . . . . . . . 51

5.4.5 Local Cache . . . . . . . . . . . . . . . . . . . . . . . 51

5.4.6 Full Tree View . . . . . . . . . . . . . . . . . . . . . 52

6 Conclusion 53

Bibliography 55

A Contents of the CD 59

5

N´azev pr´ace: IMAP E-mail Client

Autor: Jan Kundr´at

Katedra (´ustav): Katedra softwarov´eho inˇzen´yrstv´ı

Vedouc´ı bakal´aˇrsk´e pr´ace: Mgr. Vlastimil Babka

E-mail vedouc´ıho: [anonimizat]

Abstrakt: Pˇredloˇzen´a pr´ace popisuje implementaci pokroˇcil´eho klienta pro

pr´aci s poˇstou pomoc´ı protokolu IMAP. Hlavn´ım zamˇeˇren´ım je podpora

relevantn´ıch standard°u s d°urazem na efektivn´ı implementaci; vyuˇz´ıv´a se

pokroˇcil´ych vlastnost´ı IMAPu, jako napˇr´ıklad IDLE notifikac´ı, parsov´an´ı

zpr´av na stranˇe serveru ˇci lok´aln´ıho ukl´ad´an´ı e-mail°u s moˇznost´ı pr´ace of-

fline. Spojen´ı s IMAP serverem je realizov´ano protokolem TCP s volitelnou

moˇznost´ı TLS ˇsifrov´an´ı ˇci pˇres lok´alnˇe beˇz´ıc´ı proces. Projekt umoˇzˇnuje psan´ı

a odes´ıl´an´ı jednoduch´ych mail°u, podporov´ano je odes´ıl´an´ı pomoc´ı protokolu

SMTP a sendmailem. C´ılov´a platforma je framework Qt na Linuxu, avˇsak

aplikace je portovateln´a i na jin´e platformy.

Kl´ıˇcov´a slova: IMAP, e-mail, MIME, Qt, SMTP

Title: IMAP E-mail Client

Author: Jan Kundr´at

Department: Department of Software Engineering

Supervisor: Mgr. Vlastimil Babka

Supervisor’s e-mail address: [anonimizat]

Abstract: This thesis describes the implementation of an advanced IMAP

e-mail client, Trojita. Focusing on standards compliance, the client sup-

ports a wide range of IMAP features crucial for an efficient implementation

such as IDLE notifications, server-side message parsing and caching of re-

trieved body data for offline operation. Connecting to the IMAP server is

supported over TCP sockets, optionally secured via the TLS encryption, as

well as through a local process. Basic message composition and sending via

both SMTP and a local sendmail instance is supported. The target platform

is the Qt framework on Linux, but the application is reasonably portable.

Keywords: IMAP, e-mail, MIME, Qt, SMTP

6

Chapter 1

Introduction

Although being surpassed in popularity by other technologies like the World

WideWeb and peer-to-peer applications, the electronic mail is still one of the

few services that an average user can name when talking about the Internet.

There are many ways how to send and receive e-mail, some of them being

more popular than the others. In this thesis, we try to resurrect the older

approach to reading e-mail, that is, using an standalone application.

In the recent years, the improvements in the field of web browsers and

related technologies allowed rapid development of new features that were

not conceivable just five years ago. Using these new functions, the popular-

ity of web-based e-mail readers grew accordingly. However, using a proper

standalone application has numerous benefits from being able to work when

not connected to the Internet to providing a truly instant feedback, a feature

that is still somewhat missing from most of the web applications. Managing

e-mail over a standardized protocol also avoids vendor lock-in, a highly dan-

gerous phenomenon associated with using proprietary messaging solutions.

To date, the Internet Message Access Protocol [1] (or IMAP) is the only such

protocol.

1.1 Motivation

Implementing an IMAP client is far from trivial. While there are certainly

numerous stable and widely-used Mail User Agents on the market, none of

them fulfills all the expectations of reasonable performance and efficiency.

Indeed, most of these applications started as MUAs speaking the POP3

protocol only, adding support for IMAP later on. Typically, this support

7

was implemented long since the initial design phase of the product was

completed, resulting in suboptimal design choices [2]. Therefore, we believe

there is still a place on the market for a stable, highly performing IMAP

e-mail application.

1.2 Structure of the thesis

In the following chapter, we provide a gentle introduction to the world of

IMAP and related standards such as MIME. Chapter 3 explains some of

the design choices made during the development process of Trojita, as well

as elaborates on the internal application architecture and structure. An

overview of other IMAP implementations on the market is provided in chap-

ter 4, including a comparison about how well they operate when compared to

Trojita. The User’s Guide is available in chapter 5. Finally, the whole thesis

is concluded by a wrap-up providing an overview of what we implemented

and how the result is usable.

8

Chapter 2

IMAP and Related

Technologies

Electronic mail, or a SMTP-mail, is a public service suitable for automated

message exchange among connected entities. Interoperability is guaranteed

by several Internet standards, usually codified in the form of RFC docu-

ments. Subject to these standards are various protocols specifying the rules

of what entities can communicate to each other as well as definition of the

format of all transmitted messages. In this section, we provide a gentle in-

troduction to the numerous standards which deal with this highly complex

topic.

2.1 Basic Concepts

An email message, or a RFC-8221 message, consists of three parts: Envelope,

Header and Body. The envelope is the only relevant part for mail exchange

among Internet hosts; it includes basic information like addresses of the

sender and recipient. A header provides more detailed metadata about the

message, from human-readable sender addresses and message route traces

to user-defined fields. Some pieces of this information are used when the

original delivery fails for some reason, like the Return-Path header. The

header also serves as a basis for an IMAP envelope data which is explained

later in chapter 2.2. Finally, a message body is what an average user typically

1As defined by the RFC 822 standard and subsequently modified by RFC 2822 [3] and

others

9

refers to as “the e-mail”. It might contain just a plain US-ASCII text, an

HTML message with embedded images or it could be a recursively defined

entity with rich tree structure.

An IMAP server is a host in the Internet which provides access to local

mail store via the standard protocol, IMAP4rev1 in this case. The IMAP

server might be located in an employer’s data center or on the user’s laptop,

for example.

An MTA2 or an SMTP Server is an Internet host whose purpose is de-

livery of the RFC 2822 mail. MTAs in the Internet communicate with each

other, determining routing information from MX-records3 in the DNS. As a

common practice nowadays, these servers also accept outgoing e-mail from

their own users, provided the connection is properly authenticated, either

by simple fact that it originates from a trusted network or that the user has

provided her credentials, typically as a user name and password combination

or in the form of an X.509 certificate.

A Mailbox or a Mail Folder is a place on the IMAP server where the

messages are logically stored. A mailbox might contain number of child

mailboxes if the server implementation allows it. Certain IMAP servers have

to be told in advance whether the mailbox just being created is supposed to

contain only other mailboxes or only regular e-mail messages, while others

allow free mixing of both.

2.2 IMAP-specific Attributes

A message in the IMAP sense is immutable, that is, its contents (e.g., header,

structure of the body or the actual message parts) cannot change, ever. Each

message also has mutable attributes, the most important being flags.

Messages in a remote IMAP mailbox are identified by two partially in-

dependent numbers, the sequence number and the UID. Sequence numbers

start at one and are consecutive, that is, they dynamically change when

a message in the middle of the mailbox is removed. This means that one

particular message can have multiple sequence numbers assigned over time

and that one sequence number can refer to totally unrelated messages, as

the numbering changes.

2Mail Transfer Agent

3Mail eXchange, a special record in the Domain Name Service which specifies what

servers are responsible for accepting all incoming e-mail for the particular domain

10

On the other hand, the UIDs work differently. When a message is de-

livered to the mailbox, it receives a UID one greater than the previous one.

After the UID is assigned, it will never change for that particular message,

and the mailbox remembers the biggest assigned UID so far. This means

that UIDs are never recycled over the normal life span of a mailbox and they

can be used as a persistent identifier to one message in a particular mailbox.

Sometimes a non-standard situation might happen, e.g., when a third-

party accessed the mailbox data behind the back of the IMAP server. Per-

haps the user tried a utility program that removes huge attachment from an

otherwise valuable message, or a spam classifier modified message headers

directly, bypassing standard mechanisms for proper flagging. In any such

case, the IMAP guarantee of immutable nature of the messages does not

hold, and a compliant IMAP server has to communicate this problem to all

clients. The UIDVALIDITY mailbox attribute serves this purpose. When-

ever the UIDVALIDITY changes, a compliant client is required to throw

away any cached information about a mailbox because the UID assignment

starts over again.

UID and UIDVALIDITY combined together form a 64bit integer which

is absolutely guaranteed to be a unique identifier for any message in the

given mailbox – if the IMAP client once retrieved any immutable part from

mailbox A with this 64bit identifier, subsequent queries for the part identified

by the same 64bit number in the same mailbox can be satisfied from the

client’s cache.

It should be noted that this UID/UIDNEXT numbering is strictly per-

mailbox and not per-server, and that different users accessing the same server

might see the same 64bit number for totally unrelated messages. While

RFC 3501 [1] strongly recommends that UIDVALIDITY should be kept

constant if at all possible, a compliant IMAP client has to deal with UID-

VALIDITY changes nonetheless.

The IMAP envelope is a data structure holding interesting values deter-

mined mostly from various message headers. It is not the same thing as the

SMTP envelope, which typically stores less information.

The Internal date holds a time stamp about when the message was deliv-

ered to the IMAP server. Size attribute is the number of octets required for

storing a full copy of message in RFC 2822 format. Body structure represents

the tree-like structure of the MIME message.

The IMAP flags is an attribute holding a set of zero or more named

tokens associated with the message. A flag can be either permanent or

11

session-only. Permanent flags are stored in the mailbox itself, while the

session-only flags disappear on a subsequent reconnect to the mailbox. Some

of the flags are defined by the RFC 3501 standard itself, others are added by

various recommendations and extension standards. An IMAP server might

allow IMAP clients to store their own message flags. A special means of

communicating this via the protocol exist4.

Finally, message contents itself is distributed in form of message texts.

Clients are free to choose from retrieving MIME message parts separately

or as one blob.

2.3 MIME

Multipurpose Internet Mail Extensions [4], [5], [6], or just MIME, is a set

of standards for extending the old SMTP mail from 7bit ASCII texts to

rich multimedia contents. Parts of the standard deal with encapsulation of

non-ASCII characters in message headers, as well as providing instructions

about how to embed non-textual data in e-mail messages.

2.3.1 Message as a Container

An important aspect of MIME is its introduction of an internal structure

to e-mail message bodies. Previously, a message body was just a plain text,

while since the codification of this standard, it became possible to exchange

more structured information. Contemporary users are probably familiar

with HTML e-mails containing embedded images and a PDF attachment for

seamless printing. Users routinely send e-mails with attached photographs

from their holidays, or an archive containing business presentation.

MIME standard achieves this by defining a content type for message

bodies. This content type, usually set by an RFC 2822 header of a message,

determines how a compliant mail client displays the message. The old-school

non-MIME mails have a default MIME type of text/plain, an unformatted

text in 7bit US-ASCII encoding.

Another portion of the standard defines generic-purpose containers, i.e.,

abstract content types which contains other message parts within. Using

these containers, a message can suddenly evolve from an unstructured blob

of text to a deep tree of unrelated body parts.

4The PERMANENTFLAGS response code

12

Most of these containers are defined in RFC 2045 [4] and 2046 [5], one

was added in RFC 2387 [7].

The multipart/alternative encoding provides a mean of transmitting

a message that comes in several different formats, but each of them contains

the same data. The MUA is expected to pick one of the underlying parts

and display it, perhaps allowing the user to override this selection as a nice

bonus.

The multipart/mixed is a generic catch-all MIME type for multipart

messages. If a compliant MUA sees a multipart content type that it can

not recognize, it should behave as if it was the mixed multipart. A typical

action is showing all embedded parts next to each other.

There are several more content types defined, but describing them in

detail is out of scope for this thesis.

2.3.2 International Characters in Messages

Original SMTP mail as defined by RFC 822 is suitable only for transferring

7bit data. Nowadays, 8bit transport channels are far more common, both for

representation of international characters and for transfers of binary data.

Therefore, the MIME family defines transfer encodings for conversion of

generic 8bit binary data into a 7bit character stream and a portable way of

expressing national characters using 7bit ASCII characters only.

For the former, two standard encodings are available, the Quoted print-

able and Base64 (as well as a “fake” binary or 8bit encoding for transport of

binary data over less restrictive tunnels), the latter is supported by a similar

approach, as defined in RFC 2047 [6].

2.3.3 MIME Support in IMAP

A large part of work involving the MIME support can be performed by the

IMAP server. This is especially true for message structure parsing, where

the IMAP specification provisions ways to explore the “tree” of a message,

as well as methods for retrieving the resulting body parts separately (and

even including byte ranges for more convenient download).

The IMAP protocol does not, however, handle the rest of MIME support,

nor much of other header parsing. While it is common to ask the server for

just a named subset of RFC 2822 mail headers, the returned data are not

pre-parsed in any way. Therefore, much of the work from coalescing several

13

header parts to decoding international character data is left as an exercise

to the client.

Fortunately, various message attributes in the IMAP protocol can serve

as a substitute for parsing the RFC 2822 headers. Sender and recipient data

is available from the IMAP ENVELOPE, message size as RFC822.SIZE, IMAP

itself provides extensions for message threading [8], etc.

2.4 IMAP Protocol Flow

Upon a successful connection to a remote IMAP server, client might choose

to authenticate itself if the server has not already pre-authenticated it auto-

matically under a particular user account. After that or in case the authen-

tication is not required, the connection enters the authenticated state. In

this phase, no mailbox is selected and only a subset of commands is valid.

Clients can, for example, ask for listings of the mailbox tree, get quick in-

formation about number of messages in a particular mailbox or otherwise

manage mailboxes as a whole. They have to, however, select a mailbox in

order to do anything else, like retrieving messages or marking them as read.

A mailbox can be opened as read-only or for both reading and writing,

provided the authenticated user has sufficient privileges. Retrieving mes-

sages can be done in both modes, but write operations (like storing a new

message to the mailbox or manipulating the message flags) require read-

write access.

2.4.1 Commands and responses

IMAP is a line-oriented text protocol. Anything that a server sends to its

client is called a response while all data flowing in the opposite direction

are known as commands. Each command generated by client begins with a

unique identifier called tag which is followed by the actual command iden-

tifier. Most commands also accept (or require) a parameter which might

be a string literal, a number, an atom, a parenthesized list of other types,

etc. Transmission of generic string literals requires an explicit confirmation

from the server unless the LITERAL+ [9] extension is active. Support for

this extension is crucial for good performance, as if absent, most commands

would be delayed by at least network round-trip-time and no support for

pipelining of such commands would be possible. Clients are free to issue

14

several commands without waiting for their completion, subject to certain

ambiguity rules5.

Each command usually leads to at least one server response, the tagged

reply. This response contains the same tag as the client sent in the original

command, allowing the client to find out whether command failed or suc-

ceeded. Some commands may result in sending further replies, the untagged

replies. An important detail of the protocol is that such untagged replies are

allowed to occur at almost any time during the conversation and not only

as a result of a particular command. A compliant client must be prepared

for this situation and handle it correctly, for there is no difference between

those unilaterally generated and “requested” replies.

Each tagged reply indicates a completion of a particular command. If

the command succeeded, an OK status is received, if it failed, server returns

a NO. Should the server had troubles figuring out the client’s intention, a

BAD response is returned. More fine-grained control over results is achieved

via response codes, textual entities with strictly defined meaning. Examples

of such response codes are “mailbox opened in read-only mode”, “specified

character set no supported” or “please show this error message to the user”.

2.4.2 Mailbox Synchronization

For efficiency reasons, each client usually keeps some data in its persistent

cache. Good candidates for caching are message texts, a copy of body struc-

ture or perhaps even flags from the previous session. Because some server

replies, namely the EXPUNGE which informs the client that a message has

been removed from the mailbox, refer to messages only by their sequence

numbers and clients usually identify messages by UIDs in order to allow mes-

sage texts caching, a compliant client has also to keep its UID-to-sequence

number mapping up-to-speed with the server. Doing so for just a visible

(in the GUI) part of the mailbox might seem tempting, but the risks in-

volved therein (like not knowing what to purge from local cache as a result

of received EXPUNGE without extra FETCH) are high and usually outweigh

possible initial savings.

An IMAP server fully conforming to RFC 3501 is required to sent a

few “status” replies when a mailbox is selected. Interesting fields for the

mailbox synchronization are updates on UIDVALIDITY, UIDNEXT and

EXISTS. After receiving all three, client has enough information to decide

5See section 5.5 of RFC 3501

15

about what actions are necessary to bring the particular mailbox back to

a fully synchronized state. Clients only have to deal with mutable message

attributes, which are the sequence number, the UID number and message

flags.

If the UIDVALIDITY value changed, the client is required to throw away

any data it might have in its local cache that refers to this particular mailbox.

Some UIDs might have changed, message parts got modified or the client

just happens to talk to a buggy server implementation. This situation is

then identical to syncing form an initial state where client has no knowledge

about the target mailbox. In the following text, we will assume that the

UIDVALIDITY value is the same as on the previous synchronization.

If the UIDNEXT value did not change either, no messages were delivered

to the mailbox since the last time. If the EXISTS number is the same as

well, there have been no changes at all and the only item to re-synchronize

are message flags. If the EXISTS number changed, some messages were per-

manently removed. Clients usually re-fetch their UID-to-sequences mapping

as a whole, but implementations which prefer to transfer the lowest amount

of data over the number of iterations over the network could use an algo-

rithm similar to binary search to find out which regions of the UID mapping

were left intact and which require re-synchronization.

If the UIDNEXT changed6 and the _UID is the same as _EXISTS,

some new messages arrived, but none were deleted and the client only has

to ask for UIDs of these new messages (and FLAGS for all messages in the

mailbox). If the increments of UIDNEXT and EXISTS differ, a fallback to

generic synchronizing approach where client retrieves UIDs of all messages

in the mailbox is necessary. It is also reasonable to transfer flags as a part

of this step.

If there were no cached information or a UIDVALIDITY change occurred,

clients would typically fetch a complete UID mapping and message flags.

After performing these steps and having received all relevant replies,

the client is in a fully synchronized state and ready for receiving mailbox

updates.

2.4.3 Changes to Mailbox

The mailbox that is selected is typically of some interest to the user. The

original IMAP RFC mandated that all clients must be prepared for receiving

6It could only grow up, because UID numbers are strictly ascending

16

updates about number of messages contained therein, removal of old ones

and deliver of new, but due to the lack of support by clients at that time,

this feature was rarely fully utilized. Instead, the NOOP command was

widely used as a polling check for new messages. However, this had all the

disadvantages of a polling-based approach, especially unnecessary increase

of network traffic, lower possibility to enter deep sleep for battery powered

devices and even delays in mail delivery, for some clients were rather hesitant

to poll for changes too often. A solution to this problem is presented in

RFC 2177 [10] where client enters a special mode (which is syntactically

similar to synchronizing literals that are used when support for LITERAL+

[9] is absent) to tell the server that it can really send real-time notifications

to the client.

Changes to the number of messages in the mailbox are communicated

mainly by two kinds of untagged replies, EXISTS and EXPUNGE. The

EXPUNGE reply contains a sequence number of the message that has been

permanently removed from the mailbox and immediately causes all messages

with sequence number higher than the message being deleted to decrement

their assigned sequence numbers by one. This means that clients have to

work with sequence numbers, unless they are prepared to update their UID

map on each expunge, which would be a rather expensive approach. The

EXISTS reply is used to inform the client that new message was delivered,

or it could follow an EXPUNGE to provide a redundant information to the

client about number of messages in the mail store. Under no circumstances

could it be used to decrease the number of messages in current mailbox, as

this is already handled by EXPUNGE.

2.4.4 Fetching and Manipulating Messages

Once selected, messages in the mailbox can be queried and downloaded to

the client. The FETCH command serves for retrieving all data from body

structures and IMAP envelopes to actual message parts. Message flags are

updated by the STORE command and its variants. Existing messages can

be copied to other mailboxes with the COPY command, new messages can

be stored into a mail folder by the APPEND command.

17

2.4.5 Queries Against Other Mailboxes

Because most graphical MUAs want to show the user more than one mailbox

at a time, at least in a collapsed view with counts of new or unread messages,

and frequent switching among several mailboxes is not a cheap operation,

IMAP also provides a command for determining state of other than currently

selected mailbox, the STATUS command. Using this command for querying

state of a currently selected mailbox is explicitly forbidden by the RFC, for a

conforming client already has all required information to compute all possible

message counts. Another reason for disallowing STATUS on current mailbox

is that in some server implementations, this operation might cause a process

to open the mailbox once more which might in turn provide inconsistent

results and confuse the client even more.

2.4.6 Searching, Sorting and Threading

Even the base specification of the IMAP protocol provides facilities for

searching the messages stored in current mailbox. This was extended over

time by ways to request specific message ordering or threading [8]. Most

e-mail clients therefore do not need to have all message bodies and headers

fetched and available in a local cache in order to allow their users to search

through messages. However, this searching and sorting is not available in

offline clients which have to implement their own code for such purposes, or

disallow these operations when network access is disabled.

The following revisions also specified certain extensions related to the

internationalization of e-mail traffic. For example, searching for non-ASCII

characters in messages would be very hard using the bare-bone SEARCH

command only, as each message in mailbox can be stored in one of the

myriad encodings available in the MIME standard. Subsequent revisions to

IMAP therefore defined support for more intelligent searches which support

unified searching through messages that arrived in different character sets.

2.4.7 Manipulating Mailboxes

Due to some historic reasons (especially the old versions of SMTP protocol

being 7bit), IMAP does not use any standard encoding for mailbox names.

Instead, a modified version of UTF-7 called simply modified UTF-7 is man-

dated. The standard does not specify what to do if the other side uses

18

8bit data in mailbox name, but most implementations nowadays fall back

to UTF-8, which is arguably a good thing to do.

Mailboxes can be created, deleted and renamed by IMAP clients. If

the server supports it, they form a tree hierarchy. Some servers distinguish

between mailboxes for storing messages and those that contain only other

mailboxes, while other implementations allow free mixing of both. Unfortu-

nately there is no reliable way to tell to which class the target server belongs,

but provisions are given about how to create a folder for message and how for

other mailboxes. If mailboxes form a tree, the server implementation speci-

fies which character is used as a hierarchy delimiter. Most common choices

in today’s mainstream IMAP servers are dot (.) which is common among

servers exporting Maildir folders and slash (/) as used by servers exporting

traditional mbox UNIX mail store. This inconsistence might lead to user

confusion, but cannot be avoided without breaking backward compatibility.

2.4.8 Session termination

IMAP session ends when the server sends the client an untagged BYE re-

sponse. This might be caused either by client’s request via the LOGOUT

command or by an auto-logout timer on the server side. Server implemen-

tations are required to allow at least 30 minutes of inactivity before sending

this reply7.

2.4.9 IMAP Extensions

The IMAP protocol also has support for extending its functionality. Ex-

tensions can add new commands, replies and reply codes and even change

basic aspects of the protocol, as demonstrated by the introduction of non-

synchronizing literals in RFC 2088 [9]. Support for these extensions is

strictly voluntary, though, and each compliant IMAP protocol entity has

to function properly even when talking to an implementation supporting

bare IMAP4rev1 as specified by RFC 3051.

7Many real networks, however, enforce much stricter policies with shorter timers. Real

world client implementations therefore send keep-alive messages once in a few minutes to

avoid connection termination.

19

2.5 Other Methods of Mail Store Access

IMAP is not the only protocol for accessing mails stored on a remote server.

In this section, we will introduce some of the alternatives and discuss their

advantages and disadvantages when compared to IMAP.

2.5.1 POP3

The main difference between IMAP and POP38 protocol is their philosophy

— IMAP was designed for scenarios where user leaves all her e-mail at

a central place which has authoritative answer about what messages are

supposed to “be there” while POP3 expects their users to download all e-

mail to a computer where the POP3 client runs and then permanently remove

the original messages from the server. Upon each reconnect, the POP3 client

downloads and deletes all new messages again. This fundamental difference

leads to troubles when the user wants to use POP3 in situations it was not

designed for – a classic example is accessing one mailbox from two places

over time, like a work computer and a laptop at home. While there are

certain ways to work around these POP3 design limitations which allow

leaving a copy of each message on the POP3 server, they all remain just

hot fixes instead of providing a proper and reliable solution. An excellent

comparison of these two paradigms is available from Grey’s paper [11].

2.5.2 MAPI

A proprietary protocol from Microsoft whose documentation got recently

opened for public access after a pressure from both government an non-

government organisations. It has some nice features comparable to IMAP,

but offers no real advantage besides tight integration with other Exchange

services (which might or actually might not be considered an advantage).

Implementations from other parties than the original vendor are scarce.

2.5.3 Webmail

Several years ago, a boom of online services from well-known companies like

Google or regional Internet portals grew in popularity. Despite inherent

8Post Office Protocol version 3

20

limitations of web-based user interfaces, most “casual” users of e-mail, espe-

cially the second “home mailboxes” of regular employees, are today hosted

and accessed via a webmail interface. Although hardly any of these services

offers any guarantee about availability or performing backups, regular users

typically are not concerned about these issues. Reliability of these services

is, on the other hand, typically greater than that of a typical home PC with

aging hardware, and friendliness of the UI improved with advent of recent

web technologies.

2.5.4 IMAP Criticism

During more than 20 years of the IMAP history, the standard has certainly

accumulated some aging dust. A typical example are the synchronizing lit-

erals, originally the only way to send more complex data to the server, which

require explicit server’s acknowledgment before continuation. Given a typi-

cal GPRS connection which is still common in many countries, a latency of

500 ms can delay all interaction with the IMAP server considerably. Many

similar aspects were fixed by subsequent modifications to the standard, oth-

ers are rather unfixable design limitations.

A fine example of such limitation, at least when perceived by the con-

temporary optics, is the concept of mailboxes. Online messaging services

like GMail introduced a new way of thinking about messages – previously

a message would belong to exactly one mailbox and if the user wanted to

have it available from two places (perhaps in “work related” and “mailing

list” folders), she would have to store two copies. IMAP has no concept of a

“link” between two messages. When one of them is flagged, the other copy

is left intact. Another prehistoric feature of IMAP is its modified UTF-7 en-

coding which is not used anywhere else besides the IMAP protocol. Another

point – IMAP usually does a good job in shielding the client implementation

from the need to parse all MIME data, but certain pieces remain, like the

RFC 2822 headers with international characters.

Some authors also criticize the protocol on basis of its complexity and

being loosely-defined in certain aspects. An example is the IDLE [10] ex-

tension, which adds an explicit mode indicating to the server that the client

is really ready to process any updates to mailbox state, while the original

RFC mandated the client to be in such condition all the time. Most common

MUAs also have troubles with getting all side-corners of IMAP right.

That being said, the IMAP is the only widely implemented standard for

21

accessing an online or disconnected mail store. It has certain deficiencies,

but all in all, it is a perfectly usable protocol.

22

Chapter 3

Trojita Design

As evidenced by numerous available MUAs on the market, there are many

possible ways on how to implement a usable e-mail client. In this chapter,

we explain some design choices behind Trojita.

3.1 Overview

Trojita is composed of several logically decoupled layers of independent com-

ponents, see figure 3.1 on page 24. Communication between them adheres

to a strictly defined interface.

On the top of the hierarchy lies the GUI. This part is what the user

interacts with; it provides views showing all mailboxes on a server, a list

of messages in the currently selected mailbox and the contents of the e-

mail messages themselves. The GUI is based on the Qt framework, making

use of various standard components. A substantial part is based on the

Interview framework [12] and the WebKit [13] as well as certain custom

widgets, especially the Message View (section 3.7).

The GUI is fed with data by the Model, a model-view implementation

created with the Qt item views. This part works in close collaboration with

the IMAP server. It is responsible for processing server replies, building a

representation of data stored on the remote host and sending commands to

the server in response to user actions. Most of the IMAP protocol logic is

concentrated on this layer.

The Model is assisted by a Cache. The cache provides persistent storage

for certain data which are convenient to be present on next invocation of the

application. Examples of such data include message parts or mailbox state

23

GUI

Model

Parser

Low_Level Parser

Stream

Signals/Slots and

Function Calls

Responses Commands

Bytes

Tokens

Bytes

Cache

Raw

Data

Figure 3.1: A diagram showing the Trojita architecture

information which allows a quick resynchronization after a reconnect. While

the role of the cache and the data stored therein is not critical for Trojita’s

operation, having a local cache can considerably speed up the runtime. A

layer serving a similar purpose is common among other e-mail clients as well.

Beneath the Model is the IMAP Parser, a component converting the

stream of data flowing from the server into structured (and as the name

suggests, parsed) data. The parser is assisted by a Low-level parser, an

entity responsible for analysing the byte stream into tokens of data such as

24

strings or numbers.

Finally, all network I/O is managed by a Stream and associated classes

which provide a consistent interface for managing connections to the remote

server.

3.2 Model-View Architecture

Trojita’s heart, the Model, implements an interface of the QAbstractItem-

Model, a variant of the well-known Model-View-Controller design pattern.

This architecture provides natural separation between how data are stored

and how they are displayed. In case of Trojita, we went a bit ahead com-

pared to the common approach and made essentially everything just a node,

a part in one big tree which exports all data available on the server. This tree

then contains all mailboxes, all messages stored in them and even the mes-

sage structure and actual message body parts as its nodes. Several filtering

models provide more user-oriented view, like “all mailboxes” or “messages

in a mailbox”. An alternative to this one-big-tree approach were separate

models for list of mailboxes and for each opened mailbox. While the lat-

ter might make more sense at a first glance and from the perspective of

a reader who just went through the IMAP protocol standard, subsequent

analysis suggests that one big model actually fits the situation better, unless

we wanted to deal with nasty issues that would immediately pop up as a

result of sharing one Parser instance among several Models facing several

mailboxes. The upper layers are not affected by this decision, as they use a

strictly defined model-view interface for actual data retrieval.

The model-view architecture subsequently affects how Trojita and her

Model operate. Upon successful startup, for example, Trojita will not exe-

cute many IMAP commands besides making sure that a connection to the

remote IMAP server enters the authenticated state. This might involve is-

suing a STARTTLS command for establishing a secure channel, optional user

authentication, etc., but none of tasks like mailbox listing or even opening

some of them. This listing is only fetched as a result of a call from the GUI

which asks the model what should be shown in the view representing a list

of mailboxes.

After the list of mailboxes is received and processed, the model tells all

the attached views that its layout has changed and that the views should

update what they show to the user. The views react by requesting more

information from the Model, e.g., a number of unread messages or a total

25

message count for each visible mailbox.

When a user clicks on a particular mailbox, another view is pointed to

a subset of the big model, now containing a list of messages in the mailbox.

Again, the action of clicking to the mailbox does not involve any direct action

in the model itself; the mailbox synchronization is initiated only after the

new view asks the model about how many messages to show, and then for

more data concerning those messages that are visible in the current viewport.

One important feature implemented in Trojita which is absent from most

e-mail clients (especially those whose data model was designed with only

POP3 in mind) is delayed on-demand fetching with an intelligent preloading.

Suppose a user has a big mailbox with more than 30,000 e-mail messages.

A naive client would open a connection to the server, select the mailbox and

then fetch envelopes for all messages in the mailbox. Most of these messages

would never be shown to the user, though, as thirty thousands messages is

too much to be displayed on one screen. What Trojita does is, however,

more clever – it creates thirty thousand of fake entries in the Model, each

displaying a loading. . . sign, and ask for the real data only for those that

are actually visible (with some read-ahead and read-behind for increased

efficiency). This effectively minimizes the amount of network traffic as well

as the local cache size and the load on the remote IMAP server, while the

user barely notices any slowdown.

Being the central part of Trojita, the Model and related components is

described in section 3.6 at the end of this chapter.

3.3 Parser

The Parser is responsible for converting raw network replies into data suit-

able for processing by the Model.

3.3.1 Low-level Parser

Certain low-level tasks like extraction of a string literal from the input stream

are offloaded to a lower-level class, the LowLevelParser. Reading raw, un-

structured byte stream as the input, its job is to extract a certain field and

return it in the specified form. The resulting type of this tokenizing is not,

however, determined by the LowLevelParser itself, but by the upper layers.

LowLevelParser thus works as a dumb context-free extractor rather than a

full parser. Should an error occur (for example when the higher-level code

26

requests an integer, but the data at the current offset are textual), an excep-

tion is thrown. Examples of functions implemented in the LowLevelParser

are getAtom()1, parseList()2 or getNString()3. Details about their im-

plementation are available in the Doxygen documentation.

3.3.2 Parser

The Parser listens to events from the underlying Socket, sending queued

commands to the server and processing incoming data as they arrive. Dur-

ing the development of Trojita (and thanks to being the first component to

be actually implemented), design of the Parser changed several times. Orig-

inally it started as a threaded implementation due to certain concerns about

interactivity and network I/O, but after encountering some issues with Qt’s

handling of asynchronous event signalling and a recommendation from one

of the core Qt developers, it was refactored into a single-threaded state ma-

chine with a more conservative handling of the network I/O, which closely

mimics common Qt idioms.

When a reply from the server arrives, Parser instructs the auxiliary

LowLevelParser instance to read tokens from the byte stream. These tokens

are then used to build a complex AbstractResponse instance on-the-fly.

Due to the limitations of polymorphism in C++ and concerns about object

lifetime and ownership, the Parser makes heavy use of C++ smart pointers,

as introduced in the TR1 [14]. An alternative would be to use smart pointer

implementation from the Qt framework, the QSharedPointer. It provides

a similar interface, so the possibility of eliminating a dependency on TR1

implementation is open for further consideration.

This part of Trojita has an extensive unit test coverage based both on

real-world traffic and artificial corner cases. Error handling is implemented

via exceptions. Being a class derived from QObject, the Parser uses signals

and slots for communication with the rest of the application – incoming data

are read and parsed in code connected to the readyRead() signal from the

underlying socket and availability of processed server replies is announced

by emission of responseReceived() signal. The responses themselves are

1For reading an atom, which is usually used for transmission of integer values or ASCII

words not containing “complicated” characters like spaces

2For retrieving a parenthesized list of other items. The other items might be atoms,

string literals or even nested lists.

3getNString() returns string as parsed by getAString() and adds special handling

for NIL items.

27

not serialized to the Qt’s event delivery system, though, but remain stored

in an internal queue in the Parser which provides queue-like semantics for

accessing them.

3.4 Cache

A main purpose of the Cache is providing a persistent copy of certain useful

data for speeding up mailbox re-synchronization upon a subsequent select

as well as storing already requested message structure and message body

parts.

Trojita is ready for multiple cache implementations. The implementation

and interface are properly separated – an abstract class4 specifies the only

required methods of interaction between the Model and the Cache.

A simple cache implementation storing all data in operational memory

with an optional possibility of persistent data store on the disk is provided.

As no object life management or partial updates of the on-disk representa-

tion are implemented in this simple cache, it is not recommended for produc-

tion use. Advanced caching implementations are expected to be developed

after the thesis is finished. Candidates include using an sqlite database or an

Qt caching object from WebKit, the QNetworkDiskCache. One reason for

developing a simple, in-house caching solution is the fact that the Qt caching

framework was introduced only in Qt 4.5 while Trojita still supports build-

ing against the 4.4 release, albeit with reduced feature set. Therefore, it was

deemed that a simple custom caching framework is worth the extra work.

3.5 Streams

The Qt framework already provides an implementation of an entity with

support for sequential reading and writing as well as informing the rest of

the application about the availability of new data. However, no unified

interface for reporting errors is provided. Therefore, most of the classes in

the Stream sub-library are just thin wrappers around various QIODevice

subclasses, adding unified signals and functions for error handling.

Trojita includes support for communication over unencrypted TCP sock-

4Imap::Mailbox::AbstractCache as defined in Imap/Model/Cache.h

28

ets, over a connection secured by SSL5/TLS6 with the possibility to defer

the SSL/TLS negotiation to a later point during the IMAP conversation7,

and finally over a UNIX pipe to a local process. For the latter, two im-

plementations are actually included, first one being a wrapper around the

QProcess from Qt and the other a standalone class making direct use of

POSIX syscalls. The standalone implementation is no longer necessary, but

was used in an earlier implementation of the Parser which made heavy use of

nested calls to QIODevice’s waitForReadyRead() method. This usage led to

hard-to-debug failures in the networking code when using other QIODevices

than QTcpSocket. After a communication with Qt Software support per-

sonnel [15], it was suggested to abandon these nested waitForReadyRead()

calls and follow an approach common to Qt applications which simply ig-

nore the availability of new data until there is enough bytes to process a

whole response at once. In addition to more obvious and cleaner code, this

eliminated the need for blocking I/O and subsequently any advantages of

a threaded design of the Parser. Therefore, multithreading was abandoned

and a new single-threaded network handler was implemented.

3.6 Model in Detail

The Model is the most complex part of Trojita. It is responsible for correctly

figuring out the meaning of various IMAP server replies, requesting further

data as they are to be shown to the user, managing a pool of connections to

opened mailboxes as well as handling of certain non-standard situations.

3.6.1 The Tree

Being an implementation of QAbstractItemModel, the Model has to pro-

vide an interface through which the attached views and proxy models8 can

operate.

As most of other complex implementations of the QAbstractItemModel

which provide a tree view with deep hierarchy, the Model maintains an

5Secure Socket Layers

6Transport Layer Security

7The STARTTLS command, cf. section 6.2.1 of RFC 3501 [1]

8Proxy models are auxiliary models which do not supply their own data, but instead

provide a filtered and modified view of data published by the parent model. More on this

topic is explained in section 3.6.2.

29

internal tree of classes representing different entities in the big tree. These

entities are:

TreeItem An abstract parent class providing a common interface for all

specialized implementations

TreeItemMailbox A class representing a remote mailbox on the IMAP

server. Children of the mailbox are other mailboxes and a list of mes-

sages.

TreeItemMsgList A container holding all messages in the mailbox

TreeItemMessage One message in a particular mailbox

TreeItemPart One MIME body part of a message

Each of the mentioned classes contains enough information to be able

to handle all delegated operations related to the Interview framework. For

example, when the Model is asked for a displayable textual data for a par-

ticular index, it delegates the query to the corresponding TreeItem instance

using virtual methods. The target instance then decides about what is ac-

tually requested and how to retrieve that data. Certain requests might be

satisfied from the data already stored in the TreeItem instance itself while

other require a query against the IMAP server. If the latter happens, the

TreeItem asks the Model to submit a request to the IMAP server and returns

some temporary data in response to the original request which most likely

originated from the GUI. A typical temporary representation is a translated

form of “loading. . . ” or a question mark. As soon as the real data arrive

from the server, the view is asked to update the display with new value.

To illustrate this rather complex theory on a concrete example, suppose

a view just scrolled to a new message in the mailbox. The view obtained

a model index9 from the Model and called the Model’s data() function

to find out what should be displayed on screen. This function call was

immediately propagated to the newly created TreeItemMessage instance.

As the message just arrived to the mailbox, the class didn’t have time to

request more data about it yet. The TreeItemMessage instance is therefore

in an initial state indicating that no attempt to load the data from the

9A temporary index used for referring to certain item in the Model. The model index

is a standard term from the Qt Interview framework, and as such is not described in detail

in this thesis. Readers are referred to excellent Qt online documentation for details.

30

server has been performed, and thus the data() implementation does not

have any real answer to the original query. Therefore, it submits a request

to the Model asking it to fetch the IMAP envelope of the particular message.

However, the reply to this message is not guaranteed to arrive in a timely

manner and the TreeItemMessage implementation cannot afford to block

the GUI while it waits for the corresponding reply. Therefore, it returns an

empty placeholder (or some intuitive string like the loading. . . text already

mentioned) for the time being. This text is then displayed in the GUI, for

the Model does not have anything better to show to the user yet. In addition

to that, the TreeItemMessage changes its state to loading which indicates

that the remote server was already asked for the data and there is no point

in requesting it over and over again10.

In the meanwhile, the Model receives TreeItemMessage’s request for

fetching an envelope. It decides that the requested data belong to, e.g.,

message No. 666 in the mailbox. The total message count is 670 and no

messages between 660 and 670 were fetched yet. To enhance the user ex-

perience and minimize network round-trips, the Model submits a batched

request to fetch message envelopes of all these messages at once, as chances

are high that most of them will be queried for data soon anyway. As a part

of this request, they are all flagged as loading in order to prevent duplicate

fetching requests.

After a while, the response from the server arrives. As usual, the Model

delegates the actual processing of the reply to the TreeItemMailbox or

TreeItemMessage instance. The class notices that enough data for updating

its state from loading to fetched has arrived, so it marks itself as fetched and

tells the Model to broadcast this change to the attached consumers (views).

Each view, upon receiving a dataChanged() signal from the Model, asks

for the displayable data again. Model passes the data() function call to

the TreeItemMessage instance which discovers that it has the data already

available in memory and returns the real text field (like a message Subject)

this time.

The ultimate goal of this lazy population is reducing network traffic and

server load, as well as the client’s memory usage.

The delayed loading is employed in all places in the Model where possible.

For the efficiency reasons, though, certain data items which are known to

be needed shortly after each other are requested in one block. Examples of

10If the data() function concerning the same index is called again, the same placeholder

data is returned, but no further requests to the IMAP server are initiated.

31

such data are groups of the message envelope, the IMAP internal date, the

message size, the UID, the body structure and the message flags concerning

a particular message. As suggested earlier, these fields are also preloaded

for previous and following messages in a sequence.

One notable exception to this approach is building a list of mailboxes.

Due to the way the LIST response is defined11, no reliable way of request-

ing a partial listing of the mailbox tree is provided besides indicating that

the result should include mailboxes from the specified hierarchy level only.

Trojita therefore has to fetch all the names of top-level mailboxes at once.

Requesting a listing of their children is then delayed until the user clicks the

“expand” widget next to the mailbox name. Also the numbers indicating

a total message count or the number of new messages in a mailbox are not

requested for mailboxes that were not shown yet.

The tree nodes do not make use of smart pointers, instead, the par-

ent node is responsible for properly freeing all resources associated with it,

including destroying the children.

Trojita already tries to minimize the memory footprint, not fetching data

until needed, yet an empty TreeItemMessage instance is still created for each

message in the opened mailbox. The memory consumption associated with

these operations is difficult to measure12. Experiments show that opening a

mailbox with more than 43,000 messages increases the overall memory usage

by about 6.5 MB on an x86 machine. Slightly less than one third of this

memory is consumed by the QTreeView itself.

3.6.2 Proxy Models

While browsing the huge mailbox tree itself is certainly an educating expe-

rience for users wishing to become familiar with e-mail processing and the

IMAP standard, it is far from being user-friendly. Therefore, Trojita pro-

vides proxy models for presenting a more conservative view to the remote

server’s resources.

A proxy model works in close collaboration with the parent model, pro-

viding a modified and filtered view of the parent’s data to the attached

views. Trojita uses two proxy models, one for providing a list of mailboxes

and the other for listing messages in the opened mailbox. Neither of these

11Consult the RFC 3501 [1], section 7.2.2

12The increase in memory usage includes internal QTreeView data structures which

could not be eliminated even if Trojita did not create any new objects for its own purposes

32

models contain significant intelligence, as most of the hard work is already

done by the original parent Model.

3.6.3 Offline and Expensive Network Mode

In addition to the mode of operation described above, the Model can be

instructed to change its behavior in order to either reduce the network traffic

even further or to avoid any communication with the remote IMAP server

altogether. For the former, and expensive network mode is provided, the

latter is handled by an offline mode.

When offline, essentially any network traffic13 is blocked. All requests

which cannot be satisfied from the cache will fail, and the corresponding

TreeItem’s state will be changed to offline. This particular status is reflected

in the GUI in an intuitive way, mostly by changing the unknown message

subjects to offline, etc.

The expensive mode mostly eliminates various optimistic preloading, as

well as changes the operation of the message view to not show all body parts

automatically.

3.7 Message View

Rendering an e-mail message is not as simple as it seems. First problem

that the implementation has to face is the delayed on-demand loading of the

message parts. Due to the rich tree structure of MIME messages, Trojita

does not know which parts are required to be shown before an attempt

to render the message is made, and loading all of them in advance would

be not only suboptimal in terms of network utilization, but could cause

an inconvenient delay when displaying huge messages as well. Similarly,

blocking for a full delivery of all required message parts when the rendering

starts is not an option, as this process should not block the GUI.

The second problem originates in the complex nested structure of MIME

messages. There is no limit for the maximal allowed depth of the body part

nesting, so a message could have an attachment which in turn is another

message containing further complex structure, easily stretching for many

levels.

13Besides shutting down the already established connection

33

A first version implemented in Trojita dealt with the first problem, while

leaving the second one unsolved. Since that, the message view widget was

rewritten and the version presented in this thesis supports unlimited nesting

of messages.

The core of both message rendering widgets is based on the WebKit [13],

a standards compliant HTML rendering engine.

3.7.1 Network Manager

The QWebView class is a component providing the HTML rendering engine

as well as certain auxiliary infrastructure such as a client implementation of

the HTTP stack. These parts combined together contain everything required

for building an application which displays HTML pages retrieved from the

network via a standard protocol like HTTP. Messages stored on a remote

IMAP server are not, however, usually available over HTTP. Therefore, the

QWebView had to be extended in order to be usable in Trojita.

Luckily the QWebView provides a straightforward way to delegate the

network processing to a custom component via the QNetworkAccessMan-

ager interface. That custom component is then responsible for handling all

network requests that originate as part of the processing of the HTML page.

In Trojita, we created a special network manager14 whose job is to provide

an access to the message bodies stored on the remote IMAP server as well

as filter out any access to the “regular Internet”.

The reason for the former is security and spam filtering. For example,

when an HTML message contains a reference to a remote image, a naive

e-mail client which allows the retrieval of external entities via HTTP would

provide an accurate indication about when the message was read and even

confirm the very existence of the addressee’s e-mail address to the attacker.

The most interesting part of the network manager is, however, providing

an access to the body parts. When the URL to be retrieved specifies the

trojita-imap scheme and message as the “host name”, the path of the

URL is directly used as a logical address of the requested body part. If such

a part exists, an auxiliary helper structure, a subclass of QNetworkReply, is

returned which immediately requests the retrieval of the corresponding part

from the IMAP server (or the local cache, if available therein).

In an old implementation, the QNetworkReply itself was responsible for

properly handling the MIME content-type of the body part. For example,

14The MsgPartNetworkAccessmanager

34

it contained a code for selecting the preferred part among several avail-

able in the multipart/alternative, or including multiple commands in case

of multipart/mixed. This approach, however, did not scale. Therefore, the

new implementation moves this logic to the upper layer where it arguably

belongs.

The QNetworkReply subclasses in the new implementation do not handle

any formatting logic. They are, as their name indicates, just thin wrappers

dealing with raw data I/O from the TreeItemPart instance. For handling

the formatting, a new class, the PartWidgetfactory, factory was created.

3.7.2 Widget Factory

The PartWidgetfactory is a classic example of the well-known Factory

design pattern [16]. Its only public method, create(), is responsible for

returning a QWidget which is supposed to display a representation of the

actual body part.

For some “trivial”15 content-types, the factory returns an instance of a

slightly modified16 QWebView.

If the type is complex, a wrapping widget is created. A classic example of

the wrapper is the handler of multipart/alternative MIME content-type.

In this case, a QTabWidget whose tabs contain the actual nested parts is

returned. Widgets for the nested parts are obtained by a recursive call to

the create() function, solving the problem of the nested body parts in an

elegant way.

RFC 2183 [17] introduced a method for specifying whether a body part

is to be shown inline, that is, as any other regular part, or as an attach-

ment through the Content-Disposition header. If the part is an attachment,

most MUAs would not render its contents, but instead show a control for

downloading the body part to the disk. Trojita works in a similar way. Un-

fortunately, certain e-mail clients don’t distinguish among an attachment

and an inline part, labeling data such as attached ZIP files as inline. There-

fore, Trojita process the Content-Disposition header only as a suggestion if

it asks for an inline display.

15Trivial in this context refers to a message part which could not be decomposed to

more elementary parts. Examples of trivial content-types are text/plain or image/jpeg

while examples of non-trivial ones are multipart/mixed or message/rfc822.

16The modifications include filtering of the mouse wheel events, because the widget is

supposed to be as large as required and leave implementing a scrolling view to itself to

an upper layer.

35

This part of Trojita is ready for further extensions. One particular ex-

tension which would be extremely useful to be implemented is support for

signed and encrypted messages. Signatures are currently only recognized

and indicated in the GUI, but not verified at all.

3.7.3 HTML Mail

A common format for today’s commercial e-mail messages is the HTML

mail. Building on top of the RFC 2387 [7] and RFC 2111 [18], the HTML

e-mail allows grouping HTML text and related data such as images into one

MIME message part.

Conforming to the above mentioned standards, Trojita supports the cid

URL scheme. The network access manager (see section 3.7.1) is extended

with support for those URLs – if a message part with the corresponding

Content-ID header is found among the current message bodies, it is returned

in response to a cid: URL.

An interesting fact about Trojita is that her support for the cid: URLs is

more feature-complete than that of Thunderbird/2.0.0.14 which has troubles

identifying certain body parts in some HTML messages17.

3.8 GUI

No matter how advanced the underlying engine is, if the GUI does not keep

up with the features offered or is not intuitive enough, users will switch to

a competing product.

Trojita makes use of standard widgets from the Qt library whenever

possible. Common and well-known components such as tree views builds the

core of the GUI, showing list of messages and list of mailboxes. When the

standard widgets did not exist or were not usable, new were implemented,

re-using the existing ones as much as possible.

An example of a well-done re-use is the Message View. Building on

already complex parts such as the WebKit and the associated helper classes,

it combines the widgets with whom the user is probably already familiar

into a big functional part. Without an unneeded user confusion, it manages

to render the MIME structure of the received message faithfully.

17For example those from the http://mon.itor.us/ monitoring service.

36

The mail composer widget closely mimics the Write New Mail window

from Mozilla Thunderbird. The recipients matrix was implemented in a

similar way, providing users with a familiar experience and reducing the

need of getting accustomed to yet another software.

Similarly, the icons indicating message state (such as being flagged for

deletion, already replied to, forwarded to another recipient, etc.) are indi-

cated by standard icons. Trojita will, thanks to the QtIconLoader [19], try

to load standard icons as per the relevant FreeDesktop.org standard [20], and

for those that are absent from the system, a built-in icon from Thunderbird

is used.

Drag and drop is used for copying and moving messages between mail-

boxes. No support for drag and drop outside of the Trojita is available yet,

mainly due to a lack of widely accepted standard MIME type for doing so.

37

Chapter 4

Other IMAP Implementations

Albeit the guarantee of interoperability is arguably the most important as-

pect of a standardization process, certain e-mail clients perform better than

the others. In this section, we try to provide a basic overview of selected

e-mail implementations.

This overview is by no means complete, for there are many more e-

mail client implementations than pages in this thesis. We therefore focus

on highlighting issues observed during the course of interoperability testing

and on a comparison with Trojita.

Each client was tested against an instance of the Dovecot IMAP server [21].

INBOX contained roughly five thousands messages, most of them were trivial

text/plain e-mails with just one line of the message body. Other mail folders

were however filed with certain testing messages representing a typical e-mail

usage of the author of this thesis. Samples include GnuPG signed mail (the

multipart/signed MIME type) and a special “MIME Torture Test” [22] mes-

sage whose purpose is to test deep MIME part nesting as well some common

decoder errors.

4.1 Alpine 2.0

Alpine [23], a successor of pine, is a console e-mail client by Mark Crispin,

the principal author of the IMAP protocol. As such, its qualities are widely

acknowledged. When coupled with the UW-imapd, an IMAP server imple-

mentation from the University of Washington from the same author, they

offer some non-standard features such as multi-mailbox search. The IMAP

part of the code base is available as the c-client, an implementation of the

38

IMAP protocol in the C programming language.

The testing process showed that Alpine performs as an online client,

that is, a client with no local persistent cache for retrieved message parts.

These parts are cached for the session life time, but any downloaded data

will be fetched again on a subsequent Alpine invocation. A nice feature of

Alpine is, on the other hand, that it does not fetch any data about messages

not currently visible on screen at all, achieving the lowest amount of initial

network traffic among all tested IMAP implementations.

As a surprise comes the marketed lack of support for the IDLE IMAP

command. Crispin argues [24] that in today’s world of NAT1, a real client

will have its connection to the server sewered by a network device much

sooner than before the 30 minutes timeout period guaranteed by the RFC,

and suggests to use NOOP-based polling instead. This opinion is arguable,

and most e-mail clients’ authors do not seem to share it.

4.2 Mutt 1.5.19

The second console e-mail client, the Mutt [25], is a popular text-based

application. Controlling its user interface is slightly less intuitive than that

of Alpine, but the advanced users praise its speed and the fact that the GUI

does not block their operations.

Similar to Alpine, the Mutt is an online client without any persistent

IMAP cache for downloaded message parts. In addition, Mutt will not issue

the IDLE IMAP command unless specifically told so in the configuration file.

As a reason for this are stated issues with certain server implementations2.

Even when IDLE is enabled, Mutt only enters this mode when showing a

list of messages in the mailbox and not when viewing one message.

4.3 KMail 3.5

Being the default e-mail client in KDE 3.5, the KMail [26] has a broad user

community. However, its IMAP support might sometimes seem a bit rusty –

1Network Address Translation

2Interestingly enough, Dovecot is blamed, while new version of Dovecot contain a

workaround claimed to “fix Mutt issues”, so figuring out which party to blame is left as

an exercise to the reader.

39

there is, for one, no support for IDLE3, and quite a number of bugs against

the IMAP implementation is reported at its Bugzilla.

In fact, the KMail contains two distinct implementations of IMAP, the

first one being an online mode and the second one a disconnected mode.

In the disconnected mode, all message bodies selected for being available

when offline are transfered and all MIME parsing is deferred to the client,

no matter what structure the e-mail message has.

In the online mode, a first surprise is KMail’s handling of the IMAP

message flags. In spite of using the proper command forms for updating

certain individual flags instead of blindly specifying the resulting state of

all flags for a particular message, the operations are apparently aimed too

wide, targeting most of the messages in the mailbox even when some of them

were not shown to the user yet. In addition, KMail needlessly introduces

its own flag names even for those flags whose names are either standardized

or their use widely supported. An example is setting both KMAILFORWARDED

and $FORWARDED flags instead of just the former, semi-standardized [27] one.

The body parts of the complex MIME message from the MIME Tor-

ture Test are retrieved separately and the rendered representation of the

message corresponds to the original body structure, which is an impressive

result that no other e-mail client in this test (besides Trojita) achieved. The

text/plain messages are, however, fetched as one compact entity along

with their headers.

Common to both implementations, the mailbox hierarchy discovery is

performed as recommended by the IMAP best-practices [28], i.e., using the

‘‘%’’ wild character instead of ‘‘*’’.

KMail 1.11.1 with KDE 4.2.1 performed in a similar way to the already

discussed version.

4.4 Mozilla Thunderbird 2.0

Mozilla Thunderbird [29] has been the e-mail client of choice for the author

of this thesis. The GUI is excellent, not only well-looking, but also extremely

convenient to use. However, its support for detecting changes to the mailbox

performed by another session leaves much to be desired – sometimes it is

3The authors state that this limitation is present due to the architecture of the KDE’s

KIO framework which does not really allow similar modes of operation but is designed

for client-initiated actions only.

40

prone to not updating the displayed state based on what is received from

the server.

Thunderbird by default shows only subscribed mailboxes, i.e., those that

were flagged by the user as interesting in some way. Their discovery is

performed using the ‘‘*’’ wild mask, which might potentially result in a

large list to fetch. On the other hand, assuming that the user did not mark

too many mailboxes is probably acceptable. The MIME parsing is deferred

to the e-mail client, as a common choice among the graphical Mail User

Agents. We assume that this is a direct result of support for other protocols

than IMAP which do not provide any form of server-side MIME support,

and the client therefore has no reason not to decompose the message itself

after receiving the full body in one part.

Thunderbird by default opens several connections to the IMAP server

and uses IDLE for asynchronous notifications about new messages in each

of them. The limit on number of concurrent connections is configurable [30],

which is probably the only reasonable approach to figuring out how many

of them will not yet be considered an abuse by the server operators4.

4.5 Mailody

Mailody [31] originally started as a standalone IMAP e-mail client, an alter-

native to KMail. During the development of KDE4, its code base became

the foundation of the IMAP support in Akonady, a framework for PIM5

information exchange in the then-upcoming KDE4 desktop.

We were unable to test the version identified as “1.5.0-beta1” on KDE

4.2.1 as it crashed with a segmentation fault each time we tried to make it

talk to our testing Dovecot instance. A similar result was observed when

trying the older 0.5.0 version on KDE 3.5.10.

From the IMAP traffic dumps obtained before the application crashed,

it is evident that while the authors of Mailody certainly thought about how

to implement IMAP properly (as documented, e.g., by an attempt to group

4Client developers might argue that leaving tens of concurrent connections to the

server open at the same time, each of them in the IDLE mode in a particular mailbox, is

actually better for the server than multiplexing the access using just one or a few of IMAP

threads. The client developers are of course right, but the server administrators usually

cannot be expected to have such a deep understanding of the IMAP protocol. Indeed,

most of them would prefer to ban such a user.

5Personal Information Management

41

a large message set to smaller parts), it is not a finished product yet. As

an example, IMAP allows packing of a contiguous sequence into an interval

specified by both boundaries. Mailody fails to use this feature, requesting the

range by enumerating all values contained therein. It also does not seem to

notice the IMAP envelope at all, fetching the corresponding headers directly.

While the latter it not an error, strictly speaking, it at least makes the reader

of the source code wonder what led to that particular choice.

Earlier versions of Mailody had troubles even with mailbox names be-

ing passed as literals instead of quoted strings. This might be caused by

the fact that the source code used rigid regular expressions for parsing of

server replies which did not account for each possible response variation.

For example, such a naive parser would have troubles recognizing a reply

containing a response code6, which is free to be present in most situations.

4.6 Outlook Express

The Outlook Express is the built-in e-mail client in various versions of Mi-

crosoft Windows. The version we tested was shipped with Windows XP,

and is the latest release of the Outlook Express ever7.

The IMAP support in the Outlook Express is suboptimal, to say the

least. An example of the “efficiency” of the protocol implementation is how

the Outlook Express behaves when the user has selected several folders to

be subscribed. At first, the application opens multiple connections to the

server. Each of these connections then changes the subscription status of

one mailbox, enters IDLE for a short time and finally terminates.

When the application opened a mailbox with roughly five thousand test

messages, it began an immediate full download of all of them. Each messages

was fetched by a dedicated command, adding one useless parameter to the

list of items to fetch, and the IDLE mode was entered and immediately

left between each two commands. That accounts for circa five thousand

attempts to enter the IDLE mode, each of them lasting several milliseconds.

The GUI part of the application leaves much to be desired, too. A

notable example is its handling of multipart/signed message parts – if

the signature is made according to MIME/OpenPGP [32], Outlook Express

6Consult Section 2.4.1 for more on the concept of response codes

7The product got re-branded to Windows Mail and subsequently to Windows Live

Mail

42

displays an empty message with two attachments, the signed body and the

signature itself. This effectively prevents most users from actually reading

the PGP-signed e-mails, as they do not expect the “real message body” to be

available as an attachment only. Another problem exists with the display

of the X-509 signed e-mails which contain a valid signature that cannot

be verified. If such a signature is found, the Outlook Express displays a

misleading warning about a possible security threat to the local computer

instead of calmly informing the user about the fact that the certificate of the

CA8 is not found and thus the signature could not be verified. An extra click

or two is needed to display the actual message body. This again presents a

big obstacle to the actual usage of the signed e-mail on the Internet, for the

Outlook Express still has a substantial market share.

4.7 Windows Live Mail

After the deprecation of the Outlook Express during the development phase

of Windows Vista, a new e-mail application called Windows Mail has been

introduced. However, it was not being shipped for a long time, as yet an-

other successor, the Windows Live Mail, got introduced. Windows Live

Mail is expected to be the e-mail application distributed with the upcoming

Windows Seven operating system.

Unfortunately, most of the issues mentioned in the section about Outlook

Express still stand. Both applications apparently use not only the same (or

remarkably similar) IMAP code, but also a not-so-different GUI layer –

while the overall appearance has certainly changed since Outlook Express,

the issues with presentation of, e.g., the PGP/MIME signed e-mail messages

persist. We will therefore end this section by an observation that the IMAP

experience is almost the same as with the Outlook Express.

4.8 Trojita

Trojita is an IMAP client with support for various mail access modes. It

can be told not to request data which were not loaded from the network yet,

supports an efficient re-synchronization mode which tries to minimize the

network traffic and tries to deal with even the most advanced MIME mes-

sages reasonably. The IMAP conversation could still be improved, though

8Certificate Authority, an entity which issues certificates to other entities

43

– for example, an initial LIST is issued even before the user is properly

authenticated.

In general, we believe that we have implemented the IMAP protocol

completely and properly. We tried to follow the IMAP RFC to the letter,

but were sometimes forced to relax our requirements a bit, for example when

talking to the Cyrus IMAP server which regularly sends replies which do not

contain a textual part at all, in spite of the protocol grammar mandating

its presence. We try to handle most situations gracefully, e.g., by resorting

to a full mailbox re-synchronization when Trojita detects that the mailbox

state changed in other ways than the server already acknowledged.

When compared to Alpine and Mutt, Trojita supports an offline message

cache which allows its operation even when the connection to the remote

IMAP server cannot be obtained. Its support for IDLE is also arguably

better than that of Mutt, entering the IDLE more often.

Comparing with the messaging platform from Microsoft would not be

fair. It is commonly accepted that the Outlook Express managed to im-

plement IMAP in such a broken way that any further comment would be

redundant.

The KMail offers a nice GUI and integration with the rest of the KDE

desktop. Its IMAP support is, however, not that polished up. If Trojita had

the GUI and related features of KMail, it would be hard to beat in terms of

usability.

Finally, Mozilla Thunderbird is quite an impressive application. Even

though we might have certain reservations to the overall Mozilla architec-

ture, the GUI is user friendly and clean, and the application just works

most of the time. In certain corner-cases, such as when working over a low-

bandwidth network connection, Trojita has potential for outperforming the

Thunderbird thanks to the employment of server-side MIME parsing. In

fact, Trojita has already bitten Thunderbird when dealing with one partic-

ular HTML-formatted message which Mozilla fails to render properly, while

Trojita handles it without any problem.

A conclusion of Trojita’s overall usability is provided in the end of the

thesis.

44

Chapter 5

User’s Guide

5.1 About Trojita

Trojita is a standards-compliant IMAP Mail User Agent. Designed with

portability and efficiency in mind, it allows the user to operate over congested

network lines with high latency, while still providing sufficient comfort.

5.2 Installation

5.2.1 Prerequisites

In order to build Trojita from source, several libraries and helper programs

are required to be present on the system.

1. CMake 2.6 or later

2. Qt 4.4 or later

3. Working implementation of the TR1 C++ standard such as GCC 4.3

or newer or the Boost libraries

A recommended version of the Qt framework [33] is at least 4.5. Trojita,

however, includes compatibility code for older versions of Qt. The minimal

supported version is Qt/4.4. Any older release cannot be supported, as the

WebKit HTML engine which we use for e-mail rendering was added during

the 4.4 development. If users choose to build against 4.4, some Trojita

features might be missing.

45

Unlike most Qt projects, Trojita uses CMake [34] instead of qmake, es-

pecially due to author’s familiarity with the former system.

Trojita makes use of some standard C++ features that were adding dur-

ing the TR1 [14] standardisation, namely the std::tr1::shared ptr smart

pointer. A working implementation of said class is required. Trojita build

system will make use of compiler’s built-in TR1 support, if available, and

resort to using Boost if the compiler does not support this extension.

Some third-party code is also bundled in the source code distribution.

A list of such products including the reason for not just using an external

library follows:

1. QwwSmtpClient [35] is a Qt SMTP client library written by Witold

Wysota. Released to public only in mid May 2009, obtaining a package

of it might prove challenging. The copy in Trojita’s codebase also

contains some fixes which did not made it to the publicly released

version yet.

2. ModelTest [36], a class for verifying certain assumptions of the Inter-

view Model-View framework of Qt. Qt Software (former Trolltech)

does not ship it with Qt sources, so Trojita includes a copy for devel-

opers’ convenience. This feature is not turned on by default in release

builds.

3. QtIconLoader [19], another helper library from Qt Software. Its pur-

pose is to provide a unified icon set, as per relevant XDG standards.

4. KCodecs [37], an implementation of UTF-7, Base64, Quoted-Printable

and related RFC 2047 standards. These functions are reasonably self-

contained, so they are bundled with Trojita instead of depending on

quite heavyweight kdelibs.

5.2.2 Obtaining source code

Source code is available from the CD (see A) attached to this thesis or online

at http://trojita.flaska.net/.

5.2.3 Installing

Unpack the source tarball, prepare the build environment and launch the

compile process by entering these commands:

46

1. tar -xf trojita-1.0.tar.bz2

2. cd trojita-1.0

3. mkdir build

4. cd build

5. cmake -DCMAKE BUILD TYPE=RelWithDebInfo .. (the .. are not a

typo)

6. make

After a while, a new binary, trojita, will appear in the build directory.

Launch it to start Trojita.

5.3 Using Trojita

5.3.1 Configuration

All configuration is, thanks to the Qt’s QSettings, stored in target platform’s

common storage location. The only supported mean of configuring Trojita

is through its built-in configuration dialog that will automatically appear on

the first run. It can also be launched any time later from the application

menu.

On the first page, user is asked to provide identity data. These are used

for composing e-mail messages.

Second page is the most important one in configuration of Trojita. It

is the place where the user tells the application which IMAP server is it

supposed to talk to, which credentials should be used for authentication,

etc.

One unusual thing which is not common among other MUAs is the choice

of how to connect to the IMAP server. Most users are probably familiar with

connections over TCP, optionally secured by SSL/TLS, but the last option,

the Local Process, is unique to Trojita. If selected, it replaces the usual TCP

connection to the IMAP server with launching a local process, which is in

turn used instead of the remote IMAP server. The most interesting use case

is to set up SSH connection to the remote server (along with proper SSH

keys) and use that as a secure, reliable and convenient way for accessing e-

mail, without having to enter passwords all the time. For example, to launch

47

an instance of Dovecot IMAP server on host mail.example.org, user should

enter ssh mail.example.org dovecot –exec-mail imap.

The last page serves for configuring the message composition and send-

ing. Trojita supports mail submission via SMTP1 and local sendmail-

compatible MSA2 application.

5.3.2 Basic usage

After the configuration is complete, the user is presented with a familiar user

interface. The left pane presents a view of remote mailboxes, or folders, on

the IMAP server. The top widget contains a list of messages in the currently

opened folder, and finally the bottom area is reserved for displaying the

actual e-mail messages.

Depending on the network parameters and server load, it might take

a while before the list of mailboxes appears. The delay is only significant

when launching Trojita for the first time, for the retrieved list of mailboxes

is cached on a persistent disk cache for later use.

After the list of mailboxes is loaded, user can click on them to open them

in the Message List widget on the upper right corner of the application win-

dow. After having selected a mailbox, the list of messages appears shortly.

Again, the loading is faster next time Trojita is launched.

Depending on user settings, Trojita typically will not transfer all message

metadata upon opening a mailbox. This feature is implemented to conserve

both server’s and client’s resources and to be nice to the network traffic. In a

typical mode, that is, when not being told to be extra-mean with resources,

Trojita fetches only metadata of those messages that are displayed on the

visible screen region, and some more to make scrolling smoother. More on

this topic is said in section 3.6 of this thesis.

Message contents is transfered on-demand only, that is, when user selects

a message for viewing. As before, all persistent contents once downloaded

from the server is cached in a persistent on-disk cache for future use. This

applies to both message metadata and the real contents of e-mails.

1Simple Mail Transfer Protocol

2Mail Submission Agent[38], a local gateway whose purpose is forwarding e-mail to

the network of MTAs

48

5.3.3 Managing Messages and Mailboxes

Messages displayed to the user are automatically marked as read after some

delay. The idea behind this feature is to allow users to peek on a particular

message, shortly judge its contents, classify it as a “process later” and then

move on to another one. This is a common approach shared with other

MUAs as well.

Manipulating with message flags (see chapter 2.2) is possible via the

context menu (appearing on the message list) as well by standard keyboard

shortcuts. The M key toggles the Read status and Delete key schedules

messages for removal.

In consistency with the usual IMAP approach (and unlike the common

modus operandi on mainstream desktop MUAs), Trojita has no concept of

Trash 3 for messages. Instead, each message can be marked as deleted. If

flagged as such, Trojita displays a graphical indicator next to the message

subject. A deleted message will not be physically removed from the mailbox

until the user explicitly requests such an action. This operation, called

expunge in the IMAP dictionary, is available from the application menu.

Expunging happens on one mailbox at a time, there is no way to tell the

IMAP server to permanently remove all deleted messages from all mailboxes.

To create new mailbox, user is expected to use the context menu on the

left mailbox view pane. Due to technical limitations, some IMAP servers

distinguish among folders that can contain other mailboxes and folders for

message store only. Additionally, there is no reliable way for the IMAP

client to tell whether the remote server is affected by this limitation or not.

Therefore, Trojita uses the same approach as other common MUAs and ask

user what kind of mailbox she wants to create.

Mailbox removal is triggered from the context menu as well. Due to the

possibly serious consequences of this action (there is no way to undelete a

removed mailbox), user is presented with a confirmation dialogue asking her

whether she is serious in her intent to remove the mailbox.

Messages can be copied or moved between mailboxes by simple drag-

and-drop operations. To place a copy of one or more messages into another

mailbox, simply select the messages to copy in the opened mailbox and then

drag them with mouse to the target mailbox. If user wants to move them

3A Trash is a mailbox that presents a view of all deleted messages. It might or might

not be a real mailbox on the server, or just a virtual folder implemented purely in the

e-mail client.

49

instead of performing a copy, she is supposed to hold the Shift key. This

behavior is determined by the Qt framework, so it might vary among the

supported platforms.

5.3.4 Message Composition

Message Composition widget is triggered by the corresponding item in the

menus. The displayed dialog should be familiar to most users.

5.3.5 Checking Mail

Trojita automatically checks the current folder for new messages. If the re-

mote server supports the IDLE extension [10], the method used is extremely

friendly to both network and server resources. In cases the server does not

support this feature, Trojita resorts to polling with all it disadvantages.

5.4 Advanced usage

5.4.1 Partial Message Fetching

Thanks to unique features of the IMAP protocol, it is not necessary to

fetch the whole message in order to display just a fragment of it. Trojita

handles this automatically, fetching message parts on demand. It also will

not transfer message metadata (like its RFC 2822 envelope) unless really

needed.

5.4.2 Offline Mode

When put into offline mode, Trojita will prevent itself from accessing the

network at all. Users will be still able to view already transfered data, but

no checks for new messages will be performed and those that are not stored

in local offline cache will not have actual message bodies displayed until the

user selects either online or expensive network mode from the menu.

5.4.3 Expensive Network

Some users connect to their IMAP servers over a slow or otherwise unsuitable

network. Examples include dial-up connections or various mobile solutions

50

like GPRS4 where the overall convenience of having all messages immediately

available is usually held back by the need to conserve network resources. In

such environments, it might be desirable to fetch only the absolute minimum

data required to provide properly synchronized view of the remote mailbox.

In this situation, the user is expected to choose the Expensive Network

mode from the application menu. Trojita will not preload data to improve

interactivity, nor will it show all message parts by default. Upon viewing a

message, only parts smaller than a certain size are transfered automatically,

others will be loaded after clicking a button. This on-demand loading is

implemented separately for each part, allowing great flexibility for the user

to choose what is interesting and what can be ignored.

5.4.4 Online Mode

Online mode, the common mode of operation, is what users are familiar

from other IMAP clients. Trojita employs intelligent preloading of inter-

esting contents to minimize waiting times, yet does not blindly download

everything, including parts that will not be ever shown.

5.4.5 Local Cache

All data once transfered form the network5 are kept in a persistent offline

on-disk cache. If a message data is transfered twice, it means that at least

one of the following conditions was met:

1. The server could not guarantee the immutability of messages. This

might happen when some process touches on-disk data internal to the

IMAP server in a non-standard way.

2. User has changed her settings. Whenever any data used to access

the remote server changes, the only safe thing to do is to throw away

anything in the local cache and start over again.

4General packet radio service (GPRS) is a mobile data service typically offering low

bandwidth, high latency Internet connection with billing based on the amount of trans-

fered data

5Subject to some restrictions like maximal message part size and cache parameters

51

5.4.6 Full Tree View

As an optional part of the GUI, the full tree view, activated by the corre-

sponding item in the menu, provides a full view of the server contents, in-

cluding mailbox hierarchy, messages in mailboxes and mailbox parts. This

widget is a nice demonstration of a complex nature of MIME messages –

while most users are probably familiar with the concept of attachments,

the truth is that MIME defines a fully recursive structure that one mes-

sage can consist of. For example, it is perfectly possible to have a message

composed of six parts, each of them being a forwarded message, and each

of these forwarded messages being rich-structured as well. Trojita does its

best at formatting the message in a sane and familiar way, but unfortunately

some senders do not really follow the same philosophy and produce messages

whose structure leaves much to be desired.

More on this matter can be found in section 3.2.

52

Chapter 6

Conclusion

The goal of this thesis was to demonstrate that an IMAP e-mail client could

be usable, yet implement the relevant RFCs properly and behave in an

efficient way.

After an introduction to the world of IMAP and other Internet messaging

standards in the second chapter of the thesis, we described the design of

Trojita, the application implemented in this thesis, as well as provided a

comparison with other commonly used IMAP e-mail clients.

While it is evident that the GUI of Trojita is not as mature as the inter-

face of other, more established Mail User Agents such as Mozilla Thunder-

bird or the KMail, the core IMAP engine design is sound. Already offering

complete support for the IMAP4rev1 protocol as defined by RFC 3501 [1],

Trojita implements most important IMAP extensions such as IDLE [10] and

conforms to various IMAP client implementation recommendations which

accumulated over more than twenty years of the IMAP history. Special em-

phasis is placed at transferring only the required data, minimizing network

transfers as well as memory consumption. As a result of these optimizations,

Trojita operates swiftly even when faced with huge mailboxes containing tens

of thousands of e-mail messages.

Mailbox re-synchronization uses as much data from the previously recorded

mailbox state as permitted by the standards while the persistent offline cache

with a pluggable architecture allows storing of already downloaded message

parts among sessions and enables offline browsing of the remote server’s

contents when no network connection is available.

The rendering of the MIME messages provides a faithful reflection of the

MIME structure, yet sustains an acceptable level of user-friendliness.

53

A feature unique to Trojita is its support of operation over a UNIX

pipe to the local process instead of through a TCP socket. When combined

with SSH and the ssh-agent, it allows a convenient password-less operation

without sacrificing security.

Finally, Trojita, as presented in this thesis, is a result of several years of

the author’s involvement in the area of Internet messaging. Trojita, being

written in a modular way, provides a mature design platform, enabling the

convenient and rapid integration of new features. It is the ultimate goal of

the author to deliver a fully usable IMAP client aimed at advanced users

who need to work with lots of e-mail in an effective way. Therefore, he plans

to continue the maintenance of the project and develop new features in the

years to come. After the GUI is matured, whole range of possibilities for new

functions is open, from message encryption to supporting even experimental

IMAP extensions.

Thanks to its unique design which employs both well-known software

design patterns as well as new features offered by the modern Qt toolkit,

Trojita certainly has the potential of becoming a competitive IMAP client

on the open source desktop scene.

54

Bibliography

[1] Crispin, M.: Internet Message Access Protocol – Version 4rev1,

RFC 3501, March 2003,

http://tools.ietf.org/html/rfc3501

[2] Crispin, M.: Ten Commandments of How to Write an IMAP client,

September 2006, Washington,

http://www.washington.edu/imap/documentation/commndmt.txt.html

[3] Resnick, P. (editor) et al.: Internet Message Format, RFC 2822,

April 2001,

http://tools.ietf.org/html/rfc2822

[4] Freed, N., Borenstein, N.: Multipurpose Internet Mail Extensions

(MIME) Part One: Format of Internet Message Bodies, RFC 2045,

November 1996,

http://tools.ietf.org/html/rfc2045

[5] Freed, N., Borenstein, N..: Multipurpose Internet Mail Extensions

(MIME) Part Two: Media Types, RFC 2046, November 1996,

http://tools.ietf.org/html/rfc2046

[6] Moore, K.: MIME (Multipurpose Internet Mail Extensions) Part Three:

Message Header Extensions for Non-ASCII Text, RFC 2047, Novem-

ber 1996,

http://tools.ietf.org/html/rfc2047

[7] Levinson, E.: The MIME Multipart/Related Content-type, RFC 2387,

August 1998,

http://tools.ietf.org/html/rfc2387

55

[8] Crispin, M., Murchison, K.: Internet Message Access Protocol – SORT

and THREAD Extensions, RFC 5256, June 2008,

http://tools.ietf.org/html/rfc5256

[9] Myers, J.: IMAP4 non-synchronizing literals, RFC 2088, January 1997,

http://tools.ietf.org/html/rfc2088

[10] Leiba, B.: IMAP4 IDLE command, RFC 2177, June 1997

[11] Gray, T.: Message Access Paradigms and Protocols, September 1995,

online at ftp://ftp.cac.washington.edu/mail/imap.vs.pop

[12] Qt Software: The Interview Framework,

http://doc.trolltech.com/4.5/qt4-interview.html

[13] Qt Software: QtWebKit Module,

http://doc.trolltech.com/4.5/qtwebkit.html

[14] ISO/IEC TR 19768, C++ Library Extensions

[15] QProcess could close the reading pipe, thus killing the child

process with SIGPIPE, a thread on the qt-interest mailing list,

http://lists.trolltech.com/pipermail/qt-interest/2009-May/

006341.html

[16] Gamma, E., Helm, R., Johnson, R., Vlissides, J.: Design Patterns: Ele-

ments of Reusable Object-Oriented Software, Boston: Addison-Wesley,

1995

[17] Troost, R., Dorner, S., Moore, K.: Communicating Presentation Infor-

mation in Internet Messages: The Content-Disposition Header Field,

RFC 2183, August 1997,

http://tools.ietf.org/html/rfc2183

[18] Levinson, E.: Content-ID and Message-ID Uniform Resource Locators,

RFC 2111, March 1997,

http://tools.ietf.org/html/rfc2111

[19] Qt Software, February 2009,

http://labs.trolltech.com/blogs/2009/02/13/

freedesktop-icons-in-qt/

56

[20] Dawes, R., The FreeDesktop Project: Icon Naming Specification

v. 0.8.90,

http://standards.freedesktop.org/icon-naming-spec/

icon-naming-spec-0.8.90.html

[21] Dovecot, Secure IMAP server,

http://www.dovecot.org/

[22] Crispin, M.: The MIME Torture Test Mailbox,

ftp://ftp.cac.washington.edu/imap/mime-examples/

torture-test.mbox

[23] Alpine Messaging System,

http://www.washington.edu/alpine/

[24] Does pine make use of the IMAP IDLE command?, discussion board,

http://objectmix.com/pine/

206216-does-pine-make-use-imap-idle-command.html

[25] The Mutt E-mail Client,

http://www.mutt.org/

[26] KMail: Kontact Mail,

http://kontact.kde.org/kmail/

[27] Melnikov, A.: Common IMAP keywords, Expired Internet Draft,

http://tools.ietf.org/html/draft-melnikov-imap-keywords-03

[28] Sirainen, T., Cridland, D. et al.: Best Practices for Implementing an

IMAP Client, http://www.imapwiki.org/ClientImplementation

[29] Mozilla Thunderbird,

http://www.mozillamessaging.com/en-US/thunderbird/

[30] Mozilla Developer Center: IMAP,

https://developer.mozilla.org/en/IMAP

[31] Mailody,

http://www.mailody.net/

[32] Elkins, M. et al.: MIME Security with OpenPGP, RFC 3156, Au-

gust 2001

http://tools.ietf.org/html/rfc3156

57

[33] Qt Reference Documentation,

http://doc.trolltech.com/4.5/

[34] CMake Documentation,

http://www.cmake.org/cmake/help/documentation.html

[35] Wysota, W.: QwwSmtpClient released, May 2009,

http://blog.wysota.eu.org/index.php/2009/05/13/

qwwsmtpclient-released/

[36] Qt Software, ModelTest, February 2008,

http://labs.trolltech.com/page/Projects/Itemview/Modeltest

[37] The KDE Project: kdelibs,

http://api.kde.org/4.x-api/kdelibs-apidocs/

[38] Gellens, R., Klensin, J.: Message Submission, RFC 2476, Decem-

ber 1998,

http://tools.ietf.org/html/rfc2476

58

Appendix A

Contents of the CD

The attached CD-ROM is an integral part of this thesis. The contents of

the top-level trojita directory is the following:

bin Compiled binaries of Trojita suitable for running on several Linux

flavours

doc A copy of each publicly available document referenced in the bibliog-

raphy

doxygen An automatically generated API documentation of Trojita

src The source code of Trojita

thesis A printable PDF file with the text of this thesis

59

Similar Posts