<!doctype article PUBLIC "-//Davenport//DTD DocBook V3.0//EN" [
<!entity Evolution "<application>Evolution</application>">
<!entity Camel "Camel">
]>
<article class="whitepaper" id="camel">
<artheader>
<title>The &Camel; Messaging Library</title>
<authorgroup>
<author>
<firstname>Dan</firstname>
<surname>Winship</surname>
<affiliation>
<address>
<email>danw@helixcode.com</email>
</address>
</affiliation>
</author>
<author>
<firstname>Bertrand</firstname>
<surname>Guiheneuf</surname>
<affiliation>
<address>
<email>bertrand@helixcode.com</email>
</address>
</affiliation>
</author>
</authorgroup>
<copyright>
<year>2000</year>
<holder>Helix Code, Inc.</holder>
</copyright>
</artheader>
<sect1 id="introduction">
<title>Introduction</title>
<para>
&Camel; is a generic messaging library. It is being used as the
back end for the mail component of &Evolution;. The name
"&Camel;" is an acronym; it refers to the fact that the
library is capable of going several days without food or water.
It means : Camel's Acronym Makes Everyone Laugh.
</para>
<para>
&Camel;'s initial design is heavily based on Sun's
<trademark>JavaMail</trademark> API. It uses the Gtk+ object
system, and many of its classes are direct analags of JavaMail
classes. Its design has also been influenced by the features of
IMAP, and the limitations of the standard UNIX mbox mail store,
which set some of the boundaries on its requirements and
extensibility.
</para>
<para>
&Camel; sees all message repositories as stores containing
folders. These folders in turn contain the messages the client
actually accesses. The use of such a unified interface allows
the client applications to be very extensible. &Camel; includes
an external provider mechanism which allows applications to
dynamically load and use protocols which were not available when
the application was initially written.
</para>
<para>
The abstract store/folder mechanism is a powerful and versatile
way of accessing messages. No particular asumptions are made on
the client side, thus allowing new ways of managing the
messages. For example, the messages stored in the folders don't
necessarily have to share some common physical location. The
folder can be a purely virtual folder, containing only
references to the actual messages. This is used by the "vFolder"
provider, which allows you select messages meeting particular
criteria and deal with them as a group.
</para>
<para>
In addition to these possibilities, &Camel; has full MIME
support. &Camel; MIME messages are lightweight objects
representing the MIME skeleton of the actual message. The data
contained in the subparts are never stored in memory except when
they are actually needed. The application, when accessing the
various MIME objects contained in the message (text parts,
attachments, embedded binary objects ...) asks &Camel; for a
stream that it can read data from. This scheme is particularly
useful with the IMAP provider. IMAP has strong MIME support
built-in, which allows &Camel; to download only the parts of
messages that it actually needs: attachments need not be
downloaded until they are viewed, and unnecessary
"multipart/alternative" parts will never be read off the server.
</para>
</sect1>
<sect1 id="overview">
<title>Overview</title>
<graphic format="gif" fileref="camel"></graphic>
<para>
To begin using &Camel;, an application first creates a
<classname>CamelSession</classname> object. This object is used
to store application defaults, and to coordinate communication
between providers and the application.
</para>
<para>
A <classname>CamelProvider</classname> is a dynamically-loadable
module that provides functionality associated with a specific
service. Examples of providers are IMAP and SMTP. Providers
include subclasses of the various other &Camel; classes for
accessing and manipulating messages.
</para>
<para>
<classname>CamelService</classname> is an abstract class for
describing a connection to a local or remote service. It
currently has two subclasses: <classname>CamelStore</classname>,
for services that store messages (such as IMAP servers and mbox
files), and <classname>CamelTransport</classname>, for services
that deliver messages (such as SMTP, or a local MTA). A provider
could also be both a store and a transport, as in the case of
NNTP.
</para>
<para>
A <classname>CamelStore</classname> contains some number of
<classname>CamelFolder</classname> objects, which in turn
contain messages. A <classname>CamelFolder</classname> provides
a <classname>CamelFolderSummary</classname> object, which
includes details about the subject, date, and sender of each
message in the folder. The folder also includes the messages
themselves, as subclasses of <classname>CamelMedium</classname>.
</para>
<para>
Email messages are represented by the
<classname>CamelMimeMessage</classname> class, a subclass of
<classname>CamelMedium</classname>. This class includes
operations for accessing RFC822 and MIME headers, accessing
subparts of MIME messages, encoding and decoding Base64 and
Quoted-Printable, etc.
</para>
<para>
<classname>CamelTransport</classname> includes methods for
delivering messages. While the abstract
<function>CamelTransport::send</function> method takes a
<classname>CamelMedium</classname>, its subclasses may only be
able to deliver messages of specific
<classname>CamelMedium</classname> subclasses. For instance,
<classname>CamelSendmailTransport</classname> requires a
<classname>CamelMimeMessage</classname>, because it needs a
message that includes a "To:" header. A hypothetical
<classname>CamelNNTPTransport</classname> would need a
<classname>CamelNewsMessage</classname>, which would have a
"Newsgroups:" header.
</para>
<para>
The content of messages are referred to using
<classname>CamelStream</classname> and its subclasses. In the
case of an mbox-based store, the
<classname>CamelStream</classname> would abstract the operation
of reading the correct section of the mbox file. For IMAP,
reading off the <classname>CamelStream</classname> might result
in commands being issued to the remote IMAP server and data
being read off a socket.
</para>
<para>
The final major class in &Camel; is
<classname>CamelException</classname>, which is used to
propagate information about errors. Many methods take a
<classname>CamelException</classname> as an argument, which the
caller can then check if an error occurs. It includes both a
numeric error code which can be interpreted by the program, and
a text error message that can be displayed to the user.
</para>
</sect1>
<sect1 id="classes">
<title>Major Subcomponents</title>
<sect2 id="store">
<title>The Message Store</title>
<para>
A <classname>CamelStore</classname> inherits the ability to
connect and authenticate to a service from its parent class,
<classname>CamelService</classname>. It then adds the ability
to retrieve folders. A store must contain at least one folder,
which can be retrieved with
<function>CamelStore::get_default_folder</function>. There are
also methods to retrieve the "top-level" folder (for
hieararchical stores), and to retrieve an arbitrary folder by
name.
</para>
<para>
All <classname>CamelFolder</classname>s must implement certain
core operations, most notably generating a summary and
retrieving and deleting messages. A
<classname>CamelFolder</classname> must assign a permanently
unique identifier to each message it contains. Messages can
then be retrieved via
<function>CamelFolder::get_message_by_uid</function>. Alternately,
within a single mail-reading session, messages can be referred
to by their linear position within the store using
<function>CamelFolder::get_message_by_number</function>.
</para>
<para>
Folders must also implement the
<function>get_parent_folder</function> and
<function>list_subfolders</function> methods. For stores that
don't allow multiple folders, they would return NULL and an
empty list, respectively. Stores that do allow multiple
folders will also define methods for creating and deleting
folders, and for moving messages between them (assuming the
folders are writable).
</para>
<para>
Folders that support searching can define the
<function>search_by_expression</function> method. For mbox
folders, this is implemented by indexing the messages with the
ibex library and using that to search them later. For IMAP
folders, this uses the IMAP SEARCH command. Other folder types
might not be able to implement this functionality, in which
case users would not be able to do full-content searches on
them.
</para>
</sect2>
<sect2 id="messages">
<title>Messages</title>
<para>
As mentioned before, messages are represented by subclasses of
<classname>CamelMedium</classname>.
<classname>CamelMedium</classname> itself is a subclass of
<classname>CamelDataWrapper</classname>, a generic class for
connecting a typed data source to a data sink.
<classname>CamelMedium</classname> adds the concept of message
headers versus message body.
(<classname>CamelDataWrapper</classname> has one other
important subclass, <classname>CamelMultipart</classname>,
which is used to provide separate access to the multiple
independent parts of a multipart MIME type.)
<classname>CamelMedium</classname>'s subclasses provide more
specialized handling of various headers:
<classname>CamelMimePart</classname> adds special handling for
the &ldquot;Content-*&rdquot; headers in MIME messages, and
its subclass <classname>CamelMimeMessage</classname> adds
handling for the RFC822 headers.
</para>
<graphic format="gif" fileref="mimemessage"></graphic>
<para>
Consider a message with two parts: a text part (in both plain
text and HTML), and an attached image:
<programlisting>
From: Dan Winship <danw@helixcode.com>
To: Matt Loper <matt@helixcode.com>
Subject: the Camel white paper
MIME-Version: 1.0
Content-Type: multipart/mixed;
boundary="jhTYrnsRrdhDFGa"
This is a multi-part message in MIME format.
--jhTYrnsRrdhDFGa
Content-Type: multipart/alternative;
boundary="sFSenbAFDSgDfg"
--sFSenbAFDSgDfg
Content-Type: text/plain
Hey, Matt
Check out this graphic...
-- Dan
--sFSenbAFDSgDfg
Content-Type: text/html
Hey, Matt<br>
<br>
Check out this graphic...<br>
<br>
-- Dan<br>
<br>
--sFSenbAFDSgDfg--
--jhTYrnsRrdhDFGa
Content-Type: image/png
Content-Transfer-Encoding: base64
F4JLw0ORrkRa8AwAMQJLAaI3UDIGsco9RAaB92...
--jhTYrnsRrdhDFGa--
</programlisting>
<para>
In &Camel;, this would be represented as follows:
</para>
<graphic fileref="samplemsg"></graphic>
</sect2>
<sect2 id="streams">
<title>Streams</title>
<para>
Streams are a generic data transport layer. Two basic stream
classes are <classname>CamelStreamFs</classname>, for
reading and writing files, and
<classname>CamelStreamMem</classname>, for reading from and
writing to objects that are already in memory.
</para>
<para>
Streams can also be chained together. So a CamelMimePart
containing base64-encoded data can filter its output through
a CamelStreamB64. Other parts of the application that want
to read its data will never need to even realize that the
original data was encoded.
</para>
</sect2>
</article>