
ferencd@0: \chapter{Working with Messaging Services}
ferencd@0: 
ferencd@0: % ============================================================================
ferencd@0: \section{Introduction}
ferencd@0: 
ferencd@0: In addition to parsing and building MIME messages, VMime also offers a lot of
ferencd@0: features to work with messaging services. This includes connecting to remote
ferencd@0: messaging stores (like IMAP or POP3), local stores (maildir) and transport
ferencd@0: services (send messages over SMTP or local sendmail), through an unified
ferencd@0: interface (see Figure \ref{uml_messaging_module}). That means that you can
ferencd@0: use independently IMAP of POP3 without having to change any line of code.
ferencd@0: 
ferencd@0: Source code of {\vexample Example6} covers all features presented in this
ferencd@0: chapter, so it is important you take some time to read it.
ferencd@0: 
ferencd@0: \begin{figure}
ferencd@0: 	\center\includegraphics[width=0.9\textwidth]
ferencd@0: 		{images/messaging-services.png}\endcenter
ferencd@0: 	\caption{Overall structure of the messaging module}
ferencd@0: 	\label{uml_messaging_module}
ferencd@0: \end{figure}
ferencd@0: 
ferencd@0: The interface is composed of five classes:
ferencd@0: 
ferencd@0: \begin{itemize}
ferencd@0: \item {\vcode vmime::net::service}: this is the base interface for a
ferencd@0: messaging service. It can be either a store service or a transport
ferencd@0: service.
ferencd@0: 
ferencd@0: \item {\vcode vmime::net::serviceFactory}: create instances of a service.
ferencd@0: This is used internally by the session object (see below).
ferencd@0: 
ferencd@0: \item {\vcode vmime::net::store}: interface for a store service. A store
ferencd@0: service offers access to a set of folders containing messages. This is
ferencd@0: used for IMAP, POP3 and maildir.
ferencd@0: 
ferencd@0: \item {\vcode vmime::net::transport}: interface for a transport service.
ferencd@0: A transport service is capable of sending messages. This is used for
ferencd@0: SMTP and sendmail.
ferencd@0: 
ferencd@0: \item {\vcode vmime::net::session}: a session object is used to store the
ferencd@0: parameters used by a service (eg. connection parameters). Each service
ferencd@0: instance is associated with only one session. The session object is capable
ferencd@0: of creating instances of services.
ferencd@0: \end{itemize}
ferencd@0: 
ferencd@0: The following classes are specific to store services:
ferencd@0: 
ferencd@0: \begin{itemize}
ferencd@0: \item {\vcode vmime::net::folder}: a folder can either contain other folders
ferencd@0: or messages, or both.
ferencd@0: 
ferencd@0: \item {\vcode vmime::net::message}: this is the interface for dealing with
ferencd@0: messages. For a given message, you can have access to its flags, its MIME
ferencd@0: structure and you can also extract the whole message data or given parts (if
ferencd@0: supported by the underlying protocol).
ferencd@0: \end{itemize}
ferencd@0: 
ferencd@0: 
ferencd@0: % ============================================================================
ferencd@0: \section{Working with sessions}
ferencd@0: 
ferencd@0: \subsection{Setting properties} % --------------------------------------------
ferencd@0: 
ferencd@0: Sessions are used to store configuration parameters for services. They
ferencd@0: contains a set of typed properties that can modify the behaviour of the
ferencd@0: services. Before using a messaging service, you must create and
ferencd@0: initialize a session object:
ferencd@0: 
ferencd@0: \begin{lstlisting}
ferencd@0: vmime::shared_ptr <net::session> theSession = vmime::make_shared <net::session>();
ferencd@0: \end{lstlisting}
ferencd@0: 
ferencd@0: Session properties include:
ferencd@0: 
ferencd@0: \begin{itemize}
ferencd@0: \item connection parameters: host and port to connect to;
ferencd@0: \item authentication parameters: user credentials required to use the
ferencd@0: service (if any);
ferencd@0: \item protocol-specific parameters: enable or disable extensions (eg. APOP
ferencd@0: support in POP3).
ferencd@0: \end{itemize}
ferencd@0: 
ferencd@0: Properties are stored using a dotted notation, to specify the service type,
ferencd@0: the protocol name, the category and the name of the property:
ferencd@0: 
ferencd@0: \begin{verbatim}
ferencd@0:    {service_type}.{protocol}.category.name
ferencd@0: \end{verbatim}
ferencd@0: 
ferencd@0: An example of property is \emph{store.pop3.options.apop} (used to enable or
ferencd@0: disable the use of APOP authentication). The \emph{store.pop3} part is called
ferencd@0: the \emph{prefix}. This allow specifying different values for the same
ferencd@0: property depending on the protocol used.
ferencd@0: 
ferencd@0: The session properties are stored in a {\vcode vmime::propertySet} object.
ferencd@0: To set the value of a property, you can use either:
ferencd@0: 
ferencd@0: \begin{lstlisting}
ferencd@0: theSession->getProperties().setProperty("property-name", value);
ferencd@0: \end{lstlisting}
ferencd@0: 
ferencd@0: or:
ferencd@0: 
ferencd@0: \begin{lstlisting}
ferencd@0: theSession->getProperties()["property-name"] = value;
ferencd@0: \end{lstlisting}
ferencd@0: 
ferencd@0: 
ferencd@0: \subsection{Available properties} % ------------------------------------------
ferencd@0: 
ferencd@0: Following is a list of available properties and the protocols they apply to,
ferencd@0: as the time of writing this documentation\footnote{You can get an up-to-date
ferencd@0: list of the properties by running \vexample{Example7}}. For better clarity,
ferencd@0: the prefixes do not appear in this table.
ferencd@0: 
ferencd@0: \begin{table}[!ht]
ferencd@0: \noindent\begin{tabularx}{1.0\textwidth}{|l|c|X|c|c|c|c|c|c|c|c|}
ferencd@0: \hline
ferencd@0: 	{\bf Property name} &
ferencd@0: 	{\bf Type} &
ferencd@0: 	{\bf Description} &
ferencd@0: 	\verti{\bf POP3} &
ferencd@0: 	\verti{\bf POP3S} &
ferencd@0: 	\verti{\bf IMAP} &
ferencd@0: 	\verti{\bf IMAPS} &
ferencd@0: 	\verti{\bf SMTP} &
ferencd@0: 	\verti{\bf SMTPS} &
ferencd@0: 	\verti{\bf maildir} &
ferencd@0: 	\verti{\bf sendmail} \\
ferencd@0: \hline
ferencd@0: \hline
ferencd@0: options.sasl & bool & Set to {\vcode true} to use SASL authentication, if
ferencd@0: available. & \vdot & \vdot & \vdot & \vdot & \vdot & \vdot & & \\
ferencd@0: \hline
ferencd@0: options.sasl.fallback & bool & Fail if SASL authentication failed (do not
ferencd@0: try other authentication mechanisms). & \vdot & \vdot & \vdot & \vdot &
ferencd@0: \vdot & \vdot & & \\
ferencd@0: \hline
ferencd@0: auth.username\footnote{You should use authenticators
ferencd@0: instead.\label{fn_auth_username}} & string & Set the username of the account
ferencd@0: to connect to. & \vdot & \vdot & \vdot & \vdot & \vdot & \vdot & & \\
ferencd@0: \hline
ferencd@0: auth.password\footref{fn_auth_username} & string & Set the password of the
ferencd@0: account. & \vdot & \vdot & \vdot & \vdot & \vdot & \vdot & & \\
ferencd@0: \hline
ferencd@0: connection.tls & bool & Set to {\vcode true} to start a secured connection
ferencd@0: using STARTTLS extension, if available. & \vdot & & \vdot & & \vdot & & & \\
ferencd@0: \hline
ferencd@0: connection.tls.required & bool & Fail if a secured connection cannot be
ferencd@0: started. & \vdot & & \vdot & & \vdot & & & \\
ferencd@0: \hline
ferencd@0: server.address & string & Server host name or IP address. &\vdot & \vdot &
ferencd@0: \vdot & \vdot & \vdot & \vdot & & \\
ferencd@0: \hline
ferencd@0: server.port & int & Server port. & \vdot & \vdot & \vdot & \vdot &
ferencd@0: \vdot & \vdot & & \\
ferencd@0: \hline
ferencd@0: server.rootpath & string & Root directory for mail repository (eg.
ferencd@0: \emph{/home/vincent/Mail}). & & & & & & & \vdot & \\
ferencd@0: \hline
ferencd@0: \end{tabularx}
ferencd@0: \caption{Properties common to all protocols}
ferencd@0: \end{table}
ferencd@0: 
ferencd@0: \newpage
ferencd@0: These are the protocol-specific options:
ferencd@0: 
ferencd@0: \begin{table}[!ht]
ferencd@0: \noindent\begin{tabularx}{1.0\textwidth}{|l|c|X|}
ferencd@0: \hline
ferencd@0: 	{\bf Property name} &
ferencd@0: 	{\bf Type} &
ferencd@0: 	{\bf Description} \\
ferencd@0: % POP3/POP3S
ferencd@0: \hline
ferencd@0: \multicolumn{3}{|c|}{POP3, POP3S} \\
ferencd@0: \hline
ferencd@0: store.pop3.options.apop & bool & Enable or disable authentication with
ferencd@0: APOP (if SASL is enabled, this occurs after all SASL mechanisms have been
ferencd@0: tried). \\
ferencd@0: \hline
ferencd@0: store.pop3.options.apop.fallback & bool & If set to {\vcode true} and
ferencd@0: APOP fails, the authentication process fails (ie. unsecure plain text
ferencd@0: authentication is not used). \\
ferencd@0: \hline
ferencd@0: % SMTP
ferencd@0: \multicolumn{3}{|c|}{SMTP, SMTPS} \\
ferencd@0: \hline
ferencd@0: transport.smtp.options.need-authentication & bool & Set to \emph{true} if
ferencd@0: the server requires to authenticate before sending messages. \\
ferencd@0: \hline
ferencd@0: transport.smtp.options.pipelining & bool & Set to {\vcode false} to disable
ferencd@0: command pipelining, if the server supports it (default is {\vcode true}). \\
ferencd@0: \hline
ferencd@0: transport.smtp.options.chunking & bool & Set to {\vcode false} to disable
ferencd@0: CHUNKING extension, if the server supports it (default is {\vcode true}). \\
ferencd@0: \hline
ferencd@0: % sendmail
ferencd@0: \multicolumn{3}{|c|}{sendmail} \\
ferencd@0: \hline
ferencd@0: transport.sendmail.binpath & string & The path to the \emph{sendmail}
ferencd@0: executable on your system. The default is the one found by the configuration
ferencd@0: script when VMime was built. \\
ferencd@0: \hline
ferencd@0: \end{tabularx}
ferencd@0: \caption{Protocol-specific options}
ferencd@0: \end{table}
ferencd@0: 
ferencd@0: 
ferencd@0: \subsection{Instanciating services} % ----------------------------------------
ferencd@0: 
ferencd@0: You can create a service either by specifying its protocol name, or by
ferencd@0: specifying the URL of the service. Creation by name is deprecated so
ferencd@0: this chapter only presents the latter option.
ferencd@0: 
ferencd@0: The URL scheme for connecting to services is:
ferencd@0: 
ferencd@0: \begin{verbatim}
ferencd@0:    protocol://[username[:password]@]host[:port]/[root-path]
ferencd@0: \end{verbatim}
ferencd@0: 
ferencd@0: \vnote{For local services (ie. \emph{sendmail} and \emph{maildir}), the host
ferencd@0: part is not used, but it must not be empty (you can use "localhost").}
ferencd@0: 
ferencd@0: The following table shows an example URL for each service:
ferencd@0: 
ferencd@0: \noindent\begin{tabularx}{1.0\textwidth}{|c|X|}
ferencd@0: \hline
ferencd@0: 	{\bf Service} &
ferencd@0: 	{\bf Connection URL} \\
ferencd@0: \hline
ferencd@0: imap, imaps & {\tt imap://imap.example.com},
ferencd@0: {\tt imaps://vincent:pass@example.com} \\
ferencd@0: \hline
ferencd@0: pop3, pop3s & {\tt pop3://pop3.example.com} \\
ferencd@0: \hline
ferencd@0: smtp, smtps & {\tt smtp://smtp.example.com} \\
ferencd@0: \hline
ferencd@0: maildir & {\tt maildir://localhost/home/vincent/Mail} (host not used) \\
ferencd@0: \hline
ferencd@0: sendmail & {\tt sendmail://localhost} (host not used, always localhost) \\
ferencd@0: \hline
ferencd@0: \end{tabularx}
ferencd@0: 
ferencd@0: \newpage
ferencd@0: 
ferencd@0: When you have the connection URL, instanciating the service is quite simple.
ferencd@0: Depending on the type of service, you will use either {\vcode getStore()} or
ferencd@0: {\vcode getTransport()}. For example, for store services, use:
ferencd@0: 
ferencd@0: \begin{lstlisting}
ferencd@0: vmime::utility:url url("imap://user:pass@imap.example.com");
ferencd@0: vmime::shared_ptr <vmime::net::store> st = sess->getStore(url);
ferencd@0: \end{lstlisting}
ferencd@0: 
ferencd@0: and for transport services:
ferencd@0: 
ferencd@0: \begin{lstlisting}
ferencd@0: vmime::utility:url url("smtp://smtp.example.com");
ferencd@0: vmime::shared_ptr <vmime::net::transport> tr = sess->getTransport(url);
ferencd@0: \end{lstlisting}
ferencd@0: 
ferencd@0: 
ferencd@0: % ============================================================================
ferencd@0: \section{User credentials and authenticators}
ferencd@0: 
ferencd@0: Some services need some user credentials (eg. username and password) to open
ferencd@0: a session. In VMime, user credentials can be specified in the session
ferencd@0: properties or by using a custom authenticator (callback).
ferencd@0: 
ferencd@0: \begin{lstlisting}[caption={Setting user credentials using session
ferencd@0: properties}]
ferencd@0: vmime::shared_ptr <vmime::net::session> sess;  // Suppose we have a session
ferencd@0: 
ferencd@0: sess->getProperties()["store.imap.auth.username"] = "vincent";
ferencd@0: sess->getProperties()["store.imap.auth.password"] = "my-password";
ferencd@0: \end{lstlisting}
ferencd@0: 
ferencd@0: Although not recommended, you can also specify username and password
ferencd@0: directly in the connection URL,
ferencd@0: ie: \emph{imap://username:password@imap.example.com/}. This works only for
ferencd@0: services requiring an username and a password as user credentials, and no
ferencd@0: other information.
ferencd@0: 
ferencd@0: Sometimes, it may not be very convenient to set username/password in the
ferencd@0: session properties, or not possible (eg. extended SASL mechanisms) . That's
ferencd@0: why VMime offers an alternate way of getting user credentials: the
ferencd@0: {\vcode authenticator} object. Basically, an authenticator is an object that
ferencd@0: can return user credentials on-demand (like a callback).
ferencd@0: 
ferencd@0: Currently, there are two types of authenticator in VMime: a basic
ferencd@0: authenticator (class {\vcode vmime::security::authenticator}) and, if SASL
ferencd@0: support is enabled, a SASL authenticator
ferencd@0: (class {\vcode vmime::security::sasl::SASLAuthenticator}). Usually, you
ferencd@0: should use the default implementations, or at least make your own
ferencd@0: implementation inherit from them.
ferencd@0: 
ferencd@0: The following example shows how to use a custom authenticator to request
ferencd@0: the user to enter her/his credentials:
ferencd@0: 
ferencd@0: \begin{lstlisting}[caption={A simple interactive authenticator}]
ferencd@0: class myAuthenticator : public vmime::security::defaultAuthenticator
ferencd@0: {
ferencd@0:    const string getUsername() const
ferencd@0:    {
ferencd@0:       std::cout << "Enter your username: " << std::endl;
ferencd@0: 
ferencd@0:       vmime::string res;
ferencd@0:       std::getline(std::cin, res);
ferencd@0: 
ferencd@0:       return res;
ferencd@0:    }
ferencd@0: 
ferencd@0:    const string getPassword() const
ferencd@0:    {
ferencd@0:       std::cout << "Enter your password: " << std::endl;
ferencd@0: 
ferencd@0:       vmime::string res;
ferencd@0:       std::getline(std::cin, res);
ferencd@0: 
ferencd@0:       return res;
ferencd@0:    }
ferencd@0: };
ferencd@0: \end{lstlisting}
ferencd@0: 
ferencd@0: This is how to use it:
ferencd@0: 
ferencd@0: \begin{lstlisting}
ferencd@0: // First, create a session
ferencd@0: vmime::shared_ptr <vmime::net::session> sess =
ferencd@0:    vmime::make_shared <vmime::net::session>();
ferencd@0: 
ferencd@0: // Next, initialize a service which will use our authenticator
ferencd@0: vmime::shared_ptr <vmime::net::store> st =
ferencd@0:    sess->getStore(vmime::utility::url("imap://imap.example.com"),
ferencd@0:       /* use our authenticator */ vmime::make_shared <myAuthenticator>());
ferencd@0: \end{lstlisting}
ferencd@0: 
ferencd@0: \vnote{An authenticator object should be used with one and only one service
ferencd@0: at a time. This is required because the authentication process may need to
ferencd@0: retrieve the service name (SASL).}
ferencd@0: 
ferencd@0: Of course, this example is quite simplified. For example, if several
ferencd@0: authentication mechanisms are tried, the user may be requested to enter the
ferencd@0: same information multiple times. See  {\vexample Example6} for a more complex
ferencd@0: implementation of an authenticator, with caching support.
ferencd@0: 
ferencd@0: If you want to use SASL (ie. if \emph{options.sasl} is set to \emph{true}),
ferencd@0: your authenticator must inherit from
ferencd@0: {\vcode vmime::security::sasl::SASLAuthenticator} or
ferencd@0: {\vcode vmime::security::sasl::defaultSASLAuthenticator}, even if you do not
ferencd@0: use the SASL-specific methods {\vcode getAcceptableMechanisms()} and
ferencd@0: {\vcode setSASLMechanism()}. Have a look at {\vexample Example6} to see an
ferencd@0: implementation of an SASL authenticator.
ferencd@0: 
ferencd@0: \begin{lstlisting}[caption={A simple SASL authenticator}]
ferencd@0: class mySASLAuthenticator : public vmime::security::sasl::defaultSASLAuthenticator
ferencd@0: {
ferencd@0:    typedef vmime::security::sasl::SASLMechanism mechanism;  // save us typing
ferencd@0: 
ferencd@0:    const std::vector <vmime::shared_ptr <mechanism> > getAcceptableMechanisms
ferencd@0:          (const std::vector <vmime::shared_ptr <mechanism> >& available,
ferencd@0:           vmime::shared_ptr <mechanism> suggested) const
ferencd@0:    {
ferencd@0:       // Here, you can sort the SASL mechanisms in the order they will be
ferencd@0:       // tried. If no SASL mechanism is acceptable (ie. for example, not
ferencd@0:       // enough secure), you can return an empty list.
ferencd@0:       //
ferencd@0:       // If you do not want to bother with this, you can simply return
ferencd@0:       // the default list, which is ordered by security strength.
ferencd@0:       return defaultSASLAuthenticator::
ferencd@0:          getAcceptableMechanisms(available, suggested);
ferencd@0:    }
ferencd@0: 
ferencd@0:    void setSASLMechanism(vmime::shared_ptr <mechanism> mech)
ferencd@0:    {
ferencd@0:       // This is called when the authentication process is going to
ferencd@0:       // try the specified mechanism.
ferencd@0:       //
ferencd@0:       // The mechanism name is in mech->getName()
ferencd@0: 
ferencd@0:       defaultSASLAuthenticator::setSASLMechanism(mech);
ferencd@0:    }
ferencd@0: 
ferencd@0:    // ...implement getUsername() and getPassword()...
ferencd@0: };
ferencd@0: \end{lstlisting}
ferencd@0: 
ferencd@0: 
ferencd@0: % ============================================================================
ferencd@0: \section{Using transport service}
ferencd@0: 
ferencd@0: You have two possibilities for giving message data to the service when you
ferencd@0: want to send a message:
ferencd@0: 
ferencd@0: \begin{itemize}
ferencd@0: \item either you have a reference to a message (type {\vcode vmime::message})
ferencd@0: and you can simply call {\vcode send(msg)};
ferencd@0: \item or you only have raw message data (as a string, for example), and you
ferencd@0: have to call the second overload of {\vcode send()}, which takes additional
ferencd@0: parameters (corresponding to message envelope);
ferencd@0: \end{itemize}
ferencd@0: 
ferencd@0: The following example illustrates the use of a transport service to send a
ferencd@0: message using the second method:
ferencd@0: 
ferencd@0: \begin{lstlisting}[caption={Using a transport service}]
ferencd@0: const vmime::string msgData =
ferencd@0:    "From: me@example.org \r\n"
ferencd@0:    "To: you@example.org \r\n"
ferencd@0:    "Date: Sun, Oct 30 2005 17:06:42 +0200 \r\n"
ferencd@0:    "Subject: Test \r\n"
ferencd@0:    "\r\n"
ferencd@0:    "Message body";
ferencd@0: 
ferencd@0: // Create a new session
ferencd@0: vmime::utility::url url("smtp://example.com");
ferencd@0: 
ferencd@0: vmime::shared_ptr <vmime::net::session> sess =
ferencd@0:    vmime::make_shared <vmime::net::session>();
ferencd@0: 
ferencd@0: // Create an instance of the transport service
ferencd@0: vmime::shared_ptr <vmime::net::transport> tr = sess->getTransport(url);
ferencd@0: 
ferencd@0: // Connect it
ferencd@0: tr->connect();
ferencd@0: 
ferencd@0: // Send the message
ferencd@0: vmime::utility::inputStreamStringAdapter is(msgData);
ferencd@0: 
ferencd@0: vmime::mailbox from("me@example.org");
ferencd@0: vmime::mailboxList to;
ferencd@0: to.appendMailbox(vmime::make_shared <vmime::mailbox>("you@example.org"));
ferencd@0: 
ferencd@0: tr->send(
ferencd@0:    /* expeditor */    from,
ferencd@0:    /* recipient(s) */ to,
ferencd@0:    /* data */         is,
ferencd@0:    /* total length */ msgData.length());
ferencd@0: 
ferencd@0: // We have finished using the service
ferencd@0: tr->disconnect();
ferencd@0: \end{lstlisting}
ferencd@0: 
ferencd@0: \vnote{Exceptions can be thrown at any time when using a service. For better
ferencd@0: clarity, exceptions are not caught here, but be sure to catch them in your own
ferencd@0: application to provide error feedback to the user.}
ferencd@0: 
ferencd@0: If you use SMTP, you can enable authentication by setting some properties
ferencd@0: on the session object ({\vcode service::setProperty()} is a shortcut for
ferencd@0: setting properties on the session with the correct prefix):
ferencd@0: 
ferencd@0: \begin{lstlisting}
ferencd@0: tr->setProperty("options.need-authentication", true);
ferencd@0: tr->setProperty("auth.username", "user");
ferencd@0: tr->setProperty("auth.password", "password");
ferencd@0: \end{lstlisting}
ferencd@0: 
ferencd@0: 
ferencd@0: % ============================================================================
ferencd@0: \section{Using store service}
ferencd@0: 
ferencd@0: \subsection{Connecting to a store} % -----------------------------------------
ferencd@0: 
ferencd@0: The first basic step for using a store service is to connect to it. The
ferencd@0: following example shows how to initialize a session and instanciate the
ferencd@0: store service:
ferencd@0: 
ferencd@0: \begin{lstlisting}[caption={Connecting to a store service}]
ferencd@0: // Create a new session
ferencd@0: vmime::utility::url url("imap://vincent:password@imap:example.org");
ferencd@0: 
ferencd@0: vmime::shared_ptr <vmime::net::session> sess =
ferencd@0:    vmime::make_shared <vmime::net::session>();
ferencd@0: 
ferencd@0: // Create an instance of the transport service
ferencd@0: vmime::shared_ptr <vmime::net::store> store = sess->getStore(url);
ferencd@0: 
ferencd@0: // Connect it
ferencd@0: store->connect();
ferencd@0: \end{lstlisting}
ferencd@0: 
ferencd@0: \vnote{{\vexample Example6} contains a more complete example for connecting
ferencd@0: to a store service, with support for a custom authenticator.}
ferencd@0: 
ferencd@0: \subsection{Opening a folder} % ----------------------------------------------
ferencd@0: 
ferencd@0: You can open a folder using two different access modes: either in
ferencd@0: \emph{read-only} mode (where you can only read message flags and contents), or
ferencd@0: in \emph{read-write} mode (where you can read messages, but also delete them
ferencd@0: or add new ones). When you have a reference to a folder, simply call the
ferencd@0: {\vcode open()} method with the desired access mode:
ferencd@0: 
ferencd@0: \begin{lstlisting}
ferencd@0: folder->open(vmime::net::folder::MODE_READ_WRITE);
ferencd@0: \end{lstlisting}
ferencd@0: 
ferencd@0: \vnote{Not all stores support the \emph{read-write} mode. By default, if the
ferencd@0: \emph{read-write} mode is not available, the folder silently fall backs on
ferencd@0: the \emph{read-only} mode, unless the \emph{failIfModeIsNotAvailable} argument
ferencd@0: to {\vcode open()} is set to true.}
ferencd@0: 
ferencd@0: Call {\vcode getDefaultFolder()} on the store to obtain a reference to the
ferencd@0: default folder, which is usually the INBOX folder (where messages arrive when
ferencd@0: they are received).
ferencd@0: 
ferencd@0: You can also open a specific folder by specifying its path. The following
ferencd@0: example will open a folder named \emph{bar}, which is a child of \emph{foo}
ferencd@0: in the root folder:
ferencd@0: 
ferencd@0: \begin{lstlisting}[caption={Opening a folder from its path}]
ferencd@0: vmime::net::folder::path path;
ferencd@0: path /= vmime::net::folder::path::component("foo");
ferencd@0: path /= vmime::net::folder::path::component("bar");
ferencd@0: 
ferencd@0: vmime::shared_ptr <vmime::net::folder> fld = store->getFolder(path);
ferencd@0: fld->open(vmime::net::folder::MODE_READ_WRITE);
ferencd@0: \end{lstlisting}
ferencd@0: 
ferencd@0: \vnote{You can specify a path as a string as there is no way to get the
ferencd@0: separator used to delimitate path components. Always use {\vcode operator/=}
ferencd@0: or {\vcode appendComponent}.}
ferencd@0: 
ferencd@0: \vnote{Path components are of type {\vcode vmime::word}, which means that
ferencd@0: VMime supports folder names with extended characters, not only 7-bit
ferencd@0: US-ASCII. However, be careful that this may not be supported by the
ferencd@0: underlying store protocol (IMAP supports it, because it uses internally a
ferencd@0: modified UTF-7 encoding).}
ferencd@0: 
ferencd@0: \subsection{Fetching messages} % ---------------------------------------------
ferencd@0: 
ferencd@0: You can fetch some information about a message without having to download the
ferencd@0: whole message. Moreover, folders support fetching for multiple messages in
ferencd@0: a single request, for better performance. The following items are currently
ferencd@0: available for fetching:
ferencd@0: 
ferencd@0: \begin{itemize}
ferencd@0: \item {\bf envelope}: sender, recipients, date and subject;
ferencd@0: \item {\bf structure}: MIME structure of the message;
ferencd@0: \item {\bf content-info}: content-type of the root part;
ferencd@0: \item {\bf flags}: message flags;
ferencd@0: \item {\bf size}: message size;
ferencd@0: \item {\bf header}: retrieve all the header fields of a message;
ferencd@0: \item {\bf uid}: unique identifier of a message;
ferencd@0: \item {\bf importance}: fetch header fields suitable for use with
ferencd@0: {\vcode misc::importanceHelper}.
ferencd@0: \end{itemize}
ferencd@0: 
ferencd@0: \vnote{Not all services support all fetchable items. Call
ferencd@0: {\vcode getFetchCapabilities()} on a folder to know which information can be
ferencd@0: fetched by a service.}
ferencd@0: 
ferencd@0: The following code shows how to list all the messages in a folder, and
ferencd@0: retrieve basic information to show them to the user:
ferencd@0: 
ferencd@0: \begin{lstlisting}[caption={Fetching information about multiple messages}]
ferencd@0: std::vector <ref <vmime::net::message> > allMessages =
ferencd@0:    folder->getMessages(vmime::net::messageSet::byNumber(1, -1));
ferencd@0:       // -1 is a special value to mean "the number of the last message in the folder"
ferencd@0: 
ferencd@0: folder->fetchMessages(allMessages,
ferencd@0:    vmime::net::fetchAttributes::FLAGS |
ferencd@0:    vmime::net::fetchAttributes::ENVELOPE);
ferencd@0: 
ferencd@0: for (unsigned int i = 0 ; i < allMessages.size() ; ++i)
ferencd@0: {
ferencd@0:    vmime::shared_ptr <vmime::net::message> msg = allMessages[i];
ferencd@0: 
ferencd@0:    const int flags = msg->getFlags();
ferencd@0: 
ferencd@0:    std::cout << "Message " << i << ":" << std::endl;
ferencd@0: 
ferencd@0:    if (flags & vmime::net::message::FLAG_SEEN)
ferencd@0:       std::cout << " - is read" << std::endl;
ferencd@0:    if (flags & vmime::net::message::FLAG_DELETED)
ferencd@0:       std::cout << " - is deleted" << std::endl;
ferencd@0: 
ferencd@0:    vmime::shared_ptr <const vmime::header> hdr = msg->getHeader();
ferencd@0: 
ferencd@0:    std::cout << " - sent on " << hdr->Date()->generate() << std::endl;
ferencd@0:    std::cout << " - sent by " << hdr->From()->generate() << std::endl;
ferencd@0: }
ferencd@0: \end{lstlisting}
ferencd@0: 
ferencd@0: IMAP supports fetching specific header fields of a message. Here is how to use
ferencd@0: the {\vcode fetchAttributes} object to do it:
ferencd@0: 
ferencd@0: \begin{lstlisting}[caption={Using fetchAttributes object to fetch specific header fields of a message}]
ferencd@0: 
ferencd@0: // Fetch message flags and the "Received" and "X-Mailer" header fields
ferencd@0: vmime::net::fetchAttributes fetchAttribs;
ferencd@0: fetchAttribs.add(vmime::net::fetchAttributes::FLAGS);
ferencd@0: fetchAttribs.add("Received");
ferencd@0: fetchAttribs.add("X-Mailer");
ferencd@0: 
ferencd@0: folder->fetchMessages(allMessages, fetchAttribs);
ferencd@0: \end{lstlisting}
ferencd@0: 
ferencd@0: 
ferencd@0: \subsection{Extracting messages and parts}
ferencd@0: 
ferencd@0: To extract the whole contents of a message (including headers), use the
ferencd@0: {\vcode extract()} method on a {\vcode vmime::net::message} object. The
ferencd@0: following example extracts the first message in the default folder:
ferencd@0: 
ferencd@0: \begin{lstlisting}[caption={Extracting messages}]
ferencd@0: // Get a reference to the folder and to its first message
ferencd@0: vmime::shared_ptr <vmime::net::folder> folder = store->getDefaultFolder();
ferencd@0: vmime::shared_ptr <vmime::net::message> msg = folder->getMessage(1);
ferencd@0: 
ferencd@0: // Write the message contents to the standard output
ferencd@0: vmime::utility::outputStreamAdapter out(std::cout);
ferencd@0: msg->extract(out);
ferencd@0: \end{lstlisting}
ferencd@0: 
ferencd@0: Some protocols (like IMAP) also support the extraction of specific MIME parts
ferencd@0: of a message without downloading the whole message. This can save bandwidth
ferencd@0: and time. The method {\vcode extractPart()} is used in this case:
ferencd@0: 
ferencd@0: \begin{lstlisting}[caption={Extracting a specific MIME part of a message}]
ferencd@0: // Fetching structure is required before extracting a part
ferencd@0: folder->fetchMessage(msg, vmime::net::fetchAttributes::STRUCTURE);
ferencd@0: 
ferencd@0: // Now, we can extract the part
ferencd@0: msg->extractPart(msg->getStructure()->getPartAt(0)->getPartAt(1));
ferencd@0: \end{lstlisting}
ferencd@0: 
ferencd@0: Suppose we have a message with the following structure:
ferencd@0: 
ferencd@0: \begin{verbatim}
ferencd@0:    multipart/mixed
ferencd@0:       text/html
ferencd@0:       image/jpeg [*]
ferencd@0: \end{verbatim}
ferencd@0: 
ferencd@0: The previous example will extract the header and body of the \emph{image/jpeg}
ferencd@0: part.
ferencd@0: 
ferencd@0: \subsection{Deleting messages} % ---------------------------------------------
ferencd@0: 
ferencd@0: The following example will delete the second and the third message from the
ferencd@0: store.
ferencd@0: 
ferencd@0: \begin{lstlisting}[caption={Deleting messages}]
ferencd@0: vmime::shared_ptr <vmime::net::folder> folder = store->getDefaultFolder();
ferencd@0: 
ferencd@0: folder->deleteMessages(vmime::net::messageSet::byNumber(/* from */ 2, /* to */ 3));
ferencd@0: 
ferencd@0: // This is equivalent
ferencd@0: std::vector <int> nums;
ferencd@0: nums.push_back(2);
ferencd@0: nums.push_back(3);
ferencd@0: folder->deleteMessages(vmime::net::messageSet::byNumber(nums));
ferencd@0: 
ferencd@0: // This is also equivalent (but will require 2 roundtrips to server)
ferencd@0: folder->deleteMessages(vmime::net::messageSet::byNumber(2));
ferencd@0: folder->deleteMessages(vmime::net::messageSet::byNumber(2)); // renumbered, 3 becomes 2
ferencd@0: \end{lstlisting}
ferencd@0: 
ferencd@0: \subsection{Events} % --------------------------------------------------------
ferencd@0: 
ferencd@0: As a result of executing some operation (or from time to time, even if no
ferencd@0: operation has been performed), a store service can send events to notify you
ferencd@0: that something has changed (eg. the number of messages in a folder). These
ferencd@0: events may allow you to update the user interface associated to a message
ferencd@0: store.
ferencd@0: 
ferencd@0: Currently, there are three types of event:
ferencd@0: 
ferencd@0: \begin{itemize}
ferencd@0: \item {\bf message change}: sent when the number of messages in a folder
ferencd@0: has changed (ie. some messages have been added or removed);
ferencd@0: \item {\bf message count change}: sent when one or more message(s) have
ferencd@0: changed (eg. flags or deleted status);
ferencd@0: \item {\bf folder change}: sent when a folder has been created, renamed or
ferencd@0: deleted.
ferencd@0: \end{itemize}
ferencd@0: 
ferencd@0: You can register a listener for each event type by using the corresponding
ferencd@0: methods on a {\vcode folder} object: {\vcode addMessageChangedListener()},
ferencd@0: {\vcode addMessageCountListener()} or {\vcode addFolderListener()}. For more
ferencd@0: information, please read the class documentation for
ferencd@0: {\vcode vmime::net::events} namespace.
ferencd@0: 
ferencd@0: 
ferencd@0: % ============================================================================
ferencd@0: \section{Handling timeouts}
ferencd@0: 
ferencd@0: Unexpected errors can occur while messaging services are performing
ferencd@0: operations and waiting a response from the server (eg. server stops
ferencd@0: responding, network link falls down). As all operations as synchronous,
ferencd@0: they can be ``blocked'' a long time before returning (in fact, they loop
ferencd@0: until they either receive a response from the server, or the underlying
ferencd@0: socket system returns an error).
ferencd@0: 
ferencd@0: VMime provides a mechanism to control the duration of operations. This
ferencd@0: mechanism allows the program to cancel an operation that is currently
ferencd@0: running.
ferencd@0: 
ferencd@0: An interface called {\vcode timeoutHandler} is provided:
ferencd@0: 
ferencd@0: \begin{lstlisting}
ferencd@0: class timeoutHandler : public object
ferencd@0: {
ferencd@0:    /** Called to test if the time limit has been reached.
ferencd@0:      *
ferencd@0:      * @return true if the timeout delay is elapsed
ferencd@0:      */
ferencd@0:    virtual const bool isTimeOut() = 0;
ferencd@0: 
ferencd@0:    /** Called to reset the timeout counter.
ferencd@0:      */
ferencd@0:    virtual void resetTimeOut() = 0;
ferencd@0: 
ferencd@0:    /** Called when the time limit has been reached (when
ferencd@0:      * isTimeOut() returned true).
ferencd@0:      *
ferencd@0:      * @return true to continue (and reset the timeout)
ferencd@0:      * or false to cancel the current operation
ferencd@0:      */
ferencd@0:    virtual const bool handleTimeOut() = 0;
ferencd@0: };
ferencd@0: \end{lstlisting}
ferencd@0: 
ferencd@0: While the operation runs, the service calls {\vcode isTimeout()} at variable
ferencd@0: intervals. If the {\vcode isTimeout()} function returns {\vcode true},
ferencd@0: then {\vcode handleTimeout()} is called. If the {\vcode handleTimeout()}
ferencd@0: function returns {\vcode false}, the operation is cancelled and
ferencd@0: an {\vcode operation\_timed\_out} exception is thrown. Else, if
ferencd@0: {\vcode handleTimeout()} returns true, the operation continues and the
ferencd@0: timeout counter is reset.
ferencd@0: The function {\vcode resetTimeout()} is called each time data has
ferencd@0: been received from the server to reset the timeout delay.
ferencd@0: 
ferencd@0: When using a service, a default timeout handler is set: if an operation
ferencd@0: is blocked for more than 30 seconds (ie. network link is down and no data
ferencd@0: was received since 30 seconds), an {\vcode operation\_timed\_out} exception
ferencd@0: is thrown.
ferencd@0: 
ferencd@0: The following example shows how to implement a simple timeout handler:
ferencd@0: 
ferencd@0: \begin{lstlisting}[caption={Implementing a simple timeout handler}]
ferencd@0: class myTimeoutHandler : public vmime::net::timeoutHandler
ferencd@0: {
ferencd@0: public:
ferencd@0: 
ferencd@0:    myTimeoutHandler()
ferencd@0:    {
ferencd@0:       m_startTime = time(NULL);
ferencd@0:    }
ferencd@0: 
ferencd@0:    const bool isTimeOut()
ferencd@0:    {
ferencd@0:       return (time(NULL) >= m_startTime + 30);  // 30 seconds timeout
ferencd@0:    }
ferencd@0: 
ferencd@0:    void resetTimeOut()
ferencd@0:    {
ferencd@0:       m_startTime = time(NULL);
ferencd@0:    }
ferencd@0: 
ferencd@0:    const bool handleTimeOut()
ferencd@0:    {
ferencd@0:       std::cout << "Operation timed out." << std::endl;
ferencd@0:                 << "Press [Y] to continue, or [N] to "
ferencd@0:                 << "cancel the operation." << std::endl;
ferencd@0: 
ferencd@0:       std::string response;
ferencd@0:       std::cin >> response;
ferencd@0: 
ferencd@0:       return (response == "y" || response == "Y");
ferencd@0:    }
ferencd@0: 
ferencd@0: private:
ferencd@0: 
ferencd@0:    time_t m_startTime;
ferencd@0: };
ferencd@0: \end{lstlisting}
ferencd@0: 
ferencd@0: To make the service use your timeout handler, you need to write a factory
ferencd@0: class, to allow the service to create instances of the handler class. This
ferencd@0: is required because the service can use several connections to the server
ferencd@0: simultaneously, and each connection needs its own timeout handler.
ferencd@0: 
ferencd@0: \begin{lstlisting}
ferencd@0: class myTimeoutHandlerFactory : public vmime::net::timeoutHandlerFactory
ferencd@0: {
ferencd@0: public:
ferencd@0: 
ferencd@0:    ref <timeoutHandler> create()
ferencd@0:    {
ferencd@0:       return vmime::make_shared <myTimeoutHandler>();
ferencd@0:    }
ferencd@0: };
ferencd@0: \end{lstlisting}
ferencd@0: 
ferencd@0: Then, call the {\vcode setTimeoutHandlerFactory()} method on the service object
ferencd@0: to set the timeout handler factory to use during the session:
ferencd@0: 
ferencd@0: \begin{lstlisting}
ferencd@0: theService->setTimeoutHandlerFactory(vmime::make_shared <myTimeoutHandlerFactory>());
ferencd@0: \end{lstlisting}
ferencd@0: 
ferencd@0: 
ferencd@0: % ============================================================================
ferencd@0: \newpage
ferencd@0: \section{Secured connection using TLS/SSL}
ferencd@0: 
ferencd@0: \subsection{Introduction} % --------------------------------------------------
ferencd@0: 
ferencd@0: If you have enabled TLS support in VMime, you can configure messaging services
ferencd@0: so that they use a secured connection.
ferencd@0: 
ferencd@0: Quoting from RFC-2246 - the TLS 1.0 protocol specification: \emph{`` The TLS
ferencd@0: protocol provides communications privacy over the Internet. The protocol
ferencd@0: allows client/server applications to communicate in a way that is designed
ferencd@0: to prevent eavesdropping, tampering, or message forgery.''}
ferencd@0: 
ferencd@0: TLS has the following advantages:
ferencd@0: 
ferencd@0: \begin{itemize}
ferencd@0: \item authentication: server identity can be verified;
ferencd@0: \item privacy: transmission of data between client and server cannot be read
ferencd@0: by someone in the middle of the connection;
ferencd@0: \item integrity: original data which is transferred between a client and a
ferencd@0: server can not be modified by an attacker without being detected.
ferencd@0: \end{itemize}
ferencd@0: 
ferencd@0: \vnote{What is the difference between SSL and TLS? SSL is a protocol designed
ferencd@0: by Netscape. TLS is a standard protocol, and is partly based on version 3 of
ferencd@0: the SSL protocol. The two protocols are not interoperable, but TLS does
ferencd@0: support a mechanism to back down to SSL 3.}
ferencd@0: 
ferencd@0: VMime offers two possibilities for using a secured connection:
ferencd@0: 
ferencd@0: \begin{itemize}
ferencd@0: \item you can connect to a server listening on a special port (eg. IMAPS
ferencd@0: instead of IMAP): this is the classical use of SSL, but is now deprecated;
ferencd@0: \item connect to a server listening on the default port, and then begin a
ferencd@0: secured connection: this is STARTTLS.
ferencd@0: \end{itemize}
ferencd@0: 
ferencd@0: 
ferencd@0: \subsection{Setting up a secured connection} % -------------------------------
ferencd@0: 
ferencd@0: \subsubsection{Connecting to a ``secured'' port} % ...........................
ferencd@0: 
ferencd@0: To use the classical SSL/TLS way, simply use the ``S'' version of the protocol
ferencd@0: to connect to the server (eg. \emph{imaps} instead of \emph{imap}). This is
ferencd@0: currently available for SMTP, POP3 and IMAP.
ferencd@0: 
ferencd@0: \begin{lstlisting}
ferencd@0: vmime::shared_ptr <vmime::net::store> store =
ferencd@0:    theSession->getStore(vmime::utility::url("imaps://example.org"));
ferencd@0: \end{lstlisting}
ferencd@0: 
ferencd@0: \subsubsection{Using STARTTLS} % .............................................
ferencd@0: 
ferencd@0: To make the service start a secured session using the STARTTLS method, simply
ferencd@0: set the \emph{connection.tls} property:
ferencd@0: 
ferencd@0: \begin{lstlisting}
ferencd@0: theService->setProperty("connection.tls", true);
ferencd@0: \end{lstlisting}
ferencd@0: 
ferencd@0: \vnote{If, for some reason, a secured connection cannot be started, the
ferencd@0: default behaviour is to fallback on a normal connection. To make
ferencd@0: {\vcode connect()} fail if STARTTLS fails, set the
ferencd@0: \emph{connection.tls.required} to \emph{true}.}
ferencd@0: 
ferencd@0: \subsection{Certificate verification} % --------------------------------------
ferencd@0: 
ferencd@0: \subsubsection{How it works} % ...............................................
ferencd@0: 
ferencd@0: If you tried the previous examples, a
ferencd@0: {\vcode certificateException} might have been thrown.
ferencd@0: This is because the default certificate verifier in VMime did not manage to
ferencd@0: verify the certificate, and so could not trust it.
ferencd@0: 
ferencd@0: Basically, when you connect to a server using TLS, the server responds with
ferencd@0: a list of certificates, called a certificate chain (usually, certificates are
ferencd@0: of type X.509\footnote{And VMime currently supports only X.509 certificates}).
ferencd@0: The certificate chain is ordered so that the first certificate is the subject
ferencd@0: certificate, the second is the subject's issuer one, the third is the issuer's
ferencd@0: issuer, and so on.
ferencd@0: 
ferencd@0: To decide whether the server can be trusted or not, you have to verify that
ferencd@0: \emph{each} certificate is valid (ie. is trusted). For more information
ferencd@0: about X.509 and certificate verification, see related articles on Wikipedia
ferencd@0: \footnote{See \url{http://wikipedia.org/wiki/Public\_key\_certificate}}.
ferencd@0: 
ferencd@0: \subsubsection{Using the default certificate verifier} % .....................
ferencd@0: 
ferencd@0: The default certificate verifier maintains a list of root (CAs) and user
ferencd@0: certificates that are trusted. By default, the list is empty. So, you have
ferencd@0: to initialize it before using the verifier.
ferencd@0: 
ferencd@0: The algorithm\footnote{See
ferencd@0: \url{http://wikipedia.org/wiki/Certification\_path\_validation\_algorithm}}
ferencd@0: used is quite simple:
ferencd@0: 
ferencd@0: \begin{enumerate}
ferencd@0: \item for every certificate in the chain, verify that the certificate has been
ferencd@0: issued by the next certificate in the chain;
ferencd@0: \item for every certificate in the chain, verify that the certificate is valid
ferencd@0: at the current time;
ferencd@0: \item ensure that the first certificate's subject name matches the hostname
ferencd@0: of the server;
ferencd@0: \item decide whether the subject's certificate can be trusted:
ferencd@0: 	\begin{itemize}
ferencd@0: 	\item first, verify that the the last certificate in the chain was
ferencd@0: 	issued by a third-party that we trust (root CAs);
ferencd@0: 	\item if the issuer certificate cannot be verified against root CAs,
ferencd@0: 	compare the subject's certificate against the trusted certificates
ferencd@0: 	(the certificates the user has decided to trust).
ferencd@0: 	\end{itemize}
ferencd@0: \end{enumerate}
ferencd@0: 
ferencd@0: First, we need some code to load existing X.509 certificates:
ferencd@0: 
ferencd@0: \begin{lstlisting}[caption={Reading a X.509 certificate from a file}]
ferencd@0: vmime::shared_ptr <vmime::security::cert::X509Certificate>
ferencd@0:    loadX509CertificateFromFile(const std::string& path)
ferencd@0: {
ferencd@0:    std::ifstream certFile;
ferencd@0:    certFile.open(path.c_str(), std::ios::in | std::ios::binary);
ferencd@0: 
ferencd@0:    if (!certFile)
ferencd@0:    {
ferencd@0:       // ...handle error...
ferencd@0:    }
ferencd@0: 
ferencd@0:    vmime::utility::inputStreamAdapter is(certFile);
ferencd@0:    vmime::shared_ptr <vmime::security::cert::X509Certificate> cert;
ferencd@0: 
ferencd@0:    // Try DER format
ferencd@0:    cert = vmime::security::cert::X509Certificate::import
ferencd@0:       (is, vmime::security::cert::X509Certificate::FORMAT_DER);
ferencd@0: 
ferencd@0:    if (cert != NULL)
ferencd@0:       return cert;
ferencd@0: 
ferencd@0:    // Try PEM format
ferencd@0:    is.reset();
ferencd@0:    cert = vmime::security::cert::X509Certificate::import
ferencd@0:       (is, vmime::security::cert::X509Certificate::FORMAT_PEM);
ferencd@0: 
ferencd@0:    return cert;
ferencd@0: }
ferencd@0: \end{lstlisting}
ferencd@0: 
ferencd@0: Then, we can use the {\vcode loadX509CertificateFromFile} function to load
ferencd@0: certificates and initialize the certificate verifier:
ferencd@0: 
ferencd@0: \begin{lstlisting}[caption={Using the default certificate verifier}]
ferencd@0: vmime::shared_ptr <vmime::security::cert::defaultCertificateVerifier> vrf =
ferencd@0:    vmime::make_shared <vmime::security::cert::defaultCertificateVerifier>();
ferencd@0: 
ferencd@0: // Load root CAs (such as Verisign or Thawte)
ferencd@0: std::vector <vmime::shared_ptr <vmime::security::cert::X509Certificate> > rootCAs;
ferencd@0: 
ferencd@0: rootCAs.push_back(loadX509CertificateFromFile("/path/to/root-ca1.cer");
ferencd@0: rootCAs.push_back(loadX509CertificateFromFile("/path/to/root-ca2.cer");
ferencd@0: rootCAs.push_back(loadX509CertificateFromFile("/path/to/root-ca3.cer");
ferencd@0: 
ferencd@0: vrf->setX509RootCAs(rootCAs);
ferencd@0: 
ferencd@0: // Then, load certificates that the user explicitely chose to trust
ferencd@0: std::vector <vmime::shared_ptr <vmime::security::cert::X509Certificate> > trusted;
ferencd@0: 
ferencd@0: trusted.push_back(loadX509CertificateFromFile("/path/to/trusted-site1.cer");
ferencd@0: trusted.push_back(loadX509CertificateFromFile("/path/to/trusted-site2.cer");
ferencd@0: 
ferencd@0: vrf->setX509TrustedCerts(trusted);
ferencd@0: \end{lstlisting}
ferencd@0: 
ferencd@0: 
ferencd@0: \subsubsection{Writing your own certificate verifier} % ......................
ferencd@0: 
ferencd@0: If you need to do more complex verifications on certificates, you will have to
ferencd@0: write your own verifier. Your verifier should inherit from the
ferencd@0: {\vcode vmime::security::cert::certificateVerifier} class and implement the
ferencd@0: method {\vcode verify()}. Then, if the specified certificate chain is trusted,
ferencd@0: simply return from the function, or else throw a
ferencd@0: {\vcode certificateException}.
ferencd@0: 
ferencd@0: The following example shows how to implement an interactive certificate
ferencd@0: verifier which relies on the user's decision, and nothing else (you SHOULD NOT
ferencd@0: use this in a production application as this is obviously a serious security
ferencd@0: issue):
ferencd@0: 
ferencd@0: \begin{lstlisting}[caption={A custom certificate verifier}]
ferencd@0: class myCertVerifier : public vmime::security::cert::certificateVerifier
ferencd@0: {
ferencd@0: public:
ferencd@0: 
ferencd@0:    void verify(vmime::shared_ptr <certificateChain> certs)
ferencd@0:    {
ferencd@0:       // Obtain the subject's certificate
ferencd@0:       vmime::shared_ptr <vmime::security::cert::certificate> cert = chain->getAt(0);
ferencd@0: 
ferencd@0:       std::cout << std::endl;
ferencd@0:       std::cout << "Server sent a '" << cert->getType() << "'"
ferencd@0:          << " certificate." << std::endl;
ferencd@0:       std::cout << "Do you want to accept this certificate? (Y/n) ";
ferencd@0:       std::cout.flush();
ferencd@0: 
ferencd@0:       std::string answer;
ferencd@0:       std::getline(std::cin, answer);
ferencd@0: 
ferencd@0:       if (answer.length() != 0 && (answer[0] == 'Y' || answer[0] == 'y'))
ferencd@0:          return;  // OK, we trust the certificate
ferencd@0: 
ferencd@0:       // Don't trust this certificate
ferencd@0:       throw vmime::security::cert::certificateException();
ferencd@0:    }
ferencd@0: };
ferencd@0: \end{lstlisting}
ferencd@0: 
ferencd@0: \vnote{In production code, it may be a good idea to remember user's decisions
ferencd@0: about which certificates to trust and which not. See {\vexample Example6} for
ferencd@0: a basic cache implementation.}
ferencd@0: 
ferencd@0: Finally, to make the service use your own certificate verifier, simply write:
ferencd@0: 
ferencd@0: \begin{lstlisting}
ferencd@0: theService->setCertificateVerifier(vmime::make_shared <myCertVerifier>());
ferencd@0: \end{lstlisting}
ferencd@0: 
ferencd@0: \subsection{SSL/TLS Properties} % --------------------------------------------
ferencd@0: 
ferencd@0: If you want to customize behavior or set some options on TLS/SSL connection,
ferencd@0: you may use the TLSProperties object, and pass it to the service session. The
ferencd@0: TLS/SSL options must be set {\em before} creating any service with the session
ferencd@0: (ie. before calling either {\vcode getStore()} or {\vcode getTransport()} on
ferencd@0: the session), or they will not be used.
ferencd@0: 
ferencd@0: The following example shows how to set the cipher suite preferences for TLS:
ferencd@0: 
ferencd@0: \begin{lstlisting}[caption={Setting TLS cipher suite preferences}]
ferencd@0: vmime::shared_ptr <vmime::net::session> sess = /* ... */;
ferencd@0: 
ferencd@0: vmime::shared_ptr <vmime::net::tls::TLSProperties> tlsProps =
ferencd@0: 	vmime::make_shared <vmime::net::tls::TLSProperties>();
ferencd@0: 
ferencd@0: // for OpenSSL
ferencd@0: tlsProps->setCipherString("HIGH:!ADH:@STRENGTH");
ferencd@0: 
ferencd@0: // for GNU TLS
ferencd@0: tlsProps->setCipherString("NORMAL:%SSL3_RECORD_VERSION");
ferencd@0: 
ferencd@0: sess->setTLSProperties(tlsProps);
ferencd@0: \end{lstlisting}
ferencd@0: 
ferencd@0: Please note that the cipher suite string format and meaning depend on the
ferencd@0: underlying TLS library (either OpenSSL or GNU TLS):
ferencd@0: 
ferencd@0: \begin{itemize}
ferencd@0: \item for GNU TLS, read this: \newline
ferencd@0: \url{http://gnutls.org/manual/html\_node/Priority-Strings.html}
ferencd@0: 
ferencd@0: \item for OpenSSL, read this: \newline
ferencd@0: \url{http://www.openssl.org/docs/apps/ciphers.html#CIPHER\_STRINGS}
ferencd@0: \end{itemize}
ferencd@0: 
ferencd@0: You may also set cipher suite preferences using predefined constants that
ferencd@0: map to generic security modes:
ferencd@0: 
ferencd@0: \begin{lstlisting}[caption={Setting TLS cipher suite preferences using predefined modes}]
ferencd@0: sess->setCipherSuite(vmime::net::tls::TLSProperties::CIPHERSUITE_HIGH);
ferencd@0: \end{lstlisting}
ferencd@0: 
ferencd@0: The following constants are available:
ferencd@0: 
ferencd@0: \noindent\begin{tabularx}{1.0\textwidth}{|l|X|}
ferencd@0: \hline
ferencd@0: 	{\bf Constant} &
ferencd@0: 	{\bf Meaning} \\
ferencd@0: \hline
ferencd@0: 	CIPHERSUITE\_HIGH &
ferencd@0: 	High encryption cipher suites ($>$ 128 bits) \\
ferencd@0: \hline
ferencd@0: 	CIPHERSUITE\_MEDIUM &
ferencd@0: 	Medium encryption cipher suites ($>=$ 128 bits) \\
ferencd@0: \hline
ferencd@0: 	CIPHERSUITE\_LOW &
ferencd@0: 	Low encryption cipher suites ($>=$ 64 bits) \\
ferencd@0: \hline
ferencd@0: 	CIPHERSUITE\_DEFAULT &
ferencd@0: 	Default cipher suite (actual cipher suites used depends
ferencd@0: 	on the underlying SSL/TLS library) \\
ferencd@0: \hline
ferencd@0: \end{tabularx}
ferencd@0: 




