diff options
author | Wojtek Kosior <wk@koszkonutek-tmp.pl.eu.org> | 2021-04-30 00:33:56 +0200 |
---|---|---|
committer | Wojtek Kosior <wk@koszkonutek-tmp.pl.eu.org> | 2021-04-30 00:33:56 +0200 |
commit | aa4d426b4d3527d7e166df1a05058c9a4a0f6683 (patch) | |
tree | 4ff17ce8b89a2321b9d0ed4bcfc37c447bcb6820 /vmime-master/doc | |
download | smtps-and-pop3s-console-program-aa4d426b4d3527d7e166df1a05058c9a4a0f6683.tar.gz smtps-and-pop3s-console-program-aa4d426b4d3527d7e166df1a05058c9a4a0f6683.zip |
Diffstat (limited to 'vmime-master/doc')
-rw-r--r-- | vmime-master/doc/book/.gitignore | 17 | ||||
-rw-r--r-- | vmime-master/doc/book/basics.tex | 823 | ||||
-rw-r--r-- | vmime-master/doc/book/book.tex | 118 | ||||
-rw-r--r-- | vmime-master/doc/book/building.tex | 175 | ||||
-rw-r--r-- | vmime-master/doc/book/images/address-mailbox-mailboxgroup.svg | 355 | ||||
-rw-r--r-- | vmime-master/doc/book/images/message-body-header.svg | 716 | ||||
-rw-r--r-- | vmime-master/doc/book/images/messaging-services.svg | 617 | ||||
-rw-r--r-- | vmime-master/doc/book/intro.tex | 90 | ||||
-rw-r--r-- | vmime-master/doc/book/msg.tex | 430 | ||||
-rw-r--r-- | vmime-master/doc/book/net.tex | 1203 | ||||
-rw-r--r-- | vmime-master/doc/book/start.tex | 111 |
11 files changed, 4655 insertions, 0 deletions
diff --git a/vmime-master/doc/book/.gitignore b/vmime-master/doc/book/.gitignore new file mode 100644 index 0000000..5bb5584 --- /dev/null +++ b/vmime-master/doc/book/.gitignore @@ -0,0 +1,17 @@ +# PDFLatex +*.log +*.aux +*.toc +*.out +*.pdf +*.lo[flt] + +# Hevea +*.haux +*.htoc +book.image.tex +book.html + +images/Makefile2 +images/*.png + diff --git a/vmime-master/doc/book/basics.tex b/vmime-master/doc/book/basics.tex new file mode 100644 index 0000000..94633ef --- /dev/null +++ b/vmime-master/doc/book/basics.tex @@ -0,0 +1,823 @@ +\chapter{Basics} + +% ============================================================================ +\section{Reference counting} + +\subsection{Introduction} % -------------------------------------------------- + +Since version 0.7.2cvs, VMime use smart pointers to simplify memory +management. Smart pointers rely on +RAII\footnote{Ressource Allocation is Initialisation} so that we do not need +to bother with deleting an object (freeing memory) when it is not used +anymore. + +There are two possibilities for owning a reference to an object. We can own a +strong reference to an object: as long as we keep this reference, the object +is not destroyed. Or we can own a weak reference to the object: the object can +be destroyed if nobody owns a strong reference to it, in which case the weak +reference becomes invalid. + +An object is destroyed as soon as the last strong reference to it is released. +At the same tine, all weak references (if any) are automatically set to point +to \vnull. + +In VMime, these two types of references are known as {\vcode vmime::shared\_ptr} +and {\vcode vmime::weak\_ptr}, respectively. + +\vnote{since November 2013, we switched from an old, intrusive implementation +of smart pointers to a more standard one: either Boost {\vcode shared\_ptr<>} +implementation or standard C++ one if we are compiling in C++11. Here are the +changes: + +{\vcode vmime::ref <>} is replaced with {\vcode vmime::shared\_ptr <>} + +{\vcode vmime::weak\_ref <>} is replaced with {\vcode vmime::weak\_ptr <>} + +{\vcode vmime::create <>} is replaced with {\vcode vmime::make\_shared <>} +} + +\subsection{Instanciating reference-counted objects} % ----------------------- + +In VMime, all objects that support reference counting inherit from the +{\vcode vmime::object} class, which is responsible for +incrementing/decrementing the counter and managing the object's life cycle. +If you want to create a smart pointer to a new object instance, you should +use the function {\vcode vmime::make\_shared} instead of the {\vcode new} +operator. + +\begin{lstlisting}[caption={Smarts pointers and creating objects}] +class myObject : public vmime::object { + +public: + + myObject(const vmime::string& name) + : m_name(name) { + + } + + void sayHello() { + + std::cout << "Hello " << m_name << std::endl; + } + +private: + + vmime::string m_name; +}; + +int main() { + + vmime::shared_ptr <myObject> obj = + vmime::make_shared <myObject>("world"); + + obj->sayHello(); + + return 0; + +} // Here, 'obj' gets automatically destroyed +\end{lstlisting} + +\subsection{Using smart pointers} % ------------------------------------------ + +Smart pointers are copiable, assignable and comparable. You can use them like +you would use normal ("raw") C++ pointers (eg. you can write +\lstinline{!ptr, ptr != NULL, ptr->method(), *ptr}...). + +Type safety is also guaranteed, and you can type cast smart pointers using +the {\vcode static\_cast()}, {\vcode dynamic\_cast()} and {\vcode const\_cast()} +equivalents on {\vcode vmime::shared\_ptr} and {\vcode vmime::weak\_ptr} objects: + +\begin{lstlisting}[caption={Casting smart pointers}] +class myBase : public vmime::object { } +class myObject : public myBase { } + +vmime::shared_ptr <myObject> obj = vmime::make_shared <myObject>(); + +// Implicit downcast +vmime::shared_ptr <myBase> base = obj; + +// Explicit upcast +vmime::shared_ptr <myObject> obj2 = vmime::dynamicCast <myObject>(base); +\end{lstlisting} + +Weak references are used to resolve reference cycles (an object which refers +directly or indirectly to itself). The following example illustrates a +typical problem of reference counting: + +\begin{lstlisting} +class parent : public vmime::object { + +public: + + void createChild(vmime::shared_ptr <child> c) { + + m_child = c; + } + +private: + + vmime::shared_ptr <child> m_child; +}; + +class child : public vmime::object { + +public: + + child(vmime::shared_ptr <parent> p) + : m_parent(p) { + + } + +private: + + vmime::shared_ptr <parent> m_parent; +}; + +int main() { + + vmime::shared_ptr <parent> p = vmime::make_shared <parent>(); + vmime::shared_ptr <child> c = vmime::make_shared <child>(); + + p->setChild(c); +} +\end{lstlisting} + +In this example, neither {\vcode p} nor {\vcode c} will be deleted when +exiting {\vcode main()}. That's because {\vcode p} indirectly points to itself +{\em via} {\vcode c}, and {\em vice versa}. The solution is to use a weak +reference to the parent: + +\begin{lstlisting} +vmime::weak_ptr <parent> m_parent; +\end{lstlisting} + +The decision to make the parent or the child a weak reference is purely +semantic, and it depends on the context and the relationships between the +objects. Note that when the parent is deleted, the {\vcode m\_parent} member +of the child points to \vnull. + +More information about reference counting can be found on +Wikipedia\footnote{http://en.wikipedia.org/wiki/Reference\_counting}. + +% ============================================================================ +\section{Error handling} + +In VMime, error handling is exclusively based on exceptions, there is no error +codes, or things like that. + +VMime code may throw exceptions in many different situations: an unexpected +error occurred, an operation is not supported, etc. You should catch them if +you want to report failures to the user. This is also useful when debugging +your program. + +VMime exceptions support chaining: an exception can be encapsulated into +another exception to hide implementation details. The function +{\vcode exception::other()} returns the next exception in the chain, +or \vnull. + +Following is an example code for catching VMime exceptions and writing error +messages to the console: + +\begin{lstlisting}[caption={Catching VMime exceptions}] +std::ostream& operator<<(std::ostream& os, const vmime::exception& e) { + + os << "* vmime::exceptions::" << e.name() << std::endl; + os << " what = " << e.what() << std::endl; + + // Recursively print all encapsuled exceptions + if (e.other() != NULL) { + os << *e.other(); + } + + return os; +} + +... + +try { + + // ...some call to VMime... + +} catch (vmime::exception& e) { + + std::cerr << e; // VMime exception + +} catch (std::exception& e) { + + std::cerr << e.what(); // standard exception +} +\end{lstlisting} + +Read the source of {\vexample example6} if yo want to see a more complete +example of using VMime exceptions (such as getting more detailed information +by using specialized classes of {\vcode vmime::exception}). + + +% ============================================================================ +\section{Basic objects} + +\subsection{The {\vcode component} class} % ---------------------------------- + +In VMime, all the components of a message inherit from the same class +{\vcode component}. This includes the message itself (classes {\vcode message} +and {\vcode bodyPart}), the header, the header fields and the value of each +header field, the body and all the parts in the message. + +The class component provide a common interface for parsing or generating all +these components (methods {\vcode parse()} and {\vcode generate()}). It also +provides additional functions to get some information about the parsing +process or the structure (methods {\vcode getParsedOffset()}, +{\vcode getParsedLength()} and {\vcode getChildComponents()}). + +VMime also provides a set of classes corresponding to the basic types found +in a message; for example a mailbox, a mailbox list, date/time information, +media type, etc. They all inherit from {\vcode component} too. + +\subsection{Date and time} % ------------------------------------------------- + +Date and time are used in several places in VMime, particularly in header +fields (Date, Received, ...). VMime fully supports RFC-2822's date and time +specification. The object {\vcode vmime::datetime} is used to manipulate date +and time information, and to parse/generate it from/to RFC-2822 format. + +The following code snippet show various manners of using the +{\vcode vmime::datetime} object: + +\begin{lstlisting}[caption={Using {\vcode vmime::datetime} object}] +// Creating from string in RFC-2822 format +vmime::datetime d1("Sat, 08 Oct 2005 14:07:52 +0200"); + +// Creating from components +vmime::datetime d2( + /* date */ 2005, vmime::datetime::OCTOBER, 8, + /* time */ 14, 7, 52, + /* zone */ vmime::datetime::GMT2 +); + +// Getting day of week +const int dow = d2.getWeekDay(); // 'dow' should be datetime::SATURDAY +\end{lstlisting} + +\subsection{Media type} % ---------------------------------------------------- + +In MIME, the nature of the data contained in parts is identified using a +media type. A general type (eg. \emph{image}) and a sub-type (eg. \emph{jpeg}) +are put together to form a media type (eg. \emph{image/jpeg}). This is also +called the MIME type. + +There are a lot of media types officially registered, and vendor-specific +types are possible (they start with ``x-'', eg. +\emph{application/x-zip-compressed}). + +In VMime, the object {\vcode vmime::mediaType} represents a media type. There +are also some constants for top-level types and sub-types in the +{\vcode vmime::mediaTypes} namespace. For example, you can instanciate a new +media type with: + +\begin{lstlisting} +vmime::mediaType theType( + /* top-level type */ vmime::mediaTypes::IMAGE, + /* sub-type */ vmime::mediaTypes::IMAGE_JPEG +); + +// theType.getType() is "image" +// theType.getSubType() is "jpeg" +// theType.generate() returns "image/jpeg" +\end{lstlisting} + +For more information about media types, see +RFC-2046\footnote{http://www.faqs.org/rfcs/rfc2046.html}. + +\subsection{Mailbox and mailbox groups} % ------------------------------------ + +VMime provides several objects for working with mailboxes and addresses. + +The {\vcode vmime::address} class is an abstract type for representing an +address: it can be either a mailbox (type {\vcode vmime::mailbox}) or a +mailbox group (type {\vcode vmime::mailboxGroup}). A mailbox is composed of +an email address (mandatory) and possibly a name. A mailbox group is simply +a named list of mailboxes (see Figure \ref{uml_addr_mbox_mboxgroup}). + +\begin{lstlisting}[caption={Using mailboxes and mailbox groups}] +vmime::shared_ptr <vmime::mailbox> mbox1 = vmime::make_shared <vmime::mailbox> + (/* name */ vmime::text("John Doe"), /* email */ "john.doe@acme.com"); +vmime::shared_ptr <vmime::mailbox> mbox2 = vmime::make_shared <vmime::mailbox> + (/* no name, email only */ "bill@acme.com"); + +vmime::shared_ptr <vmime::mailboxGroup> grp = vmime::make_shared <vmime::mailboxGroup>(); +grp->appendMailbox(mbox1); +grp->appendMailbox(mbox2); +\end{lstlisting} + +\begin{figure}[ht!] + \center\includegraphics[width=0.7\textwidth] + {images/address-mailbox-mailboxgroup.png}\endcenter + \caption{Diagram for address-related classes} + \label{uml_addr_mbox_mboxgroup} +\end{figure} + + +% ============================================================================ +\section{Message, body parts and header} + +\subsection{Introduction to MIME messages} % --------------------------------- + +A MIME message is a recursive structure in which each part can contains one +or more parts (or \emph{entities}). Each part is composed of a header and +a body (actual contents). Figure \ref{uml_msg_body_header} shows how this +model is implemented in VMime, and all classes that take part in it. + +\begin{figure} + \center\includegraphics[width=1.0\textwidth] + {images/message-body-header.png}\endcenter + \caption{Overall structure of MIME messages} + \label{uml_msg_body_header} +\end{figure} + + +\subsection{Header and header fields} % -------------------------------------- + +\subsubsection{Standard header fields} % ..................................... + +Header fields carry information about a message (or a part) and its contents. +Each header field has a name and a value. All types that can be used as a +field value inherit from the {\vcode headerFieldValue} class. + +You cannot instanciate header fields directly using their constructor. +Instead, you should use the {\vcode headerFieldFactory} object. This ensures +the right field type and value type is used for the specified field name. +For more information about how to use header fields and the factory, see +section \ref{msg-building-simple-message}. + +Some standard fields are officially registered and have their value type +specified in a RFC. Table \ref{standard-fields} lists all the fields +registered by default in VMime and the value type they contains. + +By default, all unregistered fields have a value of type {\vcode text}. + +\begin{table}[!ht] +\begin{center} +\noindent\begin{tabularx}{0.85\textwidth}{|X|X|} +\hline + {\bf Field Name} & + {\bf Value Type} \\ +\hline +\hline +From & mailbox \\ +To & addressList \\ +Cc & addressList \\ +Bcc & addressList \\ +Sender & mailbox \\ +Date & datetime \\ +Received & relay \\ +Subject & text \\ +Reply-To & mailbox \\ +Delivered-To & mailbox \\ +Organization & text \\ +Return-Path & path \\ +Mime-Version & text \\ +Content-Type & mediaType \\ +Content-Transfer-Encoding & encoding \\ +Content-Description & text \\ +Content-Disposition & contentDisposition \\ +Content-Id & messageId \\ +Content-Location & text \\ +Message-Id & messageId \\ +In-Reply-To & messageIdSequence \\ +References & messageIdSequence \\ +Original-Message-Id & messageId \\ +Disposition & disposition \\ +Disposition-Notification-To & mailboxList \\ +\hline +\end{tabularx} +\end{center} +\label{standard-fields} +\caption{Standard fields and their types} +\end{table} + + +\subsubsection{Parameterized fields} % ....................................... + +In addition to a value, some header fields can contain one or more +\emph{name=value} couples which are called \emph{parameters}. For example, +this is used in the \emph{Content-Type} field to give more information about +the content: + +\begin{verbatim} + Content-Type: text/plain; charset="utf-8" +\end{verbatim} + +Fields that support parameters inherit from the +{\vcode parameterizedHeaderField} class which provides methods to deal with +these parameters: {\vcode appendParameter()}, {\vcode getParameterAt()}... + +A parameter is identified by a name (eg. \emph{charset}) and associated to +a value of type {\vcode vmime::text}. Parameters provide helper functions to +convert automatically from basic types to text, and \emph{vice versa}. The +following example illustrates it: + +\begin{lstlisting}[caption={Getting and setting parameter value in fields}] +vmime::shared_ptr <vmime::parameterizedField> field = + header->findField <vmime::parameterizedField>("X-Field-That-Contains-Parameters"); + +// Use setValue() to convert from a basic type to 'text' +vmime::shared_ptr <vmime::parameter> prm = field->getParameter("my-date-param"); +prm->setValue(vmime::datetime::now()); + +// Use getValueAs() to convert from 'text' to a basic type +prm = field->getParameter("my-charset-param"); +const vmime::charset ch = prm->getValueAs <vmime::charset>(); +\end{lstlisting} + +Some fields provide easy access to their standard parameters (see +Table \ref{standard-prm-fields}). This avoids finding the parameter and +\emph{dynamic-casting} its value to the right type. The following code +illustrates how to use it: + +\begin{lstlisting} +vmime::shared_ptr <vmime::contentTypeField> field = + header->getField <vmime::contentTypeField>(vmime::fields::CONTENT_TYPE); + +// 1. First solution: the "hard" way +vmime::shared_ptr <vmime::parameter> prm = field->findParameter("charset"); +const charset ch1 = prm->getValueAs <vmime::charset>(); + +// 2. Second solution: the simple way +const charset ch2 = field->getCharset(); +\end{lstlisting} + +\vnote{In both cases, an exception {\vcode no\_such\_parameter} can be +thrown if the parameter does not exist, so be sure to catch it.} + +\begin{table}[ht!] +\begin{center} +\noindent\begin{tabularx}{0.85\textwidth}{|l|l|X|} +\hline + {\bf Field Name} & + {\bf Field Type} & + {\bf Parameters} \\ +\hline +\hline +Content-Type & contentTypeField & boundary, charset, report-type \\ +\hline +Content-Disposition & contentDispositionField & creation-date, +modification-date, read-date, filename, size \\ +\hline +\end{tabularx} +\end{center} +\label{standard-prm-fields} +\caption{Standard parameterized fields} +\end{table} + + + +% ============================================================================ +\section{Streams} + +\subsection{Streams and stream adapters} % ----------------------------------- + +Streams permit reading or writing data whatever the underlying system is: +a file on a hard disk, a socket connected to a remote service... + +There are two types of streams: input streams (from which you can read data) +and output streams (in which you can write data). Some adapters are provided +for compatibility and convenience, for example: + +\begin{itemize} +\item {\vcode inputStreamAdapter} and {\vcode outputStreamAdapter}: allow +to use standard C++ iostreams with VMime; +\item {\vcode inputStreamStringAdapter} and +{\vcode outputStreamStringAdapter}: use a {\vcode vmime::string} object to +read/write data. +\end{itemize} + +The following example shows two ways of writing the current date to the +standard output, using stream adapters: + +\begin{lstlisting}[caption={Using stream adapters}] +// Get current date and time +const vmime::datetime date = vmime::datetime::now(); + +// 1. Using outputStreamAdapter +vmime::utility::outputStreamAdapter out(std::cout); + +std::cout << "Current date is: "; +date.generate(out); +std::cout << std::endl; + +// 2. Using outputStreamStringAdapter +vmime::string dateStr; +vmime::utility::outputStreamStringAdapter outStr(dateStr); + +date.generate(outStr); + +std::cout << "Current date is: " << dateStr << std::endl; +\end{lstlisting} + + +\subsection{Stream filters} % ------------------------------------------------ + +Input and output streams can be filtered to perform inline conversions (for +example, there is a filter to convert ``{\textbackslash}r{\textbackslash}n'' +sequences to ``{\textbackslash}n''). They inherit from +{\vcode vmime::utility::filteredInputStream} or +{\vcode vmime::utility::filteredOutputStream} and are used like adapters (some +filters also accept parameters; read the documentation). + +The most useful filter in VMime (and probably the only one you will need) is +the {\vcode charsetFilteredOutputStream}, which performs inline conversion +of charsets. See \ref{section_charsets} to know how to use it. + +\vnote{After you have finished to use a filtered output stream, it is +important to call {\vcode flush()} on it to flush the internal buffer. +If {\vcode flush()} is not called, not all data may be written to the +underlying stream.} + + +% ============================================================================ +\section{Content handlers} + +\subsection{Introduction} % -------------------------------------------------- + +Content handlers are an abstraction for data sources. They are currently used +when some data need to be stored for later use (eg. body part contents, +attachment data, ...). Data can be stored encoded or unencoded (for more +information about encodings, see \ref{section_encodings}). + +\subsection{Extracting data from content handlers} % ------------------------- + +You can extract data in a content handler using the {\vcode extract()} method +(which automatically decodes data if encoded) or {\vcode extractRaw()} (which +extracts data without perfoming any decoding). + +The following example shows how to extract the body text from a message, and +writing it to the standard output with charset conversion: + +\begin{lstlisting}[caption={Using content handlers to extract body text from +a message}] +// Suppose we already have a message +vmime::shared_ptr <vmime::message> msg; + +// Obtains a reference to the body contents +vmime::shared_ptr <vmime::body> body = msg->getBody(); +vmime::shared_ptr <vmime::contentHandler> cts = body->getContents(); + +vmime::utility::outputStreamAdapter out(std::cout); +cts->extract(out); +\end{lstlisting} + +\vnote{The body contents is extracted ``as is''. No charset conversion is +performed. See \ref{section_charsets} to know more about conversion between +charsets.} + + +\subsection{Creating content handlers} % ------------------------------------- + +When you are building a message, you may need to instanciate content handlers +if you want to set the contents of a body part. The following code snippet +shows how to set the body text of a part from a string: + +\begin{lstlisting}[caption={Setting the contents of a body part}] +vmime::shared_ptr <vmime::bodyPart> part; // suppose we have a body part + +// Create a new content handler from a string +vmime::shared_ptr <vmime::contentHandler> cth = + vmime::make_shared <vmime::stringContentHandler>("Put body contents here"); + +// Set the contents +part->getBody()->setContents(cth); +\end{lstlisting} + +Content handlers are also used when creating attachments. The following +example illustrates how to create an attachment from a file: + +\begin{lstlisting}[caption={Creating an attachment from a file}] +// Create a stream from a file +std::ifstream* fileStream = new std::ifstream(); + +fileStream->open("/home/vincent/paris.jpg", std::ios::binary); + +if (!*fileStream) { + // handle error +} + +vmime::shared_ptr <utility::stream> dataStream = + vmime::make_shared <vmime::utility::inputStreamPointerAdapter>(fileStream); + + // NOTE: 'fileStream' will be automatically deleted + // when 'dataStream' is deleted + +// Create a new content handler +vmime::shared_ptr <contentHandler> data = + vmime::make_shared <vmime::streamContentHandler>(dataStream, 0); + +// Now create the attachment +ref <vmime::attachment> att = vmime::make_shared <vmime::defaultAttachment>( + /* attachment data */ data, + /* content type */ vmime::mediaType("image/jpeg"), + /* description */ vmime::text("Holiday photo"), + /* filename */ vmime::word("paris.jpg") +); +\end{lstlisting} + +You will see later that the {\vcode vmime::fileAttachment} class already +encapsulates all the mechanics to create an attachment from a file. + + +% ============================================================================ +\section{Character sets, charsets and conversions\label{section_charsets}} + +Quoting from RFC-2278: \emph{`` The term 'charset' is used to refer to a +method of converting a sequence of octets into a sequence of characters.''} + +With the {\vcode vmime::charset} object, VMime supports conversion between +charsets using the {\em iconv} library, which is available on almost all +existing platforms. See {\vcode vmime::charset} and +{\vcode vmime::charsetConverter} in the class documentation to know more +about charset conversion. + +The following example shows how to convert data in one charset to another +charset. The data is extracted from the body of a message and converted +to UTF-8 charset: + +\begin{lstlisting}[caption={Extracting and converting body contents to a +specified charset}] +vmime::shared_ptr <vmime::message> msg; // we have a message + +// Obtain the content handler first +vmime::shared_ptr <vmime::body> body = msg->getBody(); +vmime::shared_ptr <const vmime::contentHandler> cth = body->getContents(); + +// Then, extract and convert the contents +vmime::utility::outputStreamAdapter out(std::cout); +vmime::utility::charsetFilteredOutputStream fout( + /* source charset */ body->getCharset(), + /* dest charset */ vmime::charset("utf-8"), + /* dest stream */ out +); + +cth->extract(fout); + +fout.flush(); // Very important! +\end{lstlisting} + + +% ============================================================================ +\section{Non-ASCII text in header fields} + +MIME standard defines methods\footnote{See RFC-2047: Message Header Extensions +for Non-ASCII Text} for dealing with data which is not 7-bit only (ie. the +ASCII character set), in particular in header fields. For example, the field +``Subject:'' use this data type. + +VMime is fully compatible with RFC-2047 and provides two objects for +manipulating 8-bit data: {\vcode vmime::text} and {\vcode vmime::word}. A word +represents textual information encoded in a specified charset. A text is +composed of one or more words. + +RFC-2047 describes the process of encoding 8-bit data into a 7-bit form; +basically, it relies on Base64 and Quoted-Printable encoding. Hopefully, all +the encoding/decoding process is done internally by VMime, so creating text +objects is fairly simple: + +\begin{lstlisting}[caption={Creating \vcode{vmime::text} objects}] +vmime::string inText = "Linux dans un téléphone mobile"; +vmime::charset inCharset = "utf-8"; + +vmime::text outText; +outText.createFromString(inText, inCharset); + +// 'outText' now contains 3 words: +// . <us-ascii> "Linux dans un " +// . <utf-8> "téléphone " +// . <us-ascii> "mobile" + +vmime::shared_ptr <vmime::header> header = myMessage->getHeader(); +header->Subject()->setValue(outText); +\end{lstlisting} + +In general, you will not need to decode RFC-2047-encoded data as the process +is totally transparent in VMime. If you really have to, you can use the +{\vcode vmime::text::decodeAndUnfold()} static method to create a text object +from encoded data. + +For example, say you have the following encoded data: + +\begin{verbatim} + Linux dans un =?UTF-8?B?dMOpbMOpcGhvbmUgbW9iaWxl?= +\end{verbatim} + +You can simply decode it using the following code: + +\begin{lstlisting}[caption={Decoding RFC-2047-encoded data}] +vmime::string inData = + "Linux dans un =?UTF-8?B?dMOpbMOpcGhvbmUgbW9iaWxl?="; + +vmime::text outText; +vmime::text::decodeAndUnfold(inData, &outText); +\end{lstlisting} + +{\vcode vmime::text} also provides a function to convert all the words to +another charset in a single call. The following example shows how to convert +text stored in the Subject field of a message: + +\begin{lstlisting}[caption={Converting data in a {\vcode vmime::text} to a +specified charset}] +vmime::shared_ptr <vmime::message> msg; // we have a message + +vmime::text subject = msg->getHeader()->Subject()->getValue(); + +const vmime::string subjectText = + subject.getConvertedText(vmime::charset("utf-8")); + +// 'subjectText' now contains the subject in UTF-8 encoding +\end{lstlisting} + + +% ============================================================================ +\section{Encodings\label{section_encodings}} + +\subsection{Introduction} % -------------------------------------------------- + +The MIME standard defines a certain number of encodings to allow data +to be safely transmitted from one peer to another. VMime provides +data encoding and decoding using the {\vcode vmime::utility::encoder::encoder} object. + +You should not need to use encoders directly, as all encoding/decoding +process is handled internally by the library, but it is good to know +they exist and how they work. + +\subsection{Using encoders} % ------------------------------------------------ + +You can create an instance of an encoder using the 'vmime::utility::encoder::encoderFactory' +object, giving the encoding name ({\it base64}, {\it quoted-printable}, ...). +The following example creates an instance of the Base64 encoder to encode +some data: + +\begin{lstlisting}[caption={A simple example of using an encoder}] +vmime::shared_ptr <vmime::utility::encoder::encoder> enc = + vmime::utility::encoder::encoderFactory::getInstance()->create("base64"); + +vmime::string inString("Some data to encode"); +vmime::utility::inputStreamStringAdapter in(inString); + +vmime::string outString; +vmime::utility::outputStreamStringAdapter out(outString); + +enc->encode(in, out); + +std::cout << "Encoded data is:" << outString << std::endl; +\end{lstlisting} + +\subsection{Enumerating available encoders} % -------------------------------- + +The behaviour of the encoders can be configured using properties. However, +not all encoders support properties. The following example\footnote{This is +an excerpt from {\vexample example6}} enumerates available encoders and the +supported properties for each of them: + +\begin{lstlisting}[caption={Enumerating encoders and their properties}] +vmime::shared_ptr <vmime::utility::encoder::encoderFactory> ef = + vmime::utility::encoder::encoderFactory::getInstance(); + +std::cout << "Available encoders:" << std::endl; + +for (int i = 0 ; i < ef->getEncoderCount() ; ++i) { + + // Output encoder name + vmime::shared_ptr <const vmime::utility::encoder::encoderFactory::registeredEncoder> + enc = ef->getEncoderAt(i); + + std::cout << " * " << enc->getName() << std::endl; + + // Create an instance of the encoder to get its properties + vmime::shared_ptr <vmime::utility::encoder::encoder> e = enc->create(); + + std::vector <vmime::string> props = e->getAvailableProperties(); + std::vector <vmime::string>::const_iterator it; + + for (it = props.begin() ; it != props.end() ; ++it) { + std::cout << " - " << *it << std::endl; + } +\end{lstlisting} + + +% ============================================================================ +\section{Progress listeners} + +Progress listeners are used with objects that can notify you about the state +of progress when they are performing an operation. + +The {\vcode vmime::utility::progressListener} interface is rather simple: + +\begin{lstlisting} +void start(const int predictedTotal); +void progress(const int current, const int currentTotal); +void stop(const int total); +\end{lstlisting} + +{\vcode start()} and {\vcode stop()} are called at the beginning and the end +of the operation, respectively. {\vcode progress()} is called each time the +status of progress changes (eg. a chunk of data has been processed). There is +no unit specified for the values passed in argument. It depends on the +notifier: it can be bytes, percent, number of messages... diff --git a/vmime-master/doc/book/book.tex b/vmime-master/doc/book/book.tex new file mode 100644 index 0000000..4db213a --- /dev/null +++ b/vmime-master/doc/book/book.tex @@ -0,0 +1,118 @@ +\documentclass[11pt]{report} + +\title{{\Huge VMime Book} \\ \ \\ A Developer's Guide To VMime} +\author{Vincent Richard \\ vincent@vmime.org} + +\usepackage{graphicx} +\usepackage{tabularx} +\usepackage{array} +\usepackage{listings} +\usepackage[usenames]{color} +\usepackage{ucs} +\usepackage[utf8x]{inputenc} +\usepackage[vcentering,dvips]{geometry} +%\usepackage{type1cm} % scalable Computer Modern fonts +\usepackage{courier} % use Adobe Courier instead of Computer Modern Typewriter +\usepackage{fancyheadings} +\usepackage{hyperref} +\usepackage{verbatim} +\usepackage{footmisc} + + +\setcounter{secnumdepth}{10} +\setcounter{tocdepth}{10} + +\def\vcode{\tt} +\def\vnull{{\tt NULL}} +\newcommand{\vnote}[1]{{\sc note:} #1} +\def\vexample{\tt\sc} +\newcommand{\verti}[1]{\rotatebox{90}{#1\ }} % vertical text +\def\vdot{$\bullet$} + +\sloppy % Disable "overfull \hbox..." warnings + +\newcommand{\Chapter}[1]{\chapter{#1} \setcounter{figure}{1}} + +% 'listings' configuration +\definecolor{listingFrame}{rgb}{0.9,0.9,0.9} +\lstset{language=C++,showstringspaces=false} +\lstset{keywordstyle=\bf,commentstyle=\it} +\lstset{captionpos=b,extendedchars=true,inputencoding=latin1} +\lstset{fontadjust=true,basewidth={0.5em,0.4em},columns=fixed,flexiblecolumns=false} +\lstset{frame=leftline,framerule=0.1cm,framesep=0.3cm,rulecolor=\color{listingFrame}} +\lstset{abovecaptionskip=0.5cm,xleftmargin=1.1cm,aboveskip=0.5cm,belowskip=0.2cm} + +% 'hyperref' configuration +\hypersetup{ + backref=true,pagebackref=true,hyperindex=rue,colorlinks=true, + breaklinks=true,urlcolor=blue,linkcolor=black,bookmarks=true,bookmarksopen=true +} + +% HTML output configuration +%HEVEA\renewcommand{\includegraphics}[2][]{\imgsrc{#2}} +%HEVEA\renewcommand{\verti}[1]{#1} +%HEVEA\def\vdot{\bullet} +%HEVEA\newcommand{\linespread}{} +%HEVEA\newcommand{\clubpenalty}{} +%HEVEA\newcommand{\widowpenalty}{} +%HEVEA\newcommand{\geometry}{} + + +% Page layout +\geometry{papersize={210mm,297mm},total={160mm,230mm}} + +% Text layout +\setlength{\skip\footins}{1cm} % margin between text and footnotes +\clubpenalty=1000 +\addtolength{\parskip}{+0.3cm} +\linespread{1.05} +\widowpenalty=1000 + + +\begin{document} + +% Title page +\maketitle +\newpage + +% Table of contents +\tableofcontents +\newpage + +% Chapters +\include{intro} +\include{building} +\include{start} +\include{basics} +\include{msg} +\include{net} + +\thispagestyle{empty} +\ \newpage + + +%HEVEA\begin{comment} + +% List of listings +\lstlistoflistings +\addcontentsline{toc}{chapter}{Listings} + +% List of figures +\listoffigures +\addcontentsline{toc}{chapter}{List of figures} + +% List of table +\listoftables +\addcontentsline{toc}{chapter}{List of tables} + +%HEVEA\end{comment} + + +% Appendixes +\appendix + +\chapter{The GNU General Public License\label{appendix_license}} +\verbatiminput{../../COPYING} + +\end{document} + diff --git a/vmime-master/doc/book/building.tex b/vmime-master/doc/book/building.tex new file mode 100644 index 0000000..9feeedc --- /dev/null +++ b/vmime-master/doc/book/building.tex @@ -0,0 +1,175 @@ +\label{chapter_building} +\chapter{Building and Installing VMime} + +% ============================================================================ +\section{Introduction} + +If no pre-build packages of VMime is available for your system, or if for some +reason you want to compile it yourself from scratch, this section will guide +you through the process. + +% ============================================================================ +\section{What you need} + +To build VMime from the sources, you will need the following: + +\begin{itemize} +\item a working C++ compiler with good STL implementation and also a good +support for templates (for example, \href{http://gcc.gnu.org/}{GNU GCC}) ; +\item \href{http://www.cmake.org/}{CMake} build system ; +\item either \href{http://www.icu-project.org}{ICU library} or an usable +{\vcode iconv()} implementation (see +\href{http://www.gnu.org/software/libiconv/}{libiconv of GNU Project}) ; +\item the \href{http://www.gnu.org/software/gsasl/}{GNU SASL Library} if you +want SASL\footnote{Simple Authentication and Security Layer} support ; +\item either the \href{http://www.openssl.org}{OpenSSL library} or the +\href{http://www.gnu.org/software/gnutls/}{GNU TLS Library} if you +want SSL and TLS\footnote{Transport Layer Security} support ; +\end{itemize} + +% ============================================================================ +\section{Obtaining source files} + +You can download a package containing the source files of the latest release +of the VMime library from the \href{http://www.vmime.org/}{VMime web site}. + +You can also obtain the current development version from the Git repository, +which is currently hosted at GitHub. It can be checked out through anonymous +access with the following instruction: + +\begin{verbatim} + git clone git://github.com/kisli/vmime +\end{verbatim} + +% ============================================================================ +\section{Compiling and installing} + +VMime relies on CMake for building. CMake is an open source, cross-platform +build system. It will generate all build scripts required to compile VMime on +your platform. + +First, extract the tarball or checkout the VMime source code into a directory +somewhere on your system, let's call it {\vcode /path/to/vmime-source}. Then, +create a build directory, which will contain all intermediate build files and +the final libraries, let's call it {\vcode /path/to/vmime-build}. + +From the build directory, run {\vcode cmake} with the {\vcode -G} argument +corresponding to your platform/choice. For example, if you are on a +Unix-compatible platform (like GNU/Linux or MacOS) and want to use the +{\vcode make} utility for building, type: + +\begin{verbatim} + $ cd /path/to/vmime-build + $ cmake -G "Unix Makefiles" /path/to/vmime-source +\end{verbatim} + +CMake will perform some tests on your system to check for libs installed +and some platform-specific includes, and create all files needed for +compiling the project. Additionally, a {\vcode src/vmime/config.hpp} file +with the parameters detected for your system will be created. + +Next, you can start the compilation process: + +\begin{verbatim} + $ cmake --build . +\end{verbatim} + +Please wait a few minutes while the compilation runs (you should have some +time to have a coffee right now!). If you get errors during the compilation, +be sure your system meet the requirements given at the beginning of the +chapter. You can also try to get a newer version (from the Git repository, for +example) or to get some help on VMime user forums. + +If everything compiled successfully, you can install the library and +the development files on your system: + +\begin{verbatim} + # make install +\end{verbatim} + +\vnote{you must do that with superuser rights (root) if you chose to install +the library into the default location (ie: /usr/lib and /usr/include).} + +Now, you are done! You can jump to the next chapter to know how to use VMime +in your program... + + +% ============================================================================ +\section{\label{custom-build}Customizing build} + +You should not modify the {\vcode config.hpp} file directly. Instead, you +should run {\vcode cmake} again, and specify your build options on the command +line. For example, to force using OpenSSL library instead of GnuTLS for TLS +support, type: + +\begin{verbatim} + $ cmake -G "Unix Makefiles" -DVMIME_TLS_SUPPORT_LIB=openssl +\end{verbatim} + +If you want to enable or disable some features in VMime, you can obtain some +help by typing {\vcode cmake -L}. The defaults should be OK though. For a +complate list of build options, you can also refer to section +\ref{build-options}, page \pageref{build-options}. For more information about +using CMake, go to \href{http://www.cmake.org/}{the CMake web site}. + +\vnote{Delete the {\vcode CMakeCache.txt} file if you changed configuration +or if something changed on your system, as CMake may cache some values to +speed things up.} + +You can also use another build backend, like +Ninja\footnote{\url{https://ninja-build.org/}}, if you have it on your system: + +\begin{verbatim} + $ cd /path/to/vmime-build + $ cmake -G Ninja /path/to/vmime-source + $ ninja + # ninja install +\end{verbatim} + +To install VMime in a directory different from the default directory +({\vcode /usr} on GNU/Linux systems), set the +{\vcode CMAKE\_INSTALL\_PREFIX} option: + +\begin{verbatim} + $ cmake -DCMAKE_INSTALL_PREFIX=/opt/ ... +\end{verbatim} + + +% ============================================================================ +\section{\label{build-options}Build options} + +Some options can be given to CMake to control the build: + +\begin{table}[!ht] +\noindent\begin{tabularx}{1.0\textwidth}{|l|X|} +\hline + {\bf Option name} & + {\bf Description} \\ +\hline +\hline +VMIME\_BUILD\_SHARED\_LIBRARY & +Set to ON to build a shared version (.so) of the library (default is ON). \\ +\hline +VMIME\_BUILD\_STATIC\_LIBRARY & +Set to ON to build a static version (.a) of the library (default is ON). \\ +\hline +VMIME\_BUILD\_TESTS & +Set to ON to build unit tests (default is OFF). \\ +\hline +VMIME\_TLS\_SUPPORT\_LIB & +Set to either "openssl" or "gnutls" to force using either OpenSSL or GNU TLS +for SSL/TLS support (default depends on which libraries are available on +your system). \\ +\hline +VMIME\_CHARSETCONV\_LIB & +Set to either "iconv", "icu" or "win" (Windows only) to force using iconv, ICU +or Windows built-in API for converting between charsets (default value depends +on which libraries are available on your system). \\ +\hline +CMAKE\_BUILD\_TYPE & +Set the build type: either "Release" or "Debug". In Debug build, optimizations +are disabled and debugging information are enabled. \\ +\hline +\end{tabularx} +\caption{CMake build options} +\end{table} diff --git a/vmime-master/doc/book/images/address-mailbox-mailboxgroup.svg b/vmime-master/doc/book/images/address-mailbox-mailboxgroup.svg new file mode 100644 index 0000000..a7752d4 --- /dev/null +++ b/vmime-master/doc/book/images/address-mailbox-mailboxgroup.svg @@ -0,0 +1,355 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="453.27998pt" + height="307.89001pt" + id="svg2" + sodipodi:version="0.32" + inkscape:version="0.42.2" + sodipodi:docbase="/home/vincent/projects/vmime/doc/book/images" + sodipodi:docname="address-mailbox-mailboxgroup.svg" + inkscape:export-xdpi="73.779999" + inkscape:export-ydpi="73.779999"> + <defs + id="defs3"> + <marker + inkscape:stockid="Torso" + orient="auto" + refY="0.0" + refX="0.0" + id="Torso" + style="overflow:visible"> + <g + id="g2045" + transform="scale(0.7)"> + <path + sodipodi:nodetypes="ccccc" + id="path1128" + d="M -4.7792281,-3.2395420 C -2.4288541,-2.8736027 0.52103922,-1.3019943 0.25792722,0.38794346 C -0.0051877922,2.0778819 -2.2126741,2.6176539 -4.5630471,2.2517169 C -6.9134221,1.8857769 -8.5210350,0.75201414 -8.2579220,-0.93792336 C -7.9948090,-2.6278615 -7.1296041,-3.6054813 -4.7792281,-3.2395420 z " + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;marker-start:none;marker-mid:none;marker-end:none" /> + <path + sodipodi:nodetypes="cc" + id="path1909" + d="M 4.4598789,0.088665736 C -2.5564571,-4.3783320 5.2248769,-3.9061806 -0.84829578,-8.7197331" + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;marker-end:none" /> + <path + sodipodi:nodetypes="cc" + id="path1910" + d="M 4.9298719,0.057520736 C -1.3872731,1.7494689 1.8027579,5.4782079 -4.9448731,7.5462725" + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;marker-start:none;marker-end:none" /> + <rect + transform="matrix(0.527536,-0.849533,0.887668,0.460484,0.000000,0.000000)" + y="-1.7408575" + x="-10.391706" + height="2.7608147" + width="2.6366582" + id="rect2035" + style="fill-rule:evenodd;stroke-width:1.0000000pt;marker-end:none" /> + <rect + transform="matrix(0.671205,-0.741272,0.790802,0.612072,0.000000,0.000000)" + y="-7.9629307" + x="4.9587269" + height="2.8614161" + width="2.7327356" + id="rect2036" + style="fill-rule:evenodd;stroke-width:1.0000000pt;marker-end:none" /> + <path + transform="matrix(6.793608e-17,-1.109517,1.109517,6.793608e-17,25.96648,19.71619)" + d="M 16.779951 -28.685045 A 0.60731727 0.60731727 0 1 0 15.565317,-28.685045 A 0.60731727 0.60731727 0 1 0 16.779951 -28.685045 z" + sodipodi:ry="0.60731727" + sodipodi:rx="0.60731727" + sodipodi:cy="-28.685045" + sodipodi:cx="16.172634" + id="path2037" + style="fill:#ff0000;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;marker-start:none;marker-end:none" + sodipodi:type="arc" /> + <path + transform="matrix(6.793608e-17,-1.109517,1.109517,6.793608e-17,26.82450,16.99126)" + d="M 16.779951 -28.685045 A 0.60731727 0.60731727 0 1 0 15.565317,-28.685045 A 0.60731727 0.60731727 0 1 0 16.779951 -28.685045 z" + sodipodi:ry="0.60731727" + sodipodi:rx="0.60731727" + sodipodi:cy="-28.685045" + sodipodi:cx="16.172634" + id="path2038" + style="fill:#ff0000;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;marker-start:none;marker-end:none" + sodipodi:type="arc" /> + </g> + </marker> + <marker + inkscape:stockid="TriangleOutL" + orient="auto" + refY="0.0" + refX="0.0" + id="TriangleOutL" + style="overflow:visible"> + <path + sodipodi:nodetypes="cccc" + id="path5324" + d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z " + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none" + transform="scale(0.8)" /> + </marker> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="1.0000000" + inkscape:pageshadow="2" + inkscape:zoom="1.0000000" + inkscape:cx="248.49444" + inkscape:cy="298.91345" + inkscape:document-units="px" + inkscape:current-layer="layer1" + inkscape:window-width="1150" + inkscape:window-height="986" + inkscape:window-x="0" + inkscape:window-y="30" + fill="#ff0000" + inkscape:showpageshadow="true" + showguides="true" + showgrid="false" + inkscape:grid-bbox="false" + inkscape:grid-points="false" /> + <metadata + id="metadata4"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <cc:license + rdf:resource="http://creativecommons.org/licenses/GPL/2.0/" /> + </cc:Work> + <cc:License + rdf:about="http://creativecommons.org/licenses/GPL/2.0/"> + <cc:permits + rdf:resource="http://web.resource.org/cc/Reproduction" /> + <cc:permits + rdf:resource="http://web.resource.org/cc/Distribution" /> + <cc:requires + rdf:resource="http://web.resource.org/cc/Notice" /> + <cc:permits + rdf:resource="http://web.resource.org/cc/DerivativeWorks" /> + <cc:requires + rdf:resource="http://web.resource.org/cc/ShareAlike" /> + <cc:requires + rdf:resource="http://web.resource.org/cc/SourceCode" /> + </cc:License> + </rdf:RDF> + </metadata> + <path + id="path5442" + d="M 303.65293,104.37647 L 303.65293,173.68448" + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" /> + <path + id="path5440" + d="M 462.39333,172.39335 L 462.39333,240.10630" + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" /> + <path + id="path5438" + d="M 139.24323,172.39335 L 139.24323,240.10630" + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" /> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1"> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-opacity:1.0000000" + d="M 257.32713,293.92642 L 392.05898,293.92642" + id="path2543" /> + <rect + style="fill:#e0f5cc;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500000;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000" + id="rect1291" + width="132.69368" + height="105.95705" + x="237.85556" + y="13.003311" /> + <text + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="245.51651" + y="55.887268" + id="text1293" + sodipodi:linespacing="125.00000%"><tspan + sodipodi:role="line" + id="tspan2242" + x="245.51651" + y="55.887268">isEmpty() : bool</tspan><tspan + sodipodi:role="line" + id="tspan2244" + x="245.51651" + y="70.887268">isGroup() : bool</tspan></text> + <text + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="279.65814" + y="29.038483" + id="text2347" + sodipodi:linespacing="125.00000%"><tspan + sodipodi:role="line" + id="tspan2222" + x="279.65814" + y="29.038483">address</tspan></text> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-opacity:1.0000000" + d="M 238.27499,37.373470 L 370.37704,37.373470" + id="path2351" /> + <rect + style="fill:#f5f5c8;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.0000000;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000" + id="rect2433" + width="242.87289" + height="157.12062" + x="17.947495" + y="215.62213" /> + <text + xml:space="preserve" + style="font-size:12.000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="24.265694" + y="258.30316" + id="text2435" + sodipodi:linespacing="125%"><tspan + sodipodi:role="line" + id="tspan2315" + x="24.265694" + y="258.30316">getName() : string</tspan><tspan + sodipodi:role="line" + id="tspan2317" + x="24.265694" + y="273.30316">setName(n : string) : void</tspan><tspan + sodipodi:role="line" + id="tspan2319" + x="24.265694" + y="288.30316">appendMailbox(m : ref <mailbox>)</tspan><tspan + sodipodi:role="line" + id="tspan2321" + x="24.265694" + y="303.30316">getMailboxCount() : int</tspan><tspan + sodipodi:role="line" + id="tspan2323" + x="24.265694" + y="318.30316">getMailboxAt(i : int) : ref <mailbox></tspan><tspan + sodipodi:role="line" + id="tspan2325" + x="24.265694" + y="333.30316">...</tspan></text> + <text + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="91.950951" + y="231.45441" + id="text2439" + sodipodi:linespacing="125.00000%"><tspan + sodipodi:role="line" + id="tspan2246" + x="91.950951" + y="231.45441">mailboxGroup</tspan></text> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-opacity:1.0000000" + d="M 19.330207,239.78939 L 260.20091,239.78939" + id="path2443" /> + <rect + style="fill:#f5f5c8;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500000;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000" + id="rect2447" + width="174.79645" + height="124.30678" + x="373.27942" + y="215.33472" /> + <text + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="380.74768" + y="258.15143" + id="text2449" + sodipodi:linespacing="125.00000%"><tspan + sodipodi:role="line" + id="tspan2286" + x="380.74768" + y="258.15143">getName() : text</tspan><tspan + sodipodi:role="line" + id="tspan2288" + x="380.74768" + y="273.15143">setName(n : text) : void</tspan><tspan + sodipodi:role="line" + id="tspan2290" + x="380.74768" + y="288.15143">getEmail() : string</tspan><tspan + sodipodi:role="line" + id="tspan2292" + x="380.74768" + y="303.15143">setEmail(e : string) : void</tspan></text> + <text + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="434.7478" + y="231.30267" + id="text2453" + sodipodi:linespacing="125.00000%"><tspan + sodipodi:role="line" + id="tspan2276" + x="434.74780" + y="231.30267">mailbox</tspan></text> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" + d="M 373.64397,239.63760 L 547.69600,239.63760" + id="path2457" /> + <rect + style="fill:#ffffff;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500457;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000" + id="rect2541" + width="15.541327" + height="15.541327" + x="-23.443876" + y="392.33624" + transform="matrix(0.707107,-0.707107,0.707107,0.707107,0.000000,0.000000)" /> + <text + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="344.41357" + y="289.23822" + id="text2545" + sodipodi:linespacing="100.00000%"><tspan + id="tspan5160" + sodipodi:role="line" + y="289.23822" + x="344.41357">0..n</tspan></text> + <text + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="293.07501" + y="312.23822" + id="text2549" + sodipodi:linespacing="125.00000%"><tspan + sodipodi:role="line" + id="tspan2294" + x="293.07501" + y="312.23822">mailboxes</tspan></text> + <text + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="289.07501" + y="289.23822" + id="text2553" + sodipodi:linespacing="100.00000%"><tspan + id="tspan5158" + sodipodi:role="line" + y="289.23822" + x="289.07501">0</tspan></text> + <path + id="path2575" + d="M 290.22642,134.62157 L 318.11534,134.62157 L 303.70606,120.21230 L 290.22642,134.62157 z " + style="fill:#ffffff;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" /> + </g> + <path + id="path5436" + d="M 139.78693,173.17443 L 461.72537,173.17443" + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000;stroke-dasharray:none" /> +</svg> diff --git a/vmime-master/doc/book/images/message-body-header.svg b/vmime-master/doc/book/images/message-body-header.svg new file mode 100644 index 0000000..29923fa --- /dev/null +++ b/vmime-master/doc/book/images/message-body-header.svg @@ -0,0 +1,716 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="707.28000pt" + height="612.89000pt" + id="svg2" + sodipodi:version="0.32" + inkscape:version="0.42.2" + sodipodi:docbase="/home/vincent/projects/vmime/doc/book/images" + sodipodi:docname="message-body-header.svg" + inkscape:export-xdpi="73.779999" + inkscape:export-ydpi="73.779999"> + <defs + id="defs3"> + <marker + inkscape:stockid="Torso" + orient="auto" + refY="0.0" + refX="0.0" + id="Torso" + style="overflow:visible"> + <g + id="g2045" + transform="scale(0.7)"> + <path + sodipodi:nodetypes="ccccc" + id="path1128" + d="M -4.7792281,-3.2395420 C -2.4288541,-2.8736027 0.52103922,-1.3019943 0.25792722,0.38794346 C -0.0051877922,2.0778819 -2.2126741,2.6176539 -4.5630471,2.2517169 C -6.9134221,1.8857769 -8.5210350,0.75201414 -8.2579220,-0.93792336 C -7.9948090,-2.6278615 -7.1296041,-3.6054813 -4.7792281,-3.2395420 z " + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;marker-start:none;marker-mid:none;marker-end:none" /> + <path + sodipodi:nodetypes="cc" + id="path1909" + d="M 4.4598789,0.088665736 C -2.5564571,-4.3783320 5.2248769,-3.9061806 -0.84829578,-8.7197331" + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;marker-end:none" /> + <path + sodipodi:nodetypes="cc" + id="path1910" + d="M 4.9298719,0.057520736 C -1.3872731,1.7494689 1.8027579,5.4782079 -4.9448731,7.5462725" + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;marker-start:none;marker-end:none" /> + <rect + transform="matrix(0.527536,-0.849533,0.887668,0.460484,0.000000,0.000000)" + y="-1.7408575" + x="-10.391706" + height="2.7608147" + width="2.6366582" + id="rect2035" + style="fill-rule:evenodd;stroke-width:1.0000000pt;marker-end:none" /> + <rect + transform="matrix(0.671205,-0.741272,0.790802,0.612072,0.000000,0.000000)" + y="-7.9629307" + x="4.9587269" + height="2.8614161" + width="2.7327356" + id="rect2036" + style="fill-rule:evenodd;stroke-width:1.0000000pt;marker-end:none" /> + <path + transform="matrix(6.793608e-17,-1.109517,1.109517,6.793608e-17,25.96648,19.71619)" + d="M 16.779951 -28.685045 A 0.60731727 0.60731727 0 1 0 15.565317,-28.685045 A 0.60731727 0.60731727 0 1 0 16.779951 -28.685045 z" + sodipodi:ry="0.60731727" + sodipodi:rx="0.60731727" + sodipodi:cy="-28.685045" + sodipodi:cx="16.172634" + id="path2037" + style="fill:#ff0000;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;marker-start:none;marker-end:none" + sodipodi:type="arc" /> + <path + transform="matrix(6.793608e-17,-1.109517,1.109517,6.793608e-17,26.82450,16.99126)" + d="M 16.779951 -28.685045 A 0.60731727 0.60731727 0 1 0 15.565317,-28.685045 A 0.60731727 0.60731727 0 1 0 16.779951 -28.685045 z" + sodipodi:ry="0.60731727" + sodipodi:rx="0.60731727" + sodipodi:cy="-28.685045" + sodipodi:cx="16.172634" + id="path2038" + style="fill:#ff0000;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;marker-start:none;marker-end:none" + sodipodi:type="arc" /> + </g> + </marker> + <marker + inkscape:stockid="TriangleOutL" + orient="auto" + refY="0.0" + refX="0.0" + id="TriangleOutL" + style="overflow:visible"> + <path + sodipodi:nodetypes="cccc" + id="path5324" + d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z " + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none" + transform="scale(0.8)" /> + </marker> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="1.00000000" + inkscape:cx="394.46478" + inkscape:cy="380.70648" + inkscape:document-units="px" + inkscape:current-layer="svg2" + inkscape:window-width="1150" + inkscape:window-height="986" + inkscape:window-x="0" + inkscape:window-y="30" /> + <metadata + id="metadata4"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <cc:license + rdf:resource="http://creativecommons.org/licenses/GPL/2.0/" /> + </cc:Work> + <cc:License + rdf:about="http://creativecommons.org/licenses/GPL/2.0/"> + <cc:permits + rdf:resource="http://web.resource.org/cc/Reproduction" /> + <cc:permits + rdf:resource="http://web.resource.org/cc/Distribution" /> + <cc:requires + rdf:resource="http://web.resource.org/cc/Notice" /> + <cc:permits + rdf:resource="http://web.resource.org/cc/DerivativeWorks" /> + <cc:requires + rdf:resource="http://web.resource.org/cc/ShareAlike" /> + <cc:requires + rdf:resource="http://web.resource.org/cc/SourceCode" /> + </cc:License> + </rdf:RDF> + </metadata> + <path + id="path2407" + d="M 253.02743,136.68448 L 253.02743,67.376470" + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" /> + <path + id="path5442" + d="M 635.99153,281.37647 L 635.99153,350.68448" + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" /> + <path + id="path5440" + d="M 783.39333,349.39335 L 783.39333,417.10630" + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" /> + <path + id="path5438" + d="M 446.06998,349.39335 L 446.06998,417.10630" + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" /> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1"> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" + d="M 16.987518,219.56412 L 153.50367,219.56412" + id="path2375" /> + <path + id="path2345" + d="M 508.29892,263.82217 L 105.85472,471.31117" + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" /> + <path + id="path2347" + d="M 502.39025,252.30315 L 515.17042,277.09145 L 521.37461,257.68108 L 502.39025,252.30315 z " + style="fill:#ffffff;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" /> + <g + transform="matrix(1.828236e-17,1.000000,-1.000000,1.828236e-17,533.0981,623.6004)" + id="g2321"> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" + d="M -100.36367,371.67294 L 26.017722,371.67294" + id="path2323" /> + <g + id="g2325" + transform="translate(-113.9177,-82.19766)"> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000" + d="M 140.20049,454.12696 L 129.75724,443.68372" + id="path2327" /> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" + d="M 139.84823,453.80527 L 129.66343,463.99007" + id="path2329" /> + </g> + </g> + <path + id="path2241" + d="M 507.60723,180.01568 L 350.16119,180.01568" + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" /> + <rect + style="fill:#dcf5e6;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500000;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000" + id="rect1291" + width="236.14607" + height="157.54773" + x="522.13733" + y="126.86942" /> + <text + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:120.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="529.52441" + y="169.54865" + id="text1293" + sodipodi:linespacing="120.00000%"><tspan + id="tspan5228" + sodipodi:role="line" + y="169.54865" + x="529.52441">parse(buf : string) : void</tspan><tspan + id="tspan5230" + sodipodi:role="line" + y="183.94865" + x="529.52441">generate(out : outputStream) : void</tspan><tspan + id="tspan5232" + sodipodi:role="line" + y="198.34865" + x="529.52441" /><tspan + id="tspan5234" + sodipodi:role="line" + y="212.74865" + x="529.52441">clone() : ref <component></tspan><tspan + id="tspan5236" + sodipodi:role="line" + y="227.14865" + x="529.52441">copyFrom(src : component) : void</tspan><tspan + id="tspan5238" + sodipodi:role="line" + y="241.54865" + x="529.52441">getChildComponents() : vector</tspan><tspan + id="tspan5240" + sodipodi:role="line" + y="255.94865" + x="529.52441">getParsedOffset() : int</tspan><tspan + id="tspan5242" + sodipodi:role="line" + y="270.34865" + x="529.52441">getParsedLength() : int</tspan></text> + <text + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="609.02057" + y="142.69992" + id="text2347" + sodipodi:linespacing="100.00000%"><tspan + id="tspan5172" + sodipodi:role="line" + y="142.69992" + x="609.02057">component</tspan></text> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" + d="M 522.50261,151.03487 L 758.16522,151.03487" + id="path2351" /> + <rect + style="fill:#f5f5c8;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500000;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000" + id="rect2353" + width="218.71376" + height="151.16983" + x="145.51056" + y="133.04831" /> + <text + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:120.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="154.6483" + y="175.75391" + id="text2355" + sodipodi:linespacing="120.00000%"><tspan + id="tspan2349" + sodipodi:role="line" + y="175.75391" + x="154.64830">getBody() : ref <body></tspan><tspan + id="tspan2351" + sodipodi:role="line" + y="190.15391" + x="154.64830">getHeader() : ref <header></tspan><tspan + id="tspan2353" + sodipodi:role="line" + y="204.55391" + x="154.64830">getParentPart() : ref <bodyPart></tspan></text> + <text + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="222.66418" + y="148.90518" + id="text2375" + sodipodi:linespacing="100.00000%"><tspan + id="tspan5272" + sodipodi:role="line" + y="148.90518" + x="222.66418">bodyPart</tspan></text> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" + d="M 145.87565,157.24013 L 363.84409,157.24013" + id="path2379" /> + <g + transform="matrix(1.828236e-17,1.000000,-1.000000,1.828236e-17,548.9327,384.9312)" + id="g2247"> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" + d="M -100.36367,371.67294 L 26.017722,371.67294" + id="path2387" /> + <g + id="g2395" + transform="translate(-113.9177,-82.19766)"> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000" + d="M 140.20049,454.12696 L 129.75724,443.68372" + id="path2389" /> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" + d="M 139.84823,453.80527 L 129.66343,463.99007" + id="path2393" /> + </g> + </g> + <text + sodipodi:linespacing="100.00000%" + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="138.11696" + y="382.06345" + id="text2403"><tspan + id="tspan2273" + sodipodi:role="line" + y="382.06345" + x="138.11696">body</tspan></text> + <rect + style="fill:#f5f5c8;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500000;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000" + id="rect2433" + width="276.37778" + height="157.12062" + x="304.96820" + y="412.46472" /> + <text + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:120.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="313.24988" + y="455.14575" + id="text2435" + sodipodi:linespacing="120.00000%"><tspan + id="tspan5256" + sodipodi:role="line" + y="455.14575" + x="313.24988">hasField(name : string) : bool</tspan><tspan + id="tspan5258" + sodipodi:role="line" + y="469.54575" + x="313.24988">findField(name : string) : ref <headerField></tspan><tspan + id="tspan5260" + sodipodi:role="line" + y="483.94575" + x="313.24988">findAllFields(name : string) : vector</tspan><tspan + id="tspan5262" + sodipodi:role="line" + y="498.34575" + x="313.24988">getField(name : string) : ref <headerField></tspan><tspan + id="tspan5264" + sodipodi:role="line" + y="512.74575" + x="313.24988">appendField(f : ref <headerField>) : void</tspan><tspan + id="tspan5266" + sodipodi:role="line" + y="527.14575" + x="313.24988">...</tspan><tspan + id="tspan5268" + sodipodi:role="line" + y="541.54576" + x="313.24988">getFieldAt(pos : int) : ref <headerField></tspan><tspan + id="tspan5270" + sodipodi:role="line" + y="555.94576" + x="313.24988">getFieldCount() : int</tspan></text> + <text + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="412.95099" + y="428.297" + id="text2439" + sodipodi:linespacing="100.00000%"><tspan + id="tspan5154" + sodipodi:role="line" + y="428.29700" + x="412.95099">header</tspan></text> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" + d="M 306.34976,436.63194 L 580.95005,436.63194" + id="path2443" /> + <rect + style="fill:#f5f5c8;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500000;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000" + id="rect2447" + width="174.79645" + height="124.30678" + x="694.27942" + y="412.17731" /> + <text + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:120.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="701.74768" + y="454.99402" + id="text2449" + sodipodi:linespacing="120.00000%"><tspan + id="tspan5176" + sodipodi:role="line" + y="454.99402" + x="701.74768">getName() : string</tspan><tspan + id="tspan5178" + sodipodi:role="line" + y="469.39402" + x="701.74768">getValue() : component</tspan><tspan + id="tspan5180" + sodipodi:role="line" + y="483.79402" + x="701.74768">setValue(val : component)</tspan></text> + <text + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="738.73987" + y="428.14526" + id="text2453" + sodipodi:linespacing="100.00000%"><tspan + id="tspan5152" + sodipodi:role="line" + y="428.14526" + x="738.73987">headerField</tspan></text> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" + d="M 694.64397,436.48015 L 868.69600,436.48015" + id="path2457" /> + <rect + style="fill:#ffffff;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500381;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000" + id="rect2541" + width="15.541226" + height="15.541226" + x="65.401291" + y="759.55469" + transform="matrix(0.707107,-0.707107,0.707107,0.707107,0.000000,0.000000)" /> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" + d="M 605.07226,490.76897 L 694.31385,490.76897" + id="path2543" /> + <text + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="661.23236" + y="486.08081" + id="text2545" + sodipodi:linespacing="100.00000%"><tspan + id="tspan5160" + sodipodi:role="line" + y="486.08081" + x="661.23236">0..n</tspan></text> + <text + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="626.90173" + y="509.08081" + id="text2549" + sodipodi:linespacing="100.00000%"><tspan + id="tspan5156" + sodipodi:role="line" + y="509.08081" + x="626.90173">fields</tspan></text> + <text + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="611.56311" + y="486.08081" + id="text2553" + sodipodi:linespacing="100.00000%"><tspan + id="tspan5158" + sodipodi:role="line" + y="486.08081" + x="611.56311">0</tspan></text> + <path + id="path2575" + d="M 622.56502,300.28297 L 650.45394,300.28297 L 636.04466,285.87370 L 622.56502,300.28297 z " + style="fill:#ffffff;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" /> + <rect + style="fill:#f5f5c8;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500000;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000" + id="rect2225" + width="171.85686" + height="151.16983" + x="74.698677" + y="412.04831" /> + <text + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:120.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="82.183701" + y="454.75391" + id="text2227" + sodipodi:linespacing="120.00000%"><tspan + id="tspan2377" + sodipodi:role="line" + y="454.75391" + x="82.183701">getContents() : ref <ch></tspan><tspan + id="tspan2379" + sodipodi:role="line" + y="469.15391" + x="82.183701">getCharset() : charset</tspan><tspan + id="tspan2381" + sodipodi:role="line" + y="483.55391" + x="82.183701">getEncoding() : encoding</tspan></text> + <text + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="141.69556" + y="427.90518" + id="text2231" + sodipodi:linespacing="100.00000%"><tspan + id="tspan2237" + sodipodi:role="line" + y="427.90518" + x="141.69556">body</tspan></text> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" + d="M 75.063282,436.24013 L 246.17599,436.24013" + id="path2235" /> + <path + id="path2239" + d="M 506.13949,167.78737 L 506.13949,195.67630 L 520.54876,181.26702 L 506.13949,167.78737 z " + style="fill:#ffffff;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" /> + <g + transform="matrix(1.828236e-17,1.000000,-1.000000,1.828236e-17,548.9327,384.9312)" + id="g2253"> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" + d="M -100.36367,371.67294 L 26.017722,371.67294" + id="path2255" /> + <g + id="g2257" + transform="translate(-113.9177,-82.19766)"> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000" + d="M 140.20049,454.12696 L 129.75724,443.68372" + id="path2259" /> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" + d="M 139.84823,453.80527 L 129.66343,463.99007" + id="path2261" /> + </g> + </g> + <g + transform="matrix(1.828236e-17,1.000000,-1.000000,1.828236e-17,704.8357,384.9312)" + id="g2263"> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" + d="M -100.36367,371.67294 L 26.017722,371.67294" + id="path2265" /> + <g + id="g2267" + transform="translate(-113.9177,-82.19766)"> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000" + d="M 140.20049,454.12696 L 129.75724,443.68372" + id="path2269" /> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" + d="M 139.84823,453.80527 L 129.66343,463.99007" + id="path2271" /> + </g> + </g> + <text + sodipodi:linespacing="100.00000%" + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="342.21133" + y="384.8981" + id="text2275"><tspan + id="tspan2279" + sodipodi:role="line" + y="384.89810" + x="342.21133">header</tspan></text> + <rect + style="fill:#f5f5c8;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500000;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000" + id="rect2283" + width="223.48137" + height="99.596283" + x="46.366730" + y="650.83508" /> + <text + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:120.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="53.664009" + y="693.75391" + id="text2285" + sodipodi:linespacing="120.00000%"><tspan + id="tspan2337" + sodipodi:role="line" + y="693.75391" + x="53.664009">extract(out : outputStream) : void</tspan><tspan + id="tspan2339" + sodipodi:role="line" + y="708.15391" + x="53.664009">getLength() : int</tspan><tspan + id="tspan2341" + sodipodi:role="line" + y="722.55391" + x="53.664009">getEncoding() : encoding</tspan><tspan + id="tspan2343" + sodipodi:role="line" + y="736.95391" + x="53.664009">isEmpty() : bool</tspan></text> + <text + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="107.50659" + y="666.90515" + id="text2289" + sodipodi:linespacing="100.00000%"><tspan + id="tspan2295" + sodipodi:role="line" + y="666.90515" + x="107.50659">contentHandler</tspan></text> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" + d="M 46.694654,675.24013 L 269.50523,675.24013" + id="path2293" /> + <text + sodipodi:linespacing="100.00000%" + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="96.439804" + y="606.38623" + id="text2313"><tspan + id="tspan2331" + sodipodi:role="line" + y="606.38623" + x="96.439804">contents</tspan></text> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2343873;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" + d="M 16.600928,494.52517 L 54.665082,494.52517" + id="path2357" /> + <text + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="114.21628" + y="211.67206" + id="text2359" + sodipodi:linespacing="100.00000%"><tspan + id="tspan2361" + sodipodi:role="line" + y="211.67206" + x="114.21628">0..n</tspan></text> + <text + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="15.201084" + y="211.39832" + id="text2363" + sodipodi:linespacing="100.00000%"><tspan + id="tspan2371" + sodipodi:role="line" + y="211.39832" + x="15.201084">sub-parts</tspan></text> + <text + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="37.547035" + y="486.67206" + id="text2367" + sodipodi:linespacing="100.00000%"><tspan + id="tspan2369" + sodipodi:role="line" + y="486.67206" + x="37.547035">0</tspan></text> + <rect + style="fill:#ffffff;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500843;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000" + id="rect2355" + width="15.541844" + height="15.541844" + x="-313.66727" + y="385.82047" + transform="matrix(0.707107,-0.707107,0.707107,0.707107,0.000000,0.000000)" /> + <rect + style="fill:#f5f5c8;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500000;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000" + id="rect2383" + width="171.85686" + height="67.987976" + x="169.86403" + y="15.308525" /> + <text + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="228.35699" + y="31.574478" + id="text2393" + sodipodi:linespacing="100.00000%"><tspan + id="tspan2399" + sodipodi:role="line" + y="31.574478" + x="228.35699">message</tspan></text> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" + d="M 170.22863,39.909422 L 341.34134,39.909422" + id="path2397" /> + <path + id="path2405" + d="M 266.45394,117.77798 L 238.56502,117.77798 L 252.97430,132.18725 L 266.45394,117.77798 z " + style="fill:#ffffff;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" /> + </g> + <path + id="path5436" + d="M 446.81292,350.17443 L 782.69938,350.17443" + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2515085;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" /> + <path + id="path2373" + d="M 16.806908,219.05029 L 16.806908,493.94805" + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2522694;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" /> +</svg> diff --git a/vmime-master/doc/book/images/messaging-services.svg b/vmime-master/doc/book/images/messaging-services.svg new file mode 100644 index 0000000..fe4f8c8 --- /dev/null +++ b/vmime-master/doc/book/images/messaging-services.svg @@ -0,0 +1,617 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="629.28000pt" + height="615.89000pt" + id="svg2" + sodipodi:version="0.32" + inkscape:version="0.48.0 r9654" + sodipodi:docname="messaging-services.svg" + inkscape:export-filename="/home/vincent/www/vmime/documentation/images/design-messaging.png" + inkscape:export-xdpi="74.639999" + inkscape:export-ydpi="74.639999" + version="1.1"> + <defs + id="defs3"> + <marker + inkscape:stockid="Torso" + orient="auto" + refY="0.0" + refX="0.0" + id="Torso" + style="overflow:visible"> + <g + id="g2045" + transform="scale(0.7)"> + <path + sodipodi:nodetypes="ccccc" + id="path1128" + d="M -4.7792281,-3.2395420 C -2.4288541,-2.8736027 0.52103922,-1.3019943 0.25792722,0.38794346 C -0.0051877922,2.0778819 -2.2126741,2.6176539 -4.5630471,2.2517169 C -6.9134221,1.8857769 -8.5210350,0.75201414 -8.2579220,-0.93792336 C -7.9948090,-2.6278615 -7.1296041,-3.6054813 -4.7792281,-3.2395420 z " + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;marker-start:none;marker-mid:none;marker-end:none" /> + <path + sodipodi:nodetypes="cc" + id="path1909" + d="M 4.4598789,0.088665736 C -2.5564571,-4.3783320 5.2248769,-3.9061806 -0.84829578,-8.7197331" + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;marker-end:none" /> + <path + sodipodi:nodetypes="cc" + id="path1910" + d="M 4.9298719,0.057520736 C -1.3872731,1.7494689 1.8027579,5.4782079 -4.9448731,7.5462725" + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;marker-start:none;marker-end:none" /> + <rect + transform="matrix(0.527536,-0.849533,0.887668,0.460484,0.000000,0.000000)" + y="-1.7408575" + x="-10.391706" + height="2.7608147" + width="2.6366582" + id="rect2035" + style="fill-rule:evenodd;stroke-width:1.0000000pt;marker-end:none" /> + <rect + transform="matrix(0.671205,-0.741272,0.790802,0.612072,0.000000,0.000000)" + y="-7.9629307" + x="4.9587269" + height="2.8614161" + width="2.7327356" + id="rect2036" + style="fill-rule:evenodd;stroke-width:1.0000000pt;marker-end:none" /> + <path + transform="matrix(6.793608e-17,-1.109517,1.109517,6.793608e-17,25.96648,19.71619)" + d="m 16.779951,-28.685045 c 0,0.335412 -0.271905,0.607317 -0.607317,0.607317 -0.335412,0 -0.607317,-0.271905 -0.607317,-0.607317 0,-0.335412 0.271905,-0.607318 0.607317,-0.607318 0.335412,0 0.607317,0.271906 0.607317,0.607318 z" + sodipodi:ry="0.60731727" + sodipodi:rx="0.60731727" + sodipodi:cy="-28.685045" + sodipodi:cx="16.172634" + id="path2037" + style="fill:#ff0000;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;marker-start:none;marker-end:none" + sodipodi:type="arc" /> + <path + transform="matrix(6.793608e-17,-1.109517,1.109517,6.793608e-17,26.82450,16.99126)" + d="m 16.779951,-28.685045 c 0,0.335412 -0.271905,0.607317 -0.607317,0.607317 -0.335412,0 -0.607317,-0.271905 -0.607317,-0.607317 0,-0.335412 0.271905,-0.607318 0.607317,-0.607318 0.335412,0 0.607317,0.271906 0.607317,0.607318 z" + sodipodi:ry="0.60731727" + sodipodi:rx="0.60731727" + sodipodi:cy="-28.685045" + sodipodi:cx="16.172634" + id="path2038" + style="fill:#ff0000;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;marker-start:none;marker-end:none" + sodipodi:type="arc" /> + </g> + </marker> + <marker + inkscape:stockid="TriangleOutL" + orient="auto" + refY="0.0" + refX="0.0" + id="TriangleOutL" + style="overflow:visible"> + <path + sodipodi:nodetypes="cccc" + id="path5324" + d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z " + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none" + transform="scale(0.8)" /> + </marker> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="0.75785828" + inkscape:cx="365.32198" + inkscape:cy="407.27112" + inkscape:document-units="px" + inkscape:current-layer="svg2" + inkscape:window-width="1150" + inkscape:window-height="986" + inkscape:window-x="69" + inkscape:window-y="33" + showgrid="false" + inkscape:window-maximized="0" /> + <metadata + id="metadata4"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <path + id="path5442" + d="M 495.30781,321.26414 L 495.30781,390.57215" + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" /> + <path + id="path5440" + d="M 662.55216,389.28102 L 662.55216,456.99397" + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" /> + <path + id="path5438" + d="M 325.22881,389.28102 L 325.22881,456.99397" + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" /> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1"> + <g + transform="matrix(0.866025,0.499999,-0.499999,0.866025,111.0615,336.6054)" + id="g3452"> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:5.0000000 5.0000000 ;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000" + d="M 278.87323,198.08204 L 405.25462,198.08204" + id="path3454" /> + <g + transform="matrix(-1.000000,-1.845854e-17,1.845854e-17,-1.000000,684.3929,415.9391)" + style="stroke-width:1.2500000;stroke-miterlimit:4.0000000" + id="g3456"> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000" + d="M 278.87321,217.60074 L 289.31646,228.04398" + id="path3458" /> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000" + d="M 279.22547,217.92243 L 289.41027,207.73763" + id="path3460" /> + </g> + </g> + <g + transform="matrix(-0.499998,0.866024,-0.866024,-0.499998,528.2205,319.3107)" + id="g3396"> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:5.0000000 5.0000000 ;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000" + d="M 278.87323,198.08204 L 405.25462,198.08204" + id="path3398" /> + <g + transform="matrix(-1.000000,-1.845854e-17,1.845854e-17,-1.000000,684.3929,415.9391)" + style="stroke-width:1.2500000;stroke-miterlimit:4.0000000" + id="g3400"> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000" + d="M 278.87321,217.60074 L 289.31646,228.04398" + id="path3402" /> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000" + d="M 279.22547,217.92243 L 289.41027,207.73763" + id="path3404" /> + </g> + </g> + <g + transform="matrix(0.500000,0.866024,-0.866024,0.500000,431.6077,-252.3913)" + id="g3200"> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:5.0000000 5.0000000 ;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000" + d="M 278.87323,198.08204 L 405.25462,198.08204" + id="path3202" /> + <g + transform="matrix(-1.000000,-1.845854e-17,1.845854e-17,-1.000000,684.3929,415.9391)" + style="stroke-width:1.2500000;stroke-miterlimit:4.0000000" + id="g3204"> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000" + d="M 278.87321,217.60074 L 289.31646,228.04398" + id="path3206" /> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000" + d="M 279.22547,217.92243 L 289.41027,207.73763" + id="path3208" /> + </g> + </g> + <g + transform="matrix(0.499999,-0.866025,0.866025,0.499999,-54.36140,359.0658)" + id="g3168"> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:5.0000000 5.0000000 ;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000" + d="M 278.87323,198.08204 L 405.25462,198.08204" + id="path3156" /> + <g + transform="matrix(-1.000000,-1.845854e-17,1.845854e-17,-1.000000,684.3929,415.9391)" + style="stroke-width:1.2500000;stroke-miterlimit:4.0000000" + id="g3158"> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000" + d="M 278.87321,217.60074 L 289.31646,228.04398" + id="path3160" /> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000" + d="M 279.22547,217.92243 L 289.41027,207.73763" + id="path3162" /> + </g> + </g> + <rect + style="fill:#f5f5c8;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500000;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000" + id="rect1291" + width="144.63049" + height="123.75754" + x="423.21133" + y="200.65219" /> + <text + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:120.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="430.8407" + y="243.43631" + id="text1293" + sodipodi:linespacing="120.00000%"><tspan + id="tspan3116" + sodipodi:role="line" + y="243.43631" + x="430.84070">connect() : void</tspan><tspan + id="tspan3118" + sodipodi:role="line" + y="257.83631" + x="430.84070">disconnect() : void</tspan><tspan + id="tspan3120" + sodipodi:role="line" + y="272.23631" + x="430.84070">isConnected() : bool</tspan><tspan + id="tspan3122" + sodipodi:role="line" + y="286.63631" + x="430.84070">noop() : void</tspan></text> + <text + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="473.4863" + y="216.58759" + id="text2347" + sodipodi:linespacing="100.00000%"><tspan + id="tspan2932" + sodipodi:role="line" + y="216.58759" + x="473.48630">service</tspan></text> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" + d="M 423.62452,224.92254 L 567.67587,224.92254" + id="path2351" /> + <rect + style="fill:#f5f5c8;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500000;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000" + id="rect2353" + width="254.50919" + height="106.53888" + x="40.771675" + y="200.75146" /> + <text + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:120.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="49.807129" + y="243.64157" + id="text2355" + sodipodi:linespacing="120.00000%"><tspan + id="tspan3148" + sodipodi:role="line" + y="243.64157" + x="49.807129">getTransport(url : url) : ref <transport></tspan><tspan + id="tspan3150" + sodipodi:role="line" + y="258.04157" + x="49.807129">getStore(url : url) : ref <store></tspan><tspan + id="tspan3152" + sodipodi:role="line" + y="272.44157" + x="49.807129">getProperties() : propertySet</tspan></text> + <text + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="143.33478" + y="216.79285" + id="text2375" + sodipodi:linespacing="100.00000%"><tspan + id="tspan3124" + sodipodi:role="line" + y="216.79285" + x="143.33478">session</tspan></text> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" + d="M 41.137120,225.12780 L 294.90028,225.12780" + id="path2379" /> + <rect + style="fill:#f5f5c8;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500000;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000" + id="rect2433" + width="219.00885" + height="100.80741" + x="215.20381" + y="429.00940" /> + <text + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:120.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="223.58997" + y="472.3562" + id="text2435" + sodipodi:linespacing="120.00000%"><tspan + id="tspan3110" + sodipodi:role="line" + y="472.35620" + x="223.58997">getDefaultFolder() : ref <folder></tspan><tspan + id="tspan3112" + sodipodi:role="line" + y="486.75620" + x="223.58997">getRootFolder() : ref <folder></tspan></text> + <text + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="309.11777" + y="445.50742" + id="text2439" + sodipodi:linespacing="100.00000%"><tspan + id="tspan2936" + sodipodi:role="line" + y="445.50742" + x="309.11777">store</tspan></text> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" + d="M 216.61640,453.84241 L 433.36337,453.84241" + id="path2443" /> + <rect + style="fill:#f5f5c8;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500000;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000" + id="rect2447" + width="219.00674" + height="101.04262" + x="553.75336" + y="428.77499" /> + <text + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:120.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="561.0639" + y="472.20447" + id="text2449" + sodipodi:linespacing="120.00000%"><tspan + id="tspan3114" + sodipodi:role="line" + y="472.20447" + x="561.06390">send(msg : ref <message>) : void</tspan></text> + <text + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="632.07196" + y="445.35568" + id="text2453" + sodipodi:linespacing="100.00000%"><tspan + id="tspan2934" + sodipodi:role="line" + y="445.35568" + x="632.07196">transport</tspan></text> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" + d="M 554.08593,453.69062 L 771.88660,453.69062" + id="path2457" /> + <path + id="path2575" + d="M 481.88130,340.17064 L 509.77022,340.17064 L 495.36094,325.76137 L 481.88130,340.17064 z " + style="fill:#ffffff;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" /> + <g + transform="translate(17.15883,45.55696)" + id="g3136"> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" + d="M 405.51967,217.85706 L 279.13828,217.85706" + id="path2265" /> + <g + style="stroke-width:1.2500000;stroke-miterlimit:4.0000000" + id="g3132"> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000" + d="M 278.87321,217.60074 L 289.31646,228.04398" + id="path2269" /> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000" + d="M 279.22547,217.92243 L 289.41027,207.73763" + id="path2271" /> + </g> + </g> + <text + sodipodi:linespacing="100.00000%" + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="335.37018" + y="257.45505" + id="text2275"><tspan + id="tspan3146" + sodipodi:role="line" + y="257.45505" + x="335.37018">session</tspan></text> + <text + transform="matrix(0.500000,0.866025,-0.866025,0.500000,0.000000,0.000000)" + sodipodi:linespacing="100.00000%" + xml:space="preserve" + style="font-size:11.999973px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="313.42676" + y="-318.0412" + id="text3174"><tspan + id="tspan3178" + sodipodi:role="line" + y="-318.04120" + x="313.42676"><instanciates></tspan></text> + <rect + style="fill:#f5f5c8;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500000;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000" + id="rect3180" + width="253.81813" + height="96.037521" + x="234.02649" + y="9.0948601" /> + <text + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:120.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="241.24963" + y="52.019093" + id="text3182" + sodipodi:linespacing="120.00000%"><tspan + id="tspan3218" + sodipodi:role="line" + y="52.019093" + x="241.24963">create(protocol : string) : ref <service></tspan></text> + <text + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="312.24161" + y="25.170307" + id="text3192" + sodipodi:linespacing="100.00000%"><tspan + id="tspan3198" + sodipodi:role="line" + y="25.170307" + x="312.24161">serviceFactory</tspan></text> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" + d="M 234.44127,33.505080 L 487.67742,33.505080" + id="path3196" /> + <text + transform="matrix(0.500000,-0.866025,0.866025,0.500000,0.000000,0.000000)" + sodipodi:linespacing="100.00000%" + xml:space="preserve" + style="font-size:11.999965px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="-19.006903" + y="316.46106" + id="text3210"><tspan + id="tspan3214" + sodipodi:role="line" + y="316.46106" + x="-19.006903"><uses></tspan></text> + <rect + style="fill:#f5f5c8;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500000;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000" + id="rect3362" + width="244.86130" + height="116.61144" + x="14.277589" + y="572.10736" /> + <text + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:120.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="22.589966" + y="615.3562" + id="text3364" + sodipodi:linespacing="120.00000%"><tspan + id="tspan3386" + sodipodi:role="line" + y="615.35620" + x="22.589966">getName() : string</tspan><tspan + id="tspan3388" + sodipodi:role="line" + y="629.75620" + x="22.589966">open() : void</tspan><tspan + id="tspan3390" + sodipodi:role="line" + y="644.15620" + x="22.589966">close() : void</tspan><tspan + id="tspan3392" + sodipodi:role="line" + y="658.55620" + x="22.589966">getMessages(int from, int to) : vector</tspan><tspan + id="tspan3394" + sodipodi:role="line" + y="672.95620" + x="22.589966">...</tspan></text> + <text + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="119.45631" + y="588.50739" + id="text3370" + sodipodi:linespacing="100.00000%"><tspan + id="tspan3376" + sodipodi:role="line" + y="588.50739" + x="119.45631">folder</tspan></text> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2449049;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" + d="M 15.691587,596.84241 L 258.28817,596.84241" + id="path3374" /> + <text + transform="matrix(0.500000,-0.866025,0.866025,0.500000,0.000000,0.000000)" + sodipodi:linespacing="100.00000%" + xml:space="preserve" + style="font-size:11.999992px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="-398.12543" + y="406.40524" + id="text3406"><tspan + id="tspan3408" + sodipodi:role="line" + y="406.40524" + x="-398.12543"><instanciates></tspan></text> + <rect + style="fill:#f5f5c8;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500000;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000" + id="rect3410" + width="244.86130" + height="140.35690" + x="365.27762" + y="617.23462" /> + <text + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:120.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="373.59" + y="660.3562" + id="text3412" + sodipodi:linespacing="120.00000%"><tspan + id="tspan3440" + sodipodi:role="line" + y="660.35620" + x="373.59000">getNumber() : int</tspan><tspan + id="tspan3442" + sodipodi:role="line" + y="674.75620" + x="373.59000">getFlags() : int</tspan><tspan + id="tspan3444" + sodipodi:role="line" + y="689.15620" + x="373.59000">getHeader() : int</tspan><tspan + id="tspan3446" + sodipodi:role="line" + y="703.55620" + x="373.59000">getStructure() : structure</tspan><tspan + id="tspan3448" + sodipodi:role="line" + y="717.95620" + x="373.59000">extract(out : outputStream) : void</tspan><tspan + id="tspan3450" + sodipodi:role="line" + y="732.35620" + x="373.59000">...</tspan></text> + <text + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="459.11771" + y="633.50739" + id="text3424" + sodipodi:linespacing="100.00000%"><tspan + id="tspan3430" + sodipodi:role="line" + y="633.50739" + x="459.11771">message</tspan></text> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2449049;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" + d="M 366.69159,641.84241 L 609.28817,641.84241" + id="path3428" /> + <text + transform="matrix(0.866025,0.500000,-0.500000,0.866025,0.000000,0.000000)" + sodipodi:linespacing="100.00000%" + xml:space="preserve" + style="font-size:11.999992px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="558.315" + y="419.37476" + id="text3462"><tspan + id="tspan3464" + sodipodi:role="line" + y="419.37476" + x="558.31500"><instanciates></tspan></text> + </g> + <path + id="path5436" + d="M 325.97175,390.06210 L 661.85821,390.06210" + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2515085;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" /> + <rect + y="170.36218" + x="668.00000" + height="76.000000" + width="134.00000" + id="rect3360" + style="stroke-opacity:1.0000000;stroke-dashoffset:0.0000000;stroke-miterlimit:4.0000000;stroke-linejoin:miter;stroke-linecap:round;stroke-width:1.2500000;stroke:none;fill-rule:nonzero;fill-opacity:1.0000000;fill:none" /> +</svg> diff --git a/vmime-master/doc/book/intro.tex b/vmime-master/doc/book/intro.tex new file mode 100644 index 0000000..fe7bcf5 --- /dev/null +++ b/vmime-master/doc/book/intro.tex @@ -0,0 +1,90 @@ +\chapter{Introduction} + +% ============================================================================ +\section{Overview} + +VMime is a powerful C++ class library for working with MIME messages and +Internet messaging services like IMAP, POP or SMTP. + +With VMime you can parse, generate and modify messages, and also connect to +store and transport services to receive or send messages over the Internet. +The library offers all the features to build a complete mail client. + +The main objectives of this library are: + +\begin{itemize} +\item fully RFC-compliant implementation; +\item object-oriented and modular design; +\item very easy-to-use (intuitive design); +\item well documented code; +\item very high reliability; +\item maximum portability. +\end{itemize} + + +% ============================================================================ +\section{Features} + +\noindent MIME features: + +\begin{itemize} +\item Full support for RFC-2822 and multipart messages (RFC-1521) +\item Aggregate documents (MHTML) and embedded objects (RFC-2557) +\item Message Disposition Notification (RFC-3798) +\item 8-bit MIME (RFC-2047) +\item Encoded word extensions (RFC-2231) +\item Attachments +\end{itemize} + +\noindent Network features: + +\begin{itemize} +\item Support for IMAP, POP3 and maildir stores +\item Support for SMTP and sendmail transport methods +\item Extraction of whole message or specific parts +\item TLS/SSL security layer +\item SASL authentication +\end{itemize} + + +% ============================================================================ +\section{Copyright and license} + +VMime library is Free Software and is licensed under the terms of the GNU +General Public License\footnote{See Appendix \ref{appendix_license} and +\url{http://www.gnu.org/copyleft/gpl.html}} (GPL) version 3: + +\begin{verbatim} + Copyright (C) 2002 Vincent Richard + + VMime library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 3 of + the License, or (at your option) any later version. + + VMime is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Linking this library statically or dynamically with other + modules is making a combined work based on this library. + Thus, the terms and conditions of the GNU General Public + License cover the whole combination. +\end{verbatim} + +\newpage +\noindent This document is released under the terms of the +GNU Free Documentation +License\footnote{See \url{http://www.gnu.org/copyleft/fdl.html}} (FDL): + +\begin{verbatim} + Copyright (C) 2004 Vincent Richard + + Permission is granted to copy, distribute and/or modify + this document under the terms of the GNU Free Documentation + License, Version 1.2 or any later version published by the + Free Software Foundation; with no Invariant Sections, no + Front-Cover Texts, and no Back-Cover Texts. +\end{verbatim} + diff --git a/vmime-master/doc/book/msg.tex b/vmime-master/doc/book/msg.tex new file mode 100644 index 0000000..ce9d8a8 --- /dev/null +++ b/vmime-master/doc/book/msg.tex @@ -0,0 +1,430 @@ +\chapter{Parsing and Building Messages} + +% ============================================================================ +\section{Parsing messages} + +\subsection{Introduction} % -------------------------------------------------- + +Parsing is the process of creating a structured representation (for example, +a hierarchy of C++ objects) of a message from its ``textual'' representation +(the raw data that is actually sent on the Internet). + +For example, say you have the following email in a file called "hello.eml": + +\begin{verbatim} +Date: Thu, Oct 13 2005 15:22:46 +0200 +From: Vincent <vincent@vmime.org> +To: you@vmime.org +Subject: Hello from VMime! + +A simple message to test VMime +\end{verbatim} + +The following code snippet shows how you can easily obtain a +{\vcode vmime::message} object from data in this file: + +\begin{lstlisting}[caption={Parsing a message from a file}] +// Read data from file +std::ifstream file; +file.open("hello.eml", std::ios::in | std::ios::binary); + +vmime::utility::inputStreamAdapter is(file); + +vmime::string data; +vmime::utility::outputStreamStringAdapter os(data); + +vmime::utility::bufferedStreamCopy(is, os); + +// Actually parse the message +vmime::shared_ptr <vmime::message> msg = vmime::make_shared <vmime::message>(); +msg->parse(data); + +vmime::shared_ptr <vmime::header> hdr = msg->getHeader(); +vmime::shared_ptr <vmime::body> bdy = msg->getBody(); + +// Now, you can extract some of its components +vmime::charset ch(vmime::charsets::UTF_8); + +std::cout + << "The subject of the message is: " + << hdr->Subject()->getValue <vmime::text>()->getConvertedText(ch) + << std::endl + << "It was sent by: " + << hdr->From()->getValue <vmime::mailbox>()->getName().getConvertedText(ch) + << " (email: " << hdr->From()->getValue <vmime::mailbox>()->getEmail() << ")" + << std::endl; +\end{lstlisting} + +The output of this program is: + +\begin{verbatim} +The subject of the message is: Hello from VMime! +It was sent by: Vincent (email: vincent@vmime.org) +\end{verbatim} + + +\subsection{Using the {\vcode vmime::messageParser} object} % ---------------- + +The {\vcode vmime::messageParser} object allows to parse messages in a more +simple manner. You can obtain all the text parts and attachments as well as +basic fields (expeditor, recipients, subject...), without dealing with +MIME message structure. + +\begin{lstlisting}[caption={Using {\vcode vmime::messageParser} to parse +more complex messages}] +// Read data from file +std::ifstream file; +file.open("hello.eml", std::ios::in | std::ios::binary); + +vmime::utility::inputStreamAdapter is(file); + +vmime::string data; +vmime::utility::outputStreamStringAdapter os(data); + +vmime::utility::bufferedStreamCopy(is, os); + +// Actually parse the message +vmime::shared_ptr <vmime::message> msg = vmime::make_shared <vmime::message>(); +msg->parse(data); + +// Here start the differences with the previous example +vmime::messageParser mp(msg); + +// Output information about attachments +std::cout << "Message has " << mp.getAttachmentCount() + << " attachment(s)" << std::endl; + +for (int i = 0 ; i < mp.getAttachmentCount() ; ++i) { + + vmime::shared_ptr <const vmime::attachment> att = mp.getAttachmentAt(i); + std::cout << " - " << att->getType().generate() << std::endl; +} + +// Output information about text parts +std::cout << "Message has " << mp.getTextPartCount() + << " text part(s)" << std::endl; + +for (int i = 0 ; i < mp.getTextPartCount() ; ++i) { + + vmime::shared_ptr <const vmime::textPart> tp = mp.getTextPartAt(i); + + // text/html + if (tp->getType().getSubType() == vmime::mediaTypes::TEXT_HTML) { + + vmime::shared_ptr <const vmime::htmlTextPart> htp = + vmime::dynamicCast <const vmime::htmlTextPart>(tp); + + // HTML text is in tp->getText() + // Plain text is in tp->getPlainText() + + // Enumerate embedded objects + for (int j = 0 ; j < htp->getObjectCount() ; ++j) { + + vmime::shared_ptr <const vmime::htmlTextPart::embeddedObject> obj = + htp->getObjectAt(j); + + // Identifier (Content-Id or Content-Location) is obj->getId() + // Object data is in obj->getData() + } + + // text/plain or anything else + } else { + + // Text is in tp->getText() + } +} +\end{lstlisting} + + +% ============================================================================ +\section{Building messages} + +\subsection{A simple message\label{msg-building-simple-message}} % ----------- + +Of course, you can build a MIME message from scratch by creating the various +objects that compose it (parts, fields, etc.). The following is an example of +how to achieve it: + +\begin{lstlisting}[caption={Building a simple message from scratch}] +vmime::shared_ptr <vmime::message> msg = vmime::make_shared <vmime::message>(); + +vmime::shared_ptr <vmime::header> hdr = msg->getHeader(); +vmime::shared_ptr <vmime::body> bdy = msg->getBody(); + +vmime::shared_ptr <vmime::headerFieldFactory> hfFactory = + vmime::headerFieldFactory::getInstance(); + +// Append a 'Date:' field +vmime::shared_ptr <vmime::headerField> dateField = + hfFactory->create(vmime::fields::DATE); + +dateField->setValue(vmime::datetime::now()); +hdr->appendField(dateField); + +// Append a 'Subject:' field +vmime::shared_ptr <vmime::headerField> subjectField = + hfFactory->create(vmime::fields::SUBJECT); + +subjectField->setValue(vmime::text("Message subject")); +hdr->appendField(subjectField); + +// Append a 'From:' field +vmime::shared_ptr <vmime::headerField> fromField = + hfFactory->create(vmime::fields::FROM); + +fromField->setValue(vmime::make_shared <vmime::mailbox>("me@vmime.org")); +hdr->appendField(fromField); + +// Append a 'To:' field +vmime::shared_ptr <vmime::headerField> toField = + hfFactory->create(vmime::fields::TO); + +vmime::shared_ptr <vmime::mailboxList> recipients = + vmime::make_shared <vmime::mailboxList>(); + +recipients->appendMailbox + (vmime::make_shared <vmime::mailbox>("you@vmime.org")); + +toField->setValue(recipients); +hdr->appendField(toField); + +// Set the body contents +bdy->setContents( + vmime::make_shared <vmime::stringContentHandler>( + "This is the text of your message..." + ) +); + +// Output raw message data to standard output +vmime::utility::outputStreamAdapter out(std::cout); +msg->generate(out); +\end{lstlisting} + +As you can see, this is a little fastidious. Hopefully, VMime also offers a +more simple way for creating messages. The {\vcode vmime::messageBuilder} +object can create basic messages that you can then customize. + +The following code can be used to build exactly the same message as in the +previous example, using the {\vcode vmime::messageBuilder} object: + +\begin{lstlisting}[caption={Building a simple message +using {\vcode vmime::messageBuilder}}] +try { + + vmime::messageBuilder mb; + + // Fill in some header fields and message body + mb.setSubject(vmime::text("Message subject")); + mb.setExpeditor(vmime::mailbox("me@vmime.org")); + mb.getRecipients().appendAddress( + vmime::make_shared <vmime::mailbox>("you@vmime.org") + ); + + mb.getTextPart()->setCharset(vmime::charsets::ISO8859_15); + mb.getTextPart()->setText( + vmime::make_shared <vmime::stringContentHandler>( + "This is the text of your message..." + ) + ); + + // Message construction + vmime::shared_ptr <vmime::message> msg = mb.construct(); + + // Output raw message data to standard output + vmime::utility::outputStreamAdapter out(std::cout); + msg->generate(out); + +// VMime exception +} catch (vmime::exception& e) { + + std::cerr << "vmime::exception: " << e.what() << std::endl; + +// Standard exception +} catch (std::exception& e) { + + std::cerr << "std::exception: " << e.what() << std::endl; +} +\end{lstlisting} + + +\subsection{Adding an attachment} % ------------------------------------------ + +Dealing with attachments is quite simple. Add the following code to the +previous example to attach a file to the message: + +\begin{lstlisting}[caption={Building a message with an attachment using +{\vcode vmime::messageBuilder}}] +// Create an attachment +vmime::shared_ptr <vmime::fileAttachment> att = + vmime::make_shared <vmime::fileAttachment>( + /* full path to file */ "/home/vincent/paris.jpg", + /* content type */ vmime::mediaType("image/jpeg), + /* description */ vmime::text("My holidays in Paris") + ); + +// You can also set some infos about the file +att->getFileInfo().setFilename("paris.jpg"); +att->getFileInfo().setCreationDate( + vmime::datetime("30 Apr 2003 14:30:00 +0200") +); + +// Add this attachment to the message +mb.appendAttachment(att); +\end{lstlisting} + + +\subsection{HTML messages and embedded objects} % ---------------------------- + +VMime also supports aggregate messages, which permits to build MIME messages +containing HTML text and embedded objects (such as images). For more information +about aggregate messages, please read RFC-2557 (\emph{MIME Encapsulation of +Aggregate Documents, such as HTML}). + +Creating such messages is quite easy, using the {\vcode vmime::messageBuilder} +object. The following code constructs a message containing text in both plain +and HTML format, and a JPEG image: + +\begin{lstlisting}[caption={Building an HTML message with an embedded image +using the {\vcode vmime::messageBuilder}}] +// Fill in some header fields +mb.setSubject(vmime::text("An HTML message")); +mb.setExpeditor(vmime::mailbox("me@vmime.org")); +mb.getRecipients().appendAddress( + vmime::make_shared <vmime::mailbox>("you@vmime.org") +); + +// Set the content-type to "text/html": a text part factory must be +// available for the type you are using. The following code will make +// the message builder construct the two text parts. +mb.constructTextPart( + vmime::mediaType( + vmime::mediaTypes::TEXT, + vmime::mediaTypes::TEXT_HTML + ) +); + +// Set contents of the text parts; the message is available in two formats: +// HTML and plain text. The HTML format also includes an embedded image. +vmime::shared_ptr <vmime::htmlTextPart> textPart = + vmime::dynamicCast <vmime::htmlTextPart>(mb.getTextPart()); + +// -- Add the JPEG image (the returned identifier is used to identify the +// -- embedded object in the HTML text, the famous "CID", or "Content-Id"). +// -- Note: you can also read data from a file; see the next example. +const vmime::string id = textPart->addObject("<...image data...>", + vmime::mediaType(vmime::mediaTypes::IMAGE, vmime::mediaTypes::IMAGE_JPEG)); + +// -- Set the text +textPart->setCharset(vmime::charsets::ISO8859_15); + +textPart->setText( + vmime::make_shared <vmime::stringContentHandler>( + "This is the <b>HTML text</b>, and the image:<br/>" + "<img src=\"") + id + vmime::string("\"/>" + ) +); + +textPart->setPlainText( + vmime::make_shared <vmime::stringContentHandler>( + "This is the plain text." + ) +); +\end{lstlisting} + +This will create a message having the following structure: + +\begin{verbatim} +multipart/alternative + text/plain + multipart/related + text/html + image/jpeg +\end{verbatim} + +You can easily tell VMime to read the embedded object data from a file. The +following code opens the file \emph{/path/to/image.jpg}, connects it to an +input stream, then add an embedded object: + +\begin{lstlisting} +vmime::utility::fileSystemFactory* fs = + vmime::platform::getHandler()->getFileSystemFactory(); + +vmime::shared_ptr <vmime::utility::file> imageFile = + fs->create(fs->stringToPath("/path/to/image.jpg")); + +vmime::shared_ptr <vmime::contentHandler> imageCts = + vmime::make_shared <vmime::streamContentHandler>( + imageFile->getFileReader()->getInputStream(), + imageFile->getLength() + ); + +const vmime::string cid = textPart.addObject( + imageCts, + vmime::mediaType( + vmime::mediaTypes::IMAGE, + vmime::mediaTypes::IMAGE_JPEG + ) +); +\end{lstlisting} + + +% ============================================================================ +\section{Working with attachments: the attachment helper} + +The {\vcode attachmentHelper} object allows listing all attachments in a +message, as well as adding new attachments, without using the +{\vcode messageParser} and {\vcode messageBuilders} objects. It can work +directly on messages and body parts. + +To use it, you do not need any knowledge about how attachment parts should +be organized in a MIME message. + +The following code snippet tests if a body part is an attachment, and if so, +extract its contents to the standard output: + +\begin{lstlisting}[caption={Testing if a body part is an attachment}] +vmime::shared_ptr <vmime::bodyPart> part; // suppose we have a body part + +if (vmime::attachmentHelper::isBodyPartAnAttachment(part)) { + + // The body part contains an attachment, get it + vmime::shared_ptr <const vmime::attachment> attach = + attachmentHelper::getBodyPartAttachment(part); + + // Extract attachment data to standard output + vmime::utility::outputStreamAdapter out(std::cout); + attach->getData()->extract(out); +} +\end{lstlisting} + +You can also easily extract all attachments from a message: + +\begin{lstlisting}[caption={Extracting all attachments from a message}] +vmime::shared_ptr <vmime::message> msg; // suppose we have a message + +const std::vector <ref <const attachment> > atts = + attachmentHelper::findAttachmentsInMessage(msg); +\end{lstlisting} + +Finally, the {\vcode attachmentHelper} object can be used to add an +attachment to an existing message, whatever it contains (text parts, +attachments, ...). The algorithm can modify the structure of the +message if needed (eg. add a \emph{multipart/mixed} part if no one +exists in the message). Simply call the {\vcode addAttachment} +function: + +\begin{lstlisting}[caption={Adding an attachment to an existing message}] +vmime::shared_ptr <vmime::message> msg; // suppose we have a message + +// Create an attachment +vmime::shared_ptr <vmime::fileAttachment> att = + vmime::make_shared <vmime::fileAttachment>( + /* full path to file */ "/home/vincent/paris.jpg", + /* content type */ vmime::mediaType("image/jpeg), + /* description */ vmime::text("My holidays in Paris") + ); + +// Attach it to the message +vmime::attachmentHelper::addAttachment(msg, att); +\end{lstlisting} + diff --git a/vmime-master/doc/book/net.tex b/vmime-master/doc/book/net.tex new file mode 100644 index 0000000..3fab903 --- /dev/null +++ b/vmime-master/doc/book/net.tex @@ -0,0 +1,1203 @@ +\chapter{Working with Messaging Services} + +% ============================================================================ +\section{Introduction} + +In addition to parsing and building MIME messages, VMime also offers a lot of +features to work with messaging services. This includes connecting to remote +messaging stores (like IMAP or POP3), local stores (maildir) and transport +services (send messages over SMTP or local sendmail), through an unified +interface (see Figure \ref{uml_messaging_module}). That means that you can +use independently IMAP of POP3 without having to change any line of code. + +Source code of {\vexample Example6} covers all features presented in this +chapter, so it is important you take some time to read it. + +\begin{figure} + \center\includegraphics[width=0.9\textwidth] + {images/messaging-services.png}\endcenter + \caption{Overall structure of the messaging module} + \label{uml_messaging_module} +\end{figure} + +The interface is composed of five classes: + +\begin{itemize} +\item {\vcode vmime::net::service}: this is the base interface for a +messaging service. It can be either a store service or a transport +service. + +\item {\vcode vmime::net::serviceFactory}: create instances of a service. +This is used internally by the session object (see below). + +\item {\vcode vmime::net::store}: interface for a store service. A store +service offers access to a set of folders containing messages. This is +used for IMAP, POP3 and maildir. + +\item {\vcode vmime::net::transport}: interface for a transport service. +A transport service is capable of sending messages. This is used for +SMTP and sendmail. + +\item {\vcode vmime::net::session}: a session object is used to store the +parameters used by a service (eg. connection parameters). Each service +instance is associated with only one session. The session object is capable +of creating instances of services. +\end{itemize} + +The following classes are specific to store services: + +\begin{itemize} +\item {\vcode vmime::net::folder}: a folder can either contain other folders +or messages, or both. + +\item {\vcode vmime::net::message}: this is the interface for dealing with +messages. For a given message, you can have access to its flags, its MIME +structure and you can also extract the whole message data or given parts (if +supported by the underlying protocol). +\end{itemize} + + +% ============================================================================ +\section{Working with sessions} + +\subsection{Setting properties} % -------------------------------------------- + +Sessions are used to store configuration parameters for services. They +contains a set of typed properties that can modify the behaviour of the +services. Before using a messaging service, you must create and +initialize a session object: + +\begin{lstlisting} +vmime::shared_ptr <vmime::net::session> theSession = vmime::net::session::create(); +\end{lstlisting} + +Session properties include: + +\begin{itemize} +\item connection parameters: host and port to connect to; +\item authentication parameters: user credentials required to use the +service (if any); +\item protocol-specific parameters: enable or disable extensions (eg. APOP +support in POP3). +\end{itemize} + +Properties are stored using a dotted notation, to specify the service type, +the protocol name, the category and the name of the property: + +\begin{verbatim} + {service_type}.{protocol}.category.name +\end{verbatim} + +An example of property is \emph{store.pop3.options.apop} (used to enable or +disable the use of APOP authentication). The \emph{store.pop3} part is called +the \emph{prefix}. This allow specifying different values for the same +property depending on the protocol used. + +The session properties are stored in a {\vcode vmime::propertySet} object. +To set the value of a property, you can use either: + +\begin{lstlisting} +theSession->getProperties().setProperty("property-name", value); +\end{lstlisting} + +or: + +\begin{lstlisting} +theSession->getProperties()["property-name"] = value; +\end{lstlisting} + + +\subsection{Available properties} % ------------------------------------------ + +Following is a list of available properties and the protocols they apply to, +as the time of writing this documentation\footnote{You can get an up-to-date +list of the properties by running \vexample{Example7}}. For better clarity, +the prefixes do not appear in this table. + +\begin{table}[!ht] +\noindent\begin{tabularx}{1.0\textwidth}{|l|c|X|c|c|c|c|c|c|c|c|} +\hline + {\bf Property name} & + {\bf Type} & + {\bf Description} & + \verti{\bf POP3} & + \verti{\bf POP3S} & + \verti{\bf IMAP} & + \verti{\bf IMAPS} & + \verti{\bf SMTP} & + \verti{\bf SMTPS} & + \verti{\bf maildir} & + \verti{\bf sendmail} \\ +\hline +\hline +options.sasl & bool & Set to {\vcode true} to use SASL authentication, if +available. & \vdot & \vdot & \vdot & \vdot & \vdot & \vdot & & \\ +\hline +options.sasl.fallback & bool & Fail if SASL authentication failed (do not +try other authentication mechanisms). & \vdot & \vdot & \vdot & \vdot & +\vdot & \vdot & & \\ +\hline +auth.username\footnote{You should use authenticators +instead.\label{fn_auth_username}} & string & Set the username of the account +to connect to. & \vdot & \vdot & \vdot & \vdot & \vdot & \vdot & & \\ +\hline +auth.password\footref{fn_auth_username} & string & Set the password of the +account. & \vdot & \vdot & \vdot & \vdot & \vdot & \vdot & & \\ +\hline +connection.tls & bool & Set to {\vcode true} to start a secured connection +using STARTTLS extension, if available. & \vdot & & \vdot & & \vdot & & & \\ +\hline +connection.tls.required & bool & Fail if a secured connection cannot be +started. & \vdot & & \vdot & & \vdot & & & \\ +\hline +server.address & string & Server host name or IP address. &\vdot & \vdot & +\vdot & \vdot & \vdot & \vdot & & \\ +\hline +server.port & int & Server port. & \vdot & \vdot & \vdot & \vdot & +\vdot & \vdot & & \\ +\hline +server.rootpath & string & Root directory for mail repository (eg. +\emph{/home/vincent/Mail}). & & & & & & & \vdot & \\ +\hline +\end{tabularx} +\caption{Properties common to all protocols} +\end{table} + +\newpage +These are the protocol-specific options: + +\begin{table}[!ht] +\noindent\begin{tabularx}{1.0\textwidth}{|l|c|X|} +\hline + {\bf Property name} & + {\bf Type} & + {\bf Description} \\ +% POP3/POP3S +\hline +\multicolumn{3}{|c|}{POP3, POP3S} \\ +\hline +store.pop3.options.apop & bool & Enable or disable authentication with +APOP (if SASL is enabled, this occurs after all SASL mechanisms have been +tried). \\ +\hline +store.pop3.options.apop.fallback & bool & If set to {\vcode true} and +APOP fails, the authentication process fails (ie. unsecure plain text +authentication is not used). \\ +\hline +% SMTP +\multicolumn{3}{|c|}{SMTP, SMTPS} \\ +\hline +transport.smtp.options.need-authentication & bool & Set to \emph{true} if +the server requires to authenticate before sending messages. \\ +\hline +transport.smtp.options.pipelining & bool & Set to {\vcode false} to disable +command pipelining, if the server supports it (default is {\vcode true}). \\ +\hline +transport.smtp.options.chunking & bool & Set to {\vcode false} to disable +CHUNKING extension, if the server supports it (default is {\vcode true}). \\ +\hline +% sendmail +\multicolumn{3}{|c|}{sendmail} \\ +\hline +transport.sendmail.binpath & string & The path to the \emph{sendmail} +executable on your system. The default is the one found by the configuration +script when VMime was built. \\ +\hline +\end{tabularx} +\caption{Protocol-specific options} +\end{table} + + +\subsection{Instanciating services} % ---------------------------------------- + +You can create a service either by specifying its protocol name, or by +specifying the URL of the service. Creation by name is deprecated so +this chapter only presents the latter option. + +The URL scheme for connecting to services is: + +\begin{verbatim} + protocol://[username[:password]@]host[:port]/[root-path] +\end{verbatim} + +\vnote{For local services (ie. \emph{sendmail} and \emph{maildir}), the host +part is not used, but it must not be empty (you can use "localhost").} + +The following table shows an example URL for each service: + +\noindent\begin{tabularx}{1.0\textwidth}{|c|X|} +\hline + {\bf Service} & + {\bf Connection URL} \\ +\hline +imap, imaps & {\tt imap://imap.example.com}, +{\tt imaps://vincent:pass@example.com} \\ +\hline +pop3, pop3s & {\tt pop3://pop3.example.com} \\ +\hline +smtp, smtps & {\tt smtp://smtp.example.com} \\ +\hline +maildir & {\tt maildir://localhost/home/vincent/Mail} (host not used) \\ +\hline +sendmail & {\tt sendmail://localhost} (host not used, always localhost) \\ +\hline +\end{tabularx} + +\newpage + +When you have the connection URL, instanciating the service is quite simple. +Depending on the type of service, you will use either {\vcode getStore()} or +{\vcode getTransport()}. For example, for store services, use: + +\begin{lstlisting} +vmime::utility:url url("imap://user:pass@imap.example.com"); +vmime::shared_ptr <vmime::net::store> st = sess->getStore(url); +\end{lstlisting} + +and for transport services: + +\begin{lstlisting} +vmime::utility:url url("smtp://smtp.example.com"); +vmime::shared_ptr <vmime::net::transport> tr = sess->getTransport(url); +\end{lstlisting} + + +% ============================================================================ +\section{User credentials and authenticators} + +Some services need some user credentials (eg. username and password) to open +a session. In VMime, user credentials can be specified in the session +properties or by using a custom authenticator (callback). + +\begin{lstlisting}[caption={Setting user credentials using session +properties}] +vmime::shared_ptr <vmime::net::session> sess; // Suppose we have a session + +sess->getProperties()["store.imap.auth.username"] = "vincent"; +sess->getProperties()["store.imap.auth.password"] = "my-password"; +\end{lstlisting} + +Although not recommended, you can also specify username and password +directly in the connection URL, +ie: \emph{imap://username:password@imap.example.com/}. This works only for +services requiring an username and a password as user credentials, and no +other information. + +Sometimes, it may not be very convenient to set username/password in the +session properties, or not possible (eg. extended SASL mechanisms) . That's +why VMime offers an alternate way of getting user credentials: the +{\vcode authenticator} object. Basically, an authenticator is an object that +can return user credentials on-demand (like a callback). + +Currently, there are two types of authenticator in VMime: a basic +authenticator (class {\vcode vmime::security::authenticator}) and, if SASL +support is enabled, a SASL authenticator +(class {\vcode vmime::security::sasl::SASLAuthenticator}). Usually, you +should use the default implementations, or at least make your own +implementation inherit from them. + +The following example shows how to use a custom authenticator to request +the user to enter her/his credentials: + +\begin{lstlisting}[caption={A simple interactive authenticator}] +class myAuthenticator : public vmime::security::defaultAuthenticator { + + const string getUsername() const { + + std::cout << "Enter your username: " << std::endl; + + vmime::string res; + std::getline(std::cin, res); + + return res; + } + + const string getPassword() const { + + std::cout << "Enter your password: " << std::endl; + + vmime::string res; + std::getline(std::cin, res); + + return res; + } +}; +\end{lstlisting} + +This is how to use it: + +\begin{lstlisting} +// First, create a session +vmime::shared_ptr <vmime::net::session> sess = vmime::net::session::create(); + +// Next, initialize a service which will use our authenticator +vmime::shared_ptr <vmime::net::store> st = sess->getStore( + vmime::utility::url("imap://imap.example.com"), + /* use our authenticator */ vmime::make_shared <myAuthenticator>() +); +\end{lstlisting} + +\vnote{An authenticator object should be used with one and only one service +at a time. This is required because the authentication process may need to +retrieve the service name (SASL).} + +Of course, this example is quite simplified. For example, if several +authentication mechanisms are tried, the user may be requested to enter the +same information multiple times. See {\vexample Example6} for a more complex +implementation of an authenticator, with caching support. + +If you want to use SASL (ie. if \emph{options.sasl} is set to \emph{true}), +your authenticator must inherit from +{\vcode vmime::security::sasl::SASLAuthenticator} or +{\vcode vmime::security::sasl::defaultSASLAuthenticator}, even if you do not +use the SASL-specific methods {\vcode getAcceptableMechanisms()} and +{\vcode setSASLMechanism()}. Have a look at {\vexample Example6} to see an +implementation of an SASL authenticator. + +\begin{lstlisting}[caption={A simple SASL authenticator}] +class mySASLAuthenticator : public vmime::security::sasl::defaultSASLAuthenticator { + + typedef vmime::security::sasl::SASLMechanism mechanism; // save us typing + + const std::vector <vmime::shared_ptr <mechanism> > getAcceptableMechanisms( + const std::vector <vmime::shared_ptr <mechanism> >& available, + const vmime::shared_ptr <mechanism>& suggested + ) const { + + // Here, you can sort the SASL mechanisms in the order they will be + // tried. If no SASL mechanism is acceptable (ie. for example, not + // enough secure), you can return an empty list. + // + // If you do not want to bother with this, you can simply return + // the default list, which is ordered by security strength. + return defaultSASLAuthenticator:: + getAcceptableMechanisms(available, suggested); + } + + void setSASLMechanism(const vmime::shared_ptr <mechanism>& mech) { + + // This is called when the authentication process is going to + // try the specified mechanism. + // + // The mechanism name is in mech->getName() + + defaultSASLAuthenticator::setSASLMechanism(mech); + } + + // ...implement getUsername() and getPassword()... +}; +\end{lstlisting} + + +% ============================================================================ +\section{Using transport service} + +You have two possibilities for giving message data to the service when you +want to send a message: + +\begin{itemize} +\item either you have a reference to a message (type {\vcode vmime::message}) +and you can simply call {\vcode send(msg)}; +\item or you only have raw message data (as a string, for example), and you +have to call the second overload of {\vcode send()}, which takes additional +parameters (corresponding to message envelope); +\end{itemize} + +The following example illustrates the use of a transport service to send a +message using the second method: + +\begin{lstlisting}[caption={Using a transport service}] +const vmime::string msgData = + "From: me@example.org \r\n" + "To: you@example.org \r\n" + "Date: Sun, Oct 30 2005 17:06:42 +0200 \r\n" + "Subject: Test \r\n" + "\r\n" + "Message body"; + +// Create a new session +vmime::utility::url url("smtp://example.com"); + +vmime::shared_ptr <vmime::net::session> sess = vmime::net::session::create(); + +// Create an instance of the transport service +vmime::shared_ptr <vmime::net::transport> tr = sess->getTransport(url); + +// Connect it +tr->connect(); + +// Send the message +vmime::utility::inputStreamStringAdapter is(msgData); + +vmime::mailbox from("me@example.org"); +vmime::mailboxList to; +to.appendMailbox(vmime::make_shared <vmime::mailbox>("you@example.org")); + +tr->send( + /* expeditor */ from, + /* recipient(s) */ to, + /* data */ is, + /* total length */ msgData.length() +); + +// We have finished using the service +tr->disconnect(); +\end{lstlisting} + +\vnote{Exceptions can be thrown at any time when using a service. For better +clarity, exceptions are not caught here, but be sure to catch them in your own +application to provide error feedback to the user.} + +If you use SMTP, you can enable authentication by setting some properties +on the session object ({\vcode service::setProperty()} is a shortcut for +setting properties on the session with the correct prefix): + +\begin{lstlisting} +tr->setProperty("options.need-authentication", true); +tr->setProperty("auth.username", "user"); +tr->setProperty("auth.password", "password"); +\end{lstlisting} + + +% ============================================================================ +\section{Using store service} + +\subsection{Connecting to a store} % ----------------------------------------- + +The first basic step for using a store service is to connect to it. The +following example shows how to initialize a session and instanciate the +store service: + +\begin{lstlisting}[caption={Connecting to a store service}] +// Create a new session +vmime::utility::url url("imap://vincent:password@imap:example.org"); + +vmime::shared_ptr <vmime::net::session> sess = vmime::net::session::create(); + +// Create an instance of the transport service +vmime::shared_ptr <vmime::net::store> store = sess->getStore(url); + +// Connect it +store->connect(); +\end{lstlisting} + +\vnote{{\vexample Example6} contains a more complete example for connecting +to a store service, with support for a custom authenticator.} + +\subsection{Opening a folder} % ---------------------------------------------- + +You can open a folder using two different access modes: either in +\emph{read-only} mode (where you can only read message flags and contents), or +in \emph{read-write} mode (where you can read messages, but also delete them +or add new ones). When you have a reference to a folder, simply call the +{\vcode open()} method with the desired access mode: + +\begin{lstlisting} +folder->open(vmime::net::folder::MODE_READ_WRITE); +\end{lstlisting} + +\vnote{Not all stores support the \emph{read-write} mode. By default, if the +\emph{read-write} mode is not available, the folder silently fall backs on +the \emph{read-only} mode, unless the \emph{failIfModeIsNotAvailable} argument +to {\vcode open()} is set to true.} + +Call {\vcode getDefaultFolder()} on the store to obtain a reference to the +default folder, which is usually the INBOX folder (where messages arrive when +they are received). + +You can also open a specific folder by specifying its path. The following +example will open a folder named \emph{bar}, which is a child of \emph{foo} +in the root folder: + +\begin{lstlisting}[caption={Opening a folder from its path}] +vmime::net::folder::path path; +path /= vmime::net::folder::path::component("foo"); +path /= vmime::net::folder::path::component("bar"); + +vmime::shared_ptr <vmime::net::folder> fld = store->getFolder(path); +fld->open(vmime::net::folder::MODE_READ_WRITE); +\end{lstlisting} + +\vnote{You can specify a path as a string as there is no way to get the +separator used to delimitate path components. Always use {\vcode operator/=} +or {\vcode appendComponent}.} + +\vnote{Path components are of type {\vcode vmime::word}, which means that +VMime supports folder names with extended characters, not only 7-bit +US-ASCII. However, be careful that this may not be supported by the +underlying store protocol (IMAP supports it, because it uses internally a +modified UTF-7 encoding).} + +\subsection{Fetching messages} % --------------------------------------------- + +You can fetch some information about a message without having to download the +whole message. Moreover, folders support fetching for multiple messages in +a single request, for better performance. The following items are currently +available for fetching: + +\begin{itemize} +\item {\bf envelope}: sender, recipients, date and subject; +\item {\bf structure}: MIME structure of the message; +\item {\bf content-info}: content-type of the root part; +\item {\bf flags}: message flags; +\item {\bf size}: message size; +\item {\bf header}: retrieve all the header fields of a message; +\item {\bf uid}: unique identifier of a message; +\item {\bf importance}: fetch header fields suitable for use with +{\vcode misc::importanceHelper}. +\end{itemize} + +\vnote{Not all services support all fetchable items. Call +{\vcode getFetchCapabilities()} on a folder to know which information can be +fetched by a service.} + +The following code shows how to list all the messages in a folder, and +retrieve basic information to show them to the user: + +\begin{lstlisting}[caption={Fetching information about multiple messages}] +std::vector <ref <vmime::net::message> > allMessages = + folder->getMessages(vmime::net::messageSet::byNumber(1, -1)); + // -1 is a special value to mean "the number of the last message in the folder" + +folder->fetchMessages( + allMessages, + vmime::net::fetchAttributes::FLAGS | + vmime::net::fetchAttributes::ENVELOPE +); + +for (unsigned int i = 0 ; i < allMessages.size() ; ++i) { + + vmime::shared_ptr <vmime::net::message> msg = allMessages[i]; + + const int flags = msg->getFlags(); + + std::cout << "Message " << i << ":" << std::endl; + + if (flags & vmime::net::message::FLAG_SEEN) { + std::cout << " - is read" << std::endl; + } + if (flags & vmime::net::message::FLAG_DELETED) { + std::cout << " - is deleted" << std::endl; + } + + vmime::shared_ptr <const vmime::header> hdr = msg->getHeader(); + + std::cout << " - sent on " << hdr->Date()->generate() << std::endl; + std::cout << " - sent by " << hdr->From()->generate() << std::endl; +} +\end{lstlisting} + +IMAP supports fetching specific header fields of a message. Here is how to use +the {\vcode fetchAttributes} object to do it: + +\begin{lstlisting}[caption={Using fetchAttributes object to fetch specific header fields of a message}] + +// Fetch message flags and the "Received" and "X-Mailer" header fields +vmime::net::fetchAttributes fetchAttribs; +fetchAttribs.add(vmime::net::fetchAttributes::FLAGS); +fetchAttribs.add("Received"); +fetchAttribs.add("X-Mailer"); + +folder->fetchMessages(allMessages, fetchAttribs); +\end{lstlisting} + + +\subsection{Extracting messages and parts} + +To extract the whole contents of a message (including headers), use the +{\vcode extract()} method on a {\vcode vmime::net::message} object. The +following example extracts the first message in the default folder: + +\begin{lstlisting}[caption={Extracting messages}] +// Get a reference to the folder and to its first message +vmime::shared_ptr <vmime::net::folder> folder = store->getDefaultFolder(); +vmime::shared_ptr <vmime::net::message> msg = folder->getMessage(1); + +// Write the message contents to the standard output +vmime::utility::outputStreamAdapter out(std::cout); +msg->extract(out); +\end{lstlisting} + +Some protocols (like IMAP) also support the extraction of specific MIME parts +of a message without downloading the whole message. This can save bandwidth +and time. The method {\vcode extractPart()} is used in this case: + +\begin{lstlisting}[caption={Extracting a specific MIME part of a message}] +// Fetching structure is required before extracting a part +folder->fetchMessage(msg, vmime::net::fetchAttributes::STRUCTURE); + +// Now, we can extract the part +msg->extractPart(msg->getStructure()->getPartAt(0)->getPartAt(1)); +\end{lstlisting} + +Suppose we have a message with the following structure: + +\begin{verbatim} + multipart/mixed + text/html + image/jpeg [*] +\end{verbatim} + +The previous example will extract the header and body of the \emph{image/jpeg} +part. + +\subsection{Deleting messages} % --------------------------------------------- + +The following example will delete the second and the third message from the +store. + +\begin{lstlisting}[caption={Deleting messages}] +vmime::shared_ptr <vmime::net::folder> folder = store->getDefaultFolder(); + +folder->deleteMessages(vmime::net::messageSet::byNumber(/* from */ 2, /* to */ 3)); + +// This is equivalent +std::vector <int> nums; +nums.push_back(2); +nums.push_back(3); +folder->deleteMessages(vmime::net::messageSet::byNumber(nums)); + +// This is also equivalent (but will require 2 roundtrips to server) +folder->deleteMessages(vmime::net::messageSet::byNumber(2)); +folder->deleteMessages(vmime::net::messageSet::byNumber(2)); // renumbered, 3 becomes 2 +\end{lstlisting} + +\subsection{Events} % -------------------------------------------------------- + +As a result of executing some operation (or from time to time, even if no +operation has been performed), a store service can send events to notify you +that something has changed (eg. the number of messages in a folder). These +events may allow you to update the user interface associated to a message +store. + +Currently, there are three types of event: + +\begin{itemize} +\item {\bf message change}: sent when the number of messages in a folder +has changed (ie. some messages have been added or removed); +\item {\bf message count change}: sent when one or more message(s) have +changed (eg. flags or deleted status); +\item {\bf folder change}: sent when a folder has been created, renamed or +deleted. +\end{itemize} + +You can register a listener for each event type by using the corresponding +methods on a {\vcode folder} object: {\vcode addMessageChangedListener()}, +{\vcode addMessageCountListener()} or {\vcode addFolderListener()}. For more +information, please read the class documentation for +{\vcode vmime::net::events} namespace. + + +% ============================================================================ +\section{Handling timeouts} + +Unexpected errors can occur while messaging services are performing +operations and waiting a response from the server (eg. server stops +responding, network link falls down). As all operations as synchronous, +they can be ``blocked'' a long time before returning (in fact, they loop +until they either receive a response from the server, or the underlying +socket system returns an error). + +VMime provides a mechanism to control the duration of operations. This +mechanism allows the program to cancel an operation that is currently +running. + +An interface called {\vcode timeoutHandler} is provided: + +\begin{lstlisting} +class timeoutHandler : public object { + + /** Called to test if the time limit has been reached. + * + * @return true if the timeout delay is elapsed + */ + virtual const bool isTimeOut() = 0; + + /** Called to reset the timeout counter. + */ + virtual void resetTimeOut() = 0; + + /** Called when the time limit has been reached (when + * isTimeOut() returned true). + * + * @return true to continue (and reset the timeout) + * or false to cancel the current operation + */ + virtual const bool handleTimeOut() = 0; +}; +\end{lstlisting} + +While the operation runs, the service calls {\vcode isTimeout()} at variable +intervals. If the {\vcode isTimeout()} function returns {\vcode true}, +then {\vcode handleTimeout()} is called. If the {\vcode handleTimeout()} +function returns {\vcode false}, the operation is cancelled and +an {\vcode operation\_timed\_out} exception is thrown. Else, if +{\vcode handleTimeout()} returns true, the operation continues and the +timeout counter is reset. +The function {\vcode resetTimeout()} is called each time data has +been received from the server to reset the timeout delay. + +When using a service, a default timeout handler is set: if an operation +is blocked for more than 30 seconds (ie. network link is down and no data +was received since 30 seconds), an {\vcode operation\_timed\_out} exception +is thrown. + +The following example shows how to implement a simple timeout handler: + +\begin{lstlisting}[caption={Implementing a simple timeout handler}] +class myTimeoutHandler : public vmime::net::timeoutHandler { + +public: + + myTimeoutHandler() { + + m_startTime = time(NULL); + } + + const bool isTimeOut() { + + return time(NULL) >= m_startTime + 30; // 30 seconds timeout + } + + void resetTimeOut() { + + m_startTime = time(NULL); + } + + const bool handleTimeOut() { + + std::cout << "Operation timed out." << std::endl; + << "Press [Y] to continue, or [N] to " + << "cancel the operation." << std::endl; + + std::string response; + std::cin >> response; + + return response == "y" || response == "Y"; + } + +private: + + time_t m_startTime; +}; +\end{lstlisting} + +To make the service use your timeout handler, you need to write a factory +class, to allow the service to create instances of the handler class. This +is required because the service can use several connections to the server +simultaneously, and each connection needs its own timeout handler. + +\begin{lstlisting} +class myTimeoutHandlerFactory : public vmime::net::timeoutHandlerFactory { + +public: + + ref <timeoutHandler> create() { + + return vmime::make_shared <myTimeoutHandler>(); + } +}; +\end{lstlisting} + +Then, call the {\vcode setTimeoutHandlerFactory()} method on the service object +to set the timeout handler factory to use during the session: + +\begin{lstlisting} +theService->setTimeoutHandlerFactory(vmime::make_shared <myTimeoutHandlerFactory>()); +\end{lstlisting} + + +% ============================================================================ +\newpage +\section{Secured connection using TLS/SSL} + +\subsection{Introduction} % -------------------------------------------------- + +If you have enabled TLS support in VMime, you can configure messaging services +so that they use a secured connection. + +Quoting from RFC-2246 - the TLS 1.0 protocol specification: \emph{`` The TLS +protocol provides communications privacy over the Internet. The protocol +allows client/server applications to communicate in a way that is designed +to prevent eavesdropping, tampering, or message forgery.''} + +TLS has the following advantages: + +\begin{itemize} +\item authentication: server identity can be verified; +\item privacy: transmission of data between client and server cannot be read +by someone in the middle of the connection; +\item integrity: original data which is transferred between a client and a +server can not be modified by an attacker without being detected. +\end{itemize} + +\vnote{What is the difference between SSL and TLS? SSL is a protocol designed +by Netscape. TLS is a standard protocol, and is partly based on version 3 of +the SSL protocol. The two protocols are not interoperable, but TLS does +support a mechanism to back down to SSL 3.} + +VMime offers two possibilities for using a secured connection: + +\begin{itemize} +\item you can connect to a server listening on a special port (eg. IMAPS +instead of IMAP): this is the classical use of SSL, but is now deprecated; +\item connect to a server listening on the default port, and then begin a +secured connection: this is STARTTLS. +\end{itemize} + + +\subsection{Setting up a secured connection} % ------------------------------- + +\subsubsection{Connecting to a ``secured'' port} % ........................... + +To use the classical SSL/TLS way, simply use the ``S'' version of the protocol +to connect to the server (eg. \emph{imaps} instead of \emph{imap}). This is +currently available for SMTP, POP3 and IMAP. + +\begin{lstlisting} +vmime::shared_ptr <vmime::net::store> store = + theSession->getStore(vmime::utility::url("imaps://example.org")); +\end{lstlisting} + +\subsubsection{Using STARTTLS} % ............................................. + +To make the service start a secured session using the STARTTLS method, simply +set the \emph{connection.tls} property: + +\begin{lstlisting} +theService->setProperty("connection.tls", true); +\end{lstlisting} + +\vnote{If, for some reason, a secured connection cannot be started, the +default behaviour is to fallback on a normal connection. To make +{\vcode connect()} fail if STARTTLS fails, set the +\emph{connection.tls.required} to \emph{true}.} + +\subsection{Certificate verification} % -------------------------------------- + +\subsubsection{How it works} % ............................................... + +If you tried the previous examples, a +{\vcode certificateException} might have been thrown. +This is because the default certificate verifier in VMime did not manage to +verify the certificate, and so could not trust it. + +Basically, when you connect to a server using TLS, the server responds with +a list of certificates, called a certificate chain (usually, certificates are +of type X.509\footnote{And VMime currently supports only X.509 certificates}). +The certificate chain is ordered so that the first certificate is the subject +certificate, the second is the subject's issuer one, the third is the issuer's +issuer, and so on. + +To decide whether the server can be trusted or not, you have to verify that +\emph{each} certificate is valid (ie. is trusted). For more information +about X.509 and certificate verification, see related articles on Wikipedia +\footnote{See \url{http://wikipedia.org/wiki/Public\_key\_certificate}}. + +\subsubsection{Using the default certificate verifier} % ..................... + +The default certificate verifier maintains a list of root (CAs) and user +certificates that are trusted. By default, the list is empty. So, you have +to initialize it before using the verifier. + +The algorithm\footnote{See +\url{http://wikipedia.org/wiki/Certification\_path\_validation\_algorithm}} +used is quite simple: + +\begin{enumerate} +\item for every certificate in the chain, verify that the certificate has been +issued by the next certificate in the chain; +\item for every certificate in the chain, verify that the certificate is valid +at the current time; +\item ensure that the first certificate's subject name matches the hostname +of the server; +\item decide whether the subject's certificate can be trusted: + \begin{itemize} + \item first, verify that the the last certificate in the chain was + issued by a third-party that we trust (root CAs); + \item if the issuer certificate cannot be verified against root CAs, + compare the subject's certificate against the trusted certificates + (the certificates the user has decided to trust). + \end{itemize} +\end{enumerate} + +First, we need some code to load existing X.509 certificates: + +\begin{lstlisting}[caption={Reading a X.509 certificate from a file}] +vmime::shared_ptr <vmime::security::cert::X509Certificate> + loadX509CertificateFromFile(const std::string& path) { + + std::ifstream certFile; + certFile.open(path.c_str(), std::ios::in | std::ios::binary); + + if (!certFile) { + // ...handle error... + } + + vmime::utility::inputStreamAdapter is(certFile); + vmime::shared_ptr <vmime::security::cert::X509Certificate> cert; + + cert = vmime::security::cert::X509Certificate::import(is); + + return cert; +} +\end{lstlisting} + +Then, we can use the {\vcode loadX509CertificateFromFile} function to load +certificates and initialize the certificate verifier: + +\begin{lstlisting}[caption={Using the default certificate verifier}] +vmime::shared_ptr <vmime::security::cert::defaultCertificateVerifier> vrf = + vmime::make_shared <vmime::security::cert::defaultCertificateVerifier>(); + +// Load root CAs (such as Verisign or Thawte) +std::vector <vmime::shared_ptr <vmime::security::cert::X509Certificate> > rootCAs; + +rootCAs.push_back(loadX509CertificateFromFile("/path/to/root-ca1.cer"); +rootCAs.push_back(loadX509CertificateFromFile("/path/to/root-ca2.cer"); +rootCAs.push_back(loadX509CertificateFromFile("/path/to/root-ca3.cer"); + +vrf->setX509RootCAs(rootCAs); + +// Then, load certificates that the user explicitely chose to trust +std::vector <vmime::shared_ptr <vmime::security::cert::X509Certificate> > trusted; + +trusted.push_back(loadX509CertificateFromFile("/path/to/trusted-site1.cer"); +trusted.push_back(loadX509CertificateFromFile("/path/to/trusted-site2.cer"); + +vrf->setX509TrustedCerts(trusted); +\end{lstlisting} + + +\subsubsection{Writing your own certificate verifier} % ...................... + +If you need to do more complex verifications on certificates, you will have to +write your own verifier. Your verifier should inherit from the +{\vcode vmime::security::cert::certificateVerifier} class and implement the +method {\vcode verify()}. Then, if the specified certificate chain is trusted, +simply return from the function, or else throw a +{\vcode certificateException}. + +The following example shows how to implement an interactive certificate +verifier which relies on the user's decision, and nothing else (you SHOULD NOT +use this in a production application as this is obviously a serious security +issue): + +\begin{lstlisting}[caption={A custom certificate verifier}] +class myCertVerifier : public vmime::security::cert::certificateVerifier { + +public: + + void verify(const vmime::shared_ptr <certificateChain>& certs) { + + // Obtain the subject's certificate + vmime::shared_ptr <vmime::security::cert::certificate> cert = chain->getAt(0); + + std::cout << std::endl; + std::cout << "Server sent a '" << cert->getType() << "'" + << " certificate." << std::endl; + std::cout << "Do you want to accept this certificate? (Y/n) "; + std::cout.flush(); + + std::string answer; + std::getline(std::cin, answer); + + if (answer.length() != 0 && (answer[0] == 'Y' || answer[0] == 'y')) { + return; // OK, we trust the certificate + } + + // Don't trust this certificate + throw vmime::security::cert::certificateException(); + } +}; +\end{lstlisting} + +\vnote{In production code, it may be a good idea to remember user's decisions +about which certificates to trust and which not. See {\vexample Example6} for +a basic cache implementation.} + +Finally, to make the service use your own certificate verifier, simply write: + +\begin{lstlisting} +theService->setCertificateVerifier(vmime::make_shared <myCertVerifier>()); +\end{lstlisting} + +\subsection{SSL/TLS Properties} % -------------------------------------------- + +If you want to customize behavior or set some options on TLS/SSL connection, +you may use the TLSProperties object, and pass it to the service session. The +TLS/SSL options must be set {\em before} creating any service with the session +(ie. before calling either {\vcode getStore()} or {\vcode getTransport()} on +the session), or they will not be used. + +The following example shows how to set the cipher suite preferences for TLS: + +\begin{lstlisting}[caption={Setting TLS cipher suite preferences}] +vmime::shared_ptr <vmime::net::session> sess = /* ... */; + +vmime::shared_ptr <vmime::net::tls::TLSProperties> tlsProps = + vmime::make_shared <vmime::net::tls::TLSProperties>(); + +// for OpenSSL +tlsProps->setCipherString("HIGH:!ADH:@STRENGTH"); + +// for GNU TLS +tlsProps->setCipherString("NORMAL:%SSL3_RECORD_VERSION"); + +sess->setTLSProperties(tlsProps); +\end{lstlisting} + +Please note that the cipher suite string format and meaning depend on the +underlying TLS library (either OpenSSL or GNU TLS): + +\begin{itemize} +\item for GNU TLS, read this: \newline +\url{http://gnutls.org/manual/html\_node/Priority-Strings.html} + +\item for OpenSSL, read this: \newline +\url{http://www.openssl.org/docs/apps/ciphers.html#CIPHER\_STRINGS} +\end{itemize} + +You may also set cipher suite preferences using predefined constants that +map to generic security modes: + +\begin{lstlisting}[caption={Setting TLS cipher suite preferences using predefined modes}] +sess->setCipherSuite(vmime::net::tls::TLSProperties::CIPHERSUITE_HIGH); +\end{lstlisting} + +The following constants are available: + +\noindent\begin{tabularx}{1.0\textwidth}{|l|X|} +\hline + {\bf Constant} & + {\bf Meaning} \\ +\hline + CIPHERSUITE\_HIGH & + High encryption cipher suites ($>$ 128 bits) \\ +\hline + CIPHERSUITE\_MEDIUM & + Medium encryption cipher suites ($>=$ 128 bits) \\ +\hline + CIPHERSUITE\_LOW & + Low encryption cipher suites ($>=$ 64 bits) \\ +\hline + CIPHERSUITE\_DEFAULT & + Default cipher suite (actual cipher suites used depends + on the underlying SSL/TLS library) \\ +\hline +\end{tabularx} + + +% ============================================================================ +\section{Tracing connection} + +Connection tracing is used to log what is sent and received on the wire +between the client and the server, and may help debugging. + +First, you have to create your own tracer, which must implement the +{\vcode vmime::net::tracer} interface. Here is an example of a tracer which +simply logs to the standard output: + +\begin{lstlisting}[caption={A simple tracer}] +class myTracer : public vmime::net::tracer { + +public: + + myTracer(const vmime::string& proto, const int connectionId) + : m_proto(proto), + m_connectionId(connectionId) { + + } + + // Called by VMime to trace what is sent on the socket + void traceSend(const vmime::string& line) { + + std::cout << "[" << m_proto << ":" << m_connectionId + << "] C: " << line << std::endl; + } + + // Called by VMime to trace what is received from the socket + void traceReceive(const vmime::string& line) { + + std::cout << "[" < < m_proto << ":" << m_connectionId + << "] S: " << line << std::endl; + } + +private: + + const vmime::string m_proto; + const int m_connectionId; +}; +\end{lstlisting} + +Also create a factory class, used to instanciate your tracer objects: + +\begin{lstlisting} +class myTracerFactory : public vmime::net::tracerFactory { + +public: + + vmime::shared_ptr <vmime::net::tracer> create( + const vmime::shared_ptr <vmime::net::service>& serv, + const int connectionId + ) { + + return vmime::make_shared <myTracer>( + serv->getProtocolName(), connectionId + ); + } +}; +\end{lstlisting} + +Next, we have to tell VMime to use it. When you create your service +(either store or transport), simply call the {\vcode setTracerFactory} +on the service and pass an instance of your factory class: + +\begin{lstlisting}[caption={Enabling tracer on a connection}] +vmime::shared_ptr <vmime::net::transport> store = + session->getStore("imaps://user:password@imap.myserver.com"); + +// Enable tracing communication between client and server +store->setTracerFactory(vmime::make_shared <myTracerFactory>()); +\end{lstlisting} + +That's all! Now, everything which is sent on/received from the socket +will be logged using your tracer object. Here is an example of a trace +session for IMAP: + +\begin{verbatim} +[imaps:1] S: * OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR + LOGIN-REFERRALS ID ENABLE IDLE AUTH=PLAIN] Dovecot ready. +[imaps:1] C: a001 AUTHENTICATE PLAIN +[imaps:1] S: + +[imaps:1] C: {...SASL exchange: 52 bytes of data...} +[imaps:1] S: a001 OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR + LOGIN-REFERRALS ID ENABLE IDLE SORT SPECIAL-USE QUOTA] Logged in +[imaps:1] C: a002 LIST "" "" +[imaps:1] S: * LIST (\Noselect) "." "" +[imaps:1] S: a002 OK List completed. +[imaps:1] C: a003 CAPABILITY +[imaps:1] S: * CAPABILITY IMAP4rev1 LITERAL+ SASL-IR + LOGIN-REFERRALS ID ENABLE IDLE SORT SPECIAL-USE QUOTA +[imaps:1] S: a003 OK Capability completed. +[imaps:1] C: a003 SELECT INBOX (CONDSTORE) +[imaps:1] S: * FLAGS (\Answered \Flagged \Deleted \Seen \Draft + $NotJunk NonJunk JunkRecorded $MDNSent NotJunk $Forwarded + Junk $Junk Forwarded $MailFlagBit1) +[imaps:1] S: * OK [PERMANENTFLAGS (\Answered \Flagged \Deleted + \Seen \Draft $NotJunk NonJunk JunkRecorded $MDNSent NotJunk + $Forwarded Junk $Junk Forwarded $MailFlagBit1 \*)] + Flags permitted. +[imaps:1] S: * 104 EXISTS +[imaps:1] S: * 0 RECENT +[imaps:1] S: * OK [UNSEEN 6] First unseen. +[imaps:1] S: * OK [UIDVALIDITY 1268127585] UIDs valid +[imaps:1] S: * OK [UIDNEXT 32716] Predicted next UID +[imaps:1] S: * OK [HIGHESTMODSEQ 148020] Highest +[imaps:1] S: a003 OK [READ-WRITE] Select completed. +\end{verbatim} + +Please note that no sensitive data (ie. login or password) will be traced. +Same, {\em blob} data such as message content or SASL exchanges will be logged +as a marker which indicates how many bytes were sent/received (eg. "{...SASL +exchange: 52 bytes of data...}""). diff --git a/vmime-master/doc/book/start.tex b/vmime-master/doc/book/start.tex new file mode 100644 index 0000000..f169330 --- /dev/null +++ b/vmime-master/doc/book/start.tex @@ -0,0 +1,111 @@ +\chapter{Getting Started} + +% ============================================================================ +\section{Using VMime in your programs} + +First, make sure you have successfully compiled and installed VMime using the +instructions described in Chapter \ref{chapter_building}. To use VMime in your +program, you simply have to include VMime headers: + +\begin{lstlisting} +#include <vmime/vmime.hpp> +\end{lstlisting} + +\vnote{for versions older than 0.6.1, include $<$vmime/vmime$>$.} + +As of version 0.6.1, VMime uses {\vcode pkg-config} to simplify compiling and +linking with VMime. The {\vcode pkg-config} utility is used to detect the +appropriate compiler and linker flags needed for a library. + +You can simply build your program with: + +\begin{verbatim} + $ g++ `pkg-config --cflags --libs vmime` -static -o myprog myprog.cpp +\end{verbatim} + +to use the static version, or with: + +\begin{verbatim} + $ g++ `pkg-config --cflags vmime` -o myprog myprog.cpp `pkg-config --libs vmime` +\end{verbatim} + +to use the shared version. + +\vnote{it is highly recommended that you link your program against the shared +version of the library.} + +All VMime classes and global functions are defined in the namespace +{\vcode vmime}, so prefix explicitely all your declarations which use VMime +with {\vcode vmime::}, or import the {\vcode vmime} namespace into the global +namespace with the C++ keywork {\vcode using} (not recommended, though). + + +% ============================================================================ +\section{If you can not (or do not want to) use {\vcode pkg-config}} + +{\bf Linking with the shared library (.so):} compile your program with the +{\vcode -lvmime} flag. You can use the -L path flag if the library file is +not in a standard path (ie. not in /usr/lib or /usr/local/lib). + +\vnote{if you want to link your program with the shared version of VMime +library, make sure the library has been compiled using CMake build system +({\vcode make}, then {\vcode make install}). When you compile with SCons, +only the static library is built and installed.} + +{\bf Linking with the static library (.a):} follow the same procedure as for +shared linking and append the flag -static to force static linking. Although +static linking is possible, you are encouraged to use the shared (dynamic) +version of the library. + + +% ============================================================================ +\section{Platform-dependent code} + +While the most part of VMime code is pure ANSI C++, there are some features +that are platform-specific: file management (opening/reading/writing files), +network code (socket, DNS resolution) and time management. All the +non-portable stuff is done by a bridge object called a platform handler (see +{\vcode vmime::platform}). + +If your platform is POSIX-compatible (eg. GNU/Linux, *BSD) or is Windows, +then you are lucky: VMime has built-in support for these platforms. If not, +don't worry, the sources of the built-in platform handlers are very well +documented, so writing you own should not be very difficult. + +If your VMime version is $<=$ 0.9.1, you should tell VMime which platform +handler you want to use at the beginning of your program (before using +\emph{any} VMime object, or calling \emph{any} VMime global function). + +So, if your platform is POSIX, your program should look like this: + +\begin{lstlisting}[caption={Initializing VMime and the platform handler}] +#include <vmime/vmime.hpp> +#include <vmime/platforms/posix/posixHandler.hpp> + +int main() { + + vmime::platform:: + setHandler <vmime::platforms::posix::posixHandler>(); + + // Now, you can use VMime + // ...do what you want, it's your program... +} +\end{lstlisting} + +For using VMime on Windows, include +{\vcode vmime/platforms/windows/windowsHandler.hpp} and use the following line +to initialize the platform handler: + +\begin{lstlisting} +vmime::platform:: + setHandler <vmime::platforms::windows::windowsHandler>(); +\end{lstlisting} + +\vnote{since version 0.9.2, this is not needed any more: the platform +handler is installed automatically using the platform detected during the +build configuration.} + +\vnote{since version 0.8.1, {\vcode vmime::platformDependant} was renamed +to {\vcode vmime::platform}. The old name has been kept for compatibility +but it is recommended that you update your code, if needed.} + |