Mercurial > thymian
comparison 3rdparty/vmime/doc/book/net.tex @ 0:a4671277546c tip
created the repository for the thymian project
| author | ferencd |
|---|---|
| date | Tue, 17 Aug 2021 11:19:54 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:a4671277546c |
|---|---|
| 1 \chapter{Working with Messaging Services} | |
| 2 | |
| 3 % ============================================================================ | |
| 4 \section{Introduction} | |
| 5 | |
| 6 In addition to parsing and building MIME messages, VMime also offers a lot of | |
| 7 features to work with messaging services. This includes connecting to remote | |
| 8 messaging stores (like IMAP or POP3), local stores (maildir) and transport | |
| 9 services (send messages over SMTP or local sendmail), through an unified | |
| 10 interface (see Figure \ref{uml_messaging_module}). That means that you can | |
| 11 use independently IMAP of POP3 without having to change any line of code. | |
| 12 | |
| 13 Source code of {\vexample Example6} covers all features presented in this | |
| 14 chapter, so it is important you take some time to read it. | |
| 15 | |
| 16 \begin{figure} | |
| 17 \center\includegraphics[width=0.9\textwidth] | |
| 18 {images/messaging-services.png}\endcenter | |
| 19 \caption{Overall structure of the messaging module} | |
| 20 \label{uml_messaging_module} | |
| 21 \end{figure} | |
| 22 | |
| 23 The interface is composed of five classes: | |
| 24 | |
| 25 \begin{itemize} | |
| 26 \item {\vcode vmime::net::service}: this is the base interface for a | |
| 27 messaging service. It can be either a store service or a transport | |
| 28 service. | |
| 29 | |
| 30 \item {\vcode vmime::net::serviceFactory}: create instances of a service. | |
| 31 This is used internally by the session object (see below). | |
| 32 | |
| 33 \item {\vcode vmime::net::store}: interface for a store service. A store | |
| 34 service offers access to a set of folders containing messages. This is | |
| 35 used for IMAP, POP3 and maildir. | |
| 36 | |
| 37 \item {\vcode vmime::net::transport}: interface for a transport service. | |
| 38 A transport service is capable of sending messages. This is used for | |
| 39 SMTP and sendmail. | |
| 40 | |
| 41 \item {\vcode vmime::net::session}: a session object is used to store the | |
| 42 parameters used by a service (eg. connection parameters). Each service | |
| 43 instance is associated with only one session. The session object is capable | |
| 44 of creating instances of services. | |
| 45 \end{itemize} | |
| 46 | |
| 47 The following classes are specific to store services: | |
| 48 | |
| 49 \begin{itemize} | |
| 50 \item {\vcode vmime::net::folder}: a folder can either contain other folders | |
| 51 or messages, or both. | |
| 52 | |
| 53 \item {\vcode vmime::net::message}: this is the interface for dealing with | |
| 54 messages. For a given message, you can have access to its flags, its MIME | |
| 55 structure and you can also extract the whole message data or given parts (if | |
| 56 supported by the underlying protocol). | |
| 57 \end{itemize} | |
| 58 | |
| 59 | |
| 60 % ============================================================================ | |
| 61 \section{Working with sessions} | |
| 62 | |
| 63 \subsection{Setting properties} % -------------------------------------------- | |
| 64 | |
| 65 Sessions are used to store configuration parameters for services. They | |
| 66 contains a set of typed properties that can modify the behaviour of the | |
| 67 services. Before using a messaging service, you must create and | |
| 68 initialize a session object: | |
| 69 | |
| 70 \begin{lstlisting} | |
| 71 vmime::shared_ptr <net::session> theSession = vmime::make_shared <net::session>(); | |
| 72 \end{lstlisting} | |
| 73 | |
| 74 Session properties include: | |
| 75 | |
| 76 \begin{itemize} | |
| 77 \item connection parameters: host and port to connect to; | |
| 78 \item authentication parameters: user credentials required to use the | |
| 79 service (if any); | |
| 80 \item protocol-specific parameters: enable or disable extensions (eg. APOP | |
| 81 support in POP3). | |
| 82 \end{itemize} | |
| 83 | |
| 84 Properties are stored using a dotted notation, to specify the service type, | |
| 85 the protocol name, the category and the name of the property: | |
| 86 | |
| 87 \begin{verbatim} | |
| 88 {service_type}.{protocol}.category.name | |
| 89 \end{verbatim} | |
| 90 | |
| 91 An example of property is \emph{store.pop3.options.apop} (used to enable or | |
| 92 disable the use of APOP authentication). The \emph{store.pop3} part is called | |
| 93 the \emph{prefix}. This allow specifying different values for the same | |
| 94 property depending on the protocol used. | |
| 95 | |
| 96 The session properties are stored in a {\vcode vmime::propertySet} object. | |
| 97 To set the value of a property, you can use either: | |
| 98 | |
| 99 \begin{lstlisting} | |
| 100 theSession->getProperties().setProperty("property-name", value); | |
| 101 \end{lstlisting} | |
| 102 | |
| 103 or: | |
| 104 | |
| 105 \begin{lstlisting} | |
| 106 theSession->getProperties()["property-name"] = value; | |
| 107 \end{lstlisting} | |
| 108 | |
| 109 | |
| 110 \subsection{Available properties} % ------------------------------------------ | |
| 111 | |
| 112 Following is a list of available properties and the protocols they apply to, | |
| 113 as the time of writing this documentation\footnote{You can get an up-to-date | |
| 114 list of the properties by running \vexample{Example7}}. For better clarity, | |
| 115 the prefixes do not appear in this table. | |
| 116 | |
| 117 \begin{table}[!ht] | |
| 118 \noindent\begin{tabularx}{1.0\textwidth}{|l|c|X|c|c|c|c|c|c|c|c|} | |
| 119 \hline | |
| 120 {\bf Property name} & | |
| 121 {\bf Type} & | |
| 122 {\bf Description} & | |
| 123 \verti{\bf POP3} & | |
| 124 \verti{\bf POP3S} & | |
| 125 \verti{\bf IMAP} & | |
| 126 \verti{\bf IMAPS} & | |
| 127 \verti{\bf SMTP} & | |
| 128 \verti{\bf SMTPS} & | |
| 129 \verti{\bf maildir} & | |
| 130 \verti{\bf sendmail} \\ | |
| 131 \hline | |
| 132 \hline | |
| 133 options.sasl & bool & Set to {\vcode true} to use SASL authentication, if | |
| 134 available. & \vdot & \vdot & \vdot & \vdot & \vdot & \vdot & & \\ | |
| 135 \hline | |
| 136 options.sasl.fallback & bool & Fail if SASL authentication failed (do not | |
| 137 try other authentication mechanisms). & \vdot & \vdot & \vdot & \vdot & | |
| 138 \vdot & \vdot & & \\ | |
| 139 \hline | |
| 140 auth.username\footnote{You should use authenticators | |
| 141 instead.\label{fn_auth_username}} & string & Set the username of the account | |
| 142 to connect to. & \vdot & \vdot & \vdot & \vdot & \vdot & \vdot & & \\ | |
| 143 \hline | |
| 144 auth.password\footref{fn_auth_username} & string & Set the password of the | |
| 145 account. & \vdot & \vdot & \vdot & \vdot & \vdot & \vdot & & \\ | |
| 146 \hline | |
| 147 connection.tls & bool & Set to {\vcode true} to start a secured connection | |
| 148 using STARTTLS extension, if available. & \vdot & & \vdot & & \vdot & & & \\ | |
| 149 \hline | |
| 150 connection.tls.required & bool & Fail if a secured connection cannot be | |
| 151 started. & \vdot & & \vdot & & \vdot & & & \\ | |
| 152 \hline | |
| 153 server.address & string & Server host name or IP address. &\vdot & \vdot & | |
| 154 \vdot & \vdot & \vdot & \vdot & & \\ | |
| 155 \hline | |
| 156 server.port & int & Server port. & \vdot & \vdot & \vdot & \vdot & | |
| 157 \vdot & \vdot & & \\ | |
| 158 \hline | |
| 159 server.rootpath & string & Root directory for mail repository (eg. | |
| 160 \emph{/home/vincent/Mail}). & & & & & & & \vdot & \\ | |
| 161 \hline | |
| 162 \end{tabularx} | |
| 163 \caption{Properties common to all protocols} | |
| 164 \end{table} | |
| 165 | |
| 166 \newpage | |
| 167 These are the protocol-specific options: | |
| 168 | |
| 169 \begin{table}[!ht] | |
| 170 \noindent\begin{tabularx}{1.0\textwidth}{|l|c|X|} | |
| 171 \hline | |
| 172 {\bf Property name} & | |
| 173 {\bf Type} & | |
| 174 {\bf Description} \\ | |
| 175 % POP3/POP3S | |
| 176 \hline | |
| 177 \multicolumn{3}{|c|}{POP3, POP3S} \\ | |
| 178 \hline | |
| 179 store.pop3.options.apop & bool & Enable or disable authentication with | |
| 180 APOP (if SASL is enabled, this occurs after all SASL mechanisms have been | |
| 181 tried). \\ | |
| 182 \hline | |
| 183 store.pop3.options.apop.fallback & bool & If set to {\vcode true} and | |
| 184 APOP fails, the authentication process fails (ie. unsecure plain text | |
| 185 authentication is not used). \\ | |
| 186 \hline | |
| 187 % SMTP | |
| 188 \multicolumn{3}{|c|}{SMTP, SMTPS} \\ | |
| 189 \hline | |
| 190 transport.smtp.options.need-authentication & bool & Set to \emph{true} if | |
| 191 the server requires to authenticate before sending messages. \\ | |
| 192 \hline | |
| 193 transport.smtp.options.pipelining & bool & Set to {\vcode false} to disable | |
| 194 command pipelining, if the server supports it (default is {\vcode true}). \\ | |
| 195 \hline | |
| 196 transport.smtp.options.chunking & bool & Set to {\vcode false} to disable | |
| 197 CHUNKING extension, if the server supports it (default is {\vcode true}). \\ | |
| 198 \hline | |
| 199 % sendmail | |
| 200 \multicolumn{3}{|c|}{sendmail} \\ | |
| 201 \hline | |
| 202 transport.sendmail.binpath & string & The path to the \emph{sendmail} | |
| 203 executable on your system. The default is the one found by the configuration | |
| 204 script when VMime was built. \\ | |
| 205 \hline | |
| 206 \end{tabularx} | |
| 207 \caption{Protocol-specific options} | |
| 208 \end{table} | |
| 209 | |
| 210 | |
| 211 \subsection{Instanciating services} % ---------------------------------------- | |
| 212 | |
| 213 You can create a service either by specifying its protocol name, or by | |
| 214 specifying the URL of the service. Creation by name is deprecated so | |
| 215 this chapter only presents the latter option. | |
| 216 | |
| 217 The URL scheme for connecting to services is: | |
| 218 | |
| 219 \begin{verbatim} | |
| 220 protocol://[username[:password]@]host[:port]/[root-path] | |
| 221 \end{verbatim} | |
| 222 | |
| 223 \vnote{For local services (ie. \emph{sendmail} and \emph{maildir}), the host | |
| 224 part is not used, but it must not be empty (you can use "localhost").} | |
| 225 | |
| 226 The following table shows an example URL for each service: | |
| 227 | |
| 228 \noindent\begin{tabularx}{1.0\textwidth}{|c|X|} | |
| 229 \hline | |
| 230 {\bf Service} & | |
| 231 {\bf Connection URL} \\ | |
| 232 \hline | |
| 233 imap, imaps & {\tt imap://imap.example.com}, | |
| 234 {\tt imaps://vincent:pass@example.com} \\ | |
| 235 \hline | |
| 236 pop3, pop3s & {\tt pop3://pop3.example.com} \\ | |
| 237 \hline | |
| 238 smtp, smtps & {\tt smtp://smtp.example.com} \\ | |
| 239 \hline | |
| 240 maildir & {\tt maildir://localhost/home/vincent/Mail} (host not used) \\ | |
| 241 \hline | |
| 242 sendmail & {\tt sendmail://localhost} (host not used, always localhost) \\ | |
| 243 \hline | |
| 244 \end{tabularx} | |
| 245 | |
| 246 \newpage | |
| 247 | |
| 248 When you have the connection URL, instanciating the service is quite simple. | |
| 249 Depending on the type of service, you will use either {\vcode getStore()} or | |
| 250 {\vcode getTransport()}. For example, for store services, use: | |
| 251 | |
| 252 \begin{lstlisting} | |
| 253 vmime::utility:url url("imap://user:pass@imap.example.com"); | |
| 254 vmime::shared_ptr <vmime::net::store> st = sess->getStore(url); | |
| 255 \end{lstlisting} | |
| 256 | |
| 257 and for transport services: | |
| 258 | |
| 259 \begin{lstlisting} | |
| 260 vmime::utility:url url("smtp://smtp.example.com"); | |
| 261 vmime::shared_ptr <vmime::net::transport> tr = sess->getTransport(url); | |
| 262 \end{lstlisting} | |
| 263 | |
| 264 | |
| 265 % ============================================================================ | |
| 266 \section{User credentials and authenticators} | |
| 267 | |
| 268 Some services need some user credentials (eg. username and password) to open | |
| 269 a session. In VMime, user credentials can be specified in the session | |
| 270 properties or by using a custom authenticator (callback). | |
| 271 | |
| 272 \begin{lstlisting}[caption={Setting user credentials using session | |
| 273 properties}] | |
| 274 vmime::shared_ptr <vmime::net::session> sess; // Suppose we have a session | |
| 275 | |
| 276 sess->getProperties()["store.imap.auth.username"] = "vincent"; | |
| 277 sess->getProperties()["store.imap.auth.password"] = "my-password"; | |
| 278 \end{lstlisting} | |
| 279 | |
| 280 Although not recommended, you can also specify username and password | |
| 281 directly in the connection URL, | |
| 282 ie: \emph{imap://username:password@imap.example.com/}. This works only for | |
| 283 services requiring an username and a password as user credentials, and no | |
| 284 other information. | |
| 285 | |
| 286 Sometimes, it may not be very convenient to set username/password in the | |
| 287 session properties, or not possible (eg. extended SASL mechanisms) . That's | |
| 288 why VMime offers an alternate way of getting user credentials: the | |
| 289 {\vcode authenticator} object. Basically, an authenticator is an object that | |
| 290 can return user credentials on-demand (like a callback). | |
| 291 | |
| 292 Currently, there are two types of authenticator in VMime: a basic | |
| 293 authenticator (class {\vcode vmime::security::authenticator}) and, if SASL | |
| 294 support is enabled, a SASL authenticator | |
| 295 (class {\vcode vmime::security::sasl::SASLAuthenticator}). Usually, you | |
| 296 should use the default implementations, or at least make your own | |
| 297 implementation inherit from them. | |
| 298 | |
| 299 The following example shows how to use a custom authenticator to request | |
| 300 the user to enter her/his credentials: | |
| 301 | |
| 302 \begin{lstlisting}[caption={A simple interactive authenticator}] | |
| 303 class myAuthenticator : public vmime::security::defaultAuthenticator | |
| 304 { | |
| 305 const string getUsername() const | |
| 306 { | |
| 307 std::cout << "Enter your username: " << std::endl; | |
| 308 | |
| 309 vmime::string res; | |
| 310 std::getline(std::cin, res); | |
| 311 | |
| 312 return res; | |
| 313 } | |
| 314 | |
| 315 const string getPassword() const | |
| 316 { | |
| 317 std::cout << "Enter your password: " << std::endl; | |
| 318 | |
| 319 vmime::string res; | |
| 320 std::getline(std::cin, res); | |
| 321 | |
| 322 return res; | |
| 323 } | |
| 324 }; | |
| 325 \end{lstlisting} | |
| 326 | |
| 327 This is how to use it: | |
| 328 | |
| 329 \begin{lstlisting} | |
| 330 // First, create a session | |
| 331 vmime::shared_ptr <vmime::net::session> sess = | |
| 332 vmime::make_shared <vmime::net::session>(); | |
| 333 | |
| 334 // Next, initialize a service which will use our authenticator | |
| 335 vmime::shared_ptr <vmime::net::store> st = | |
| 336 sess->getStore(vmime::utility::url("imap://imap.example.com"), | |
| 337 /* use our authenticator */ vmime::make_shared <myAuthenticator>()); | |
| 338 \end{lstlisting} | |
| 339 | |
| 340 \vnote{An authenticator object should be used with one and only one service | |
| 341 at a time. This is required because the authentication process may need to | |
| 342 retrieve the service name (SASL).} | |
| 343 | |
| 344 Of course, this example is quite simplified. For example, if several | |
| 345 authentication mechanisms are tried, the user may be requested to enter the | |
| 346 same information multiple times. See {\vexample Example6} for a more complex | |
| 347 implementation of an authenticator, with caching support. | |
| 348 | |
| 349 If you want to use SASL (ie. if \emph{options.sasl} is set to \emph{true}), | |
| 350 your authenticator must inherit from | |
| 351 {\vcode vmime::security::sasl::SASLAuthenticator} or | |
| 352 {\vcode vmime::security::sasl::defaultSASLAuthenticator}, even if you do not | |
| 353 use the SASL-specific methods {\vcode getAcceptableMechanisms()} and | |
| 354 {\vcode setSASLMechanism()}. Have a look at {\vexample Example6} to see an | |
| 355 implementation of an SASL authenticator. | |
| 356 | |
| 357 \begin{lstlisting}[caption={A simple SASL authenticator}] | |
| 358 class mySASLAuthenticator : public vmime::security::sasl::defaultSASLAuthenticator | |
| 359 { | |
| 360 typedef vmime::security::sasl::SASLMechanism mechanism; // save us typing | |
| 361 | |
| 362 const std::vector <vmime::shared_ptr <mechanism> > getAcceptableMechanisms | |
| 363 (const std::vector <vmime::shared_ptr <mechanism> >& available, | |
| 364 vmime::shared_ptr <mechanism> suggested) const | |
| 365 { | |
| 366 // Here, you can sort the SASL mechanisms in the order they will be | |
| 367 // tried. If no SASL mechanism is acceptable (ie. for example, not | |
| 368 // enough secure), you can return an empty list. | |
| 369 // | |
| 370 // If you do not want to bother with this, you can simply return | |
| 371 // the default list, which is ordered by security strength. | |
| 372 return defaultSASLAuthenticator:: | |
| 373 getAcceptableMechanisms(available, suggested); | |
| 374 } | |
| 375 | |
| 376 void setSASLMechanism(vmime::shared_ptr <mechanism> mech) | |
| 377 { | |
| 378 // This is called when the authentication process is going to | |
| 379 // try the specified mechanism. | |
| 380 // | |
| 381 // The mechanism name is in mech->getName() | |
| 382 | |
| 383 defaultSASLAuthenticator::setSASLMechanism(mech); | |
| 384 } | |
| 385 | |
| 386 // ...implement getUsername() and getPassword()... | |
| 387 }; | |
| 388 \end{lstlisting} | |
| 389 | |
| 390 | |
| 391 % ============================================================================ | |
| 392 \section{Using transport service} | |
| 393 | |
| 394 You have two possibilities for giving message data to the service when you | |
| 395 want to send a message: | |
| 396 | |
| 397 \begin{itemize} | |
| 398 \item either you have a reference to a message (type {\vcode vmime::message}) | |
| 399 and you can simply call {\vcode send(msg)}; | |
| 400 \item or you only have raw message data (as a string, for example), and you | |
| 401 have to call the second overload of {\vcode send()}, which takes additional | |
| 402 parameters (corresponding to message envelope); | |
| 403 \end{itemize} | |
| 404 | |
| 405 The following example illustrates the use of a transport service to send a | |
| 406 message using the second method: | |
| 407 | |
| 408 \begin{lstlisting}[caption={Using a transport service}] | |
| 409 const vmime::string msgData = | |
| 410 "From: me@example.org \r\n" | |
| 411 "To: you@example.org \r\n" | |
| 412 "Date: Sun, Oct 30 2005 17:06:42 +0200 \r\n" | |
| 413 "Subject: Test \r\n" | |
| 414 "\r\n" | |
| 415 "Message body"; | |
| 416 | |
| 417 // Create a new session | |
| 418 vmime::utility::url url("smtp://example.com"); | |
| 419 | |
| 420 vmime::shared_ptr <vmime::net::session> sess = | |
| 421 vmime::make_shared <vmime::net::session>(); | |
| 422 | |
| 423 // Create an instance of the transport service | |
| 424 vmime::shared_ptr <vmime::net::transport> tr = sess->getTransport(url); | |
| 425 | |
| 426 // Connect it | |
| 427 tr->connect(); | |
| 428 | |
| 429 // Send the message | |
| 430 vmime::utility::inputStreamStringAdapter is(msgData); | |
| 431 | |
| 432 vmime::mailbox from("me@example.org"); | |
| 433 vmime::mailboxList to; | |
| 434 to.appendMailbox(vmime::make_shared <vmime::mailbox>("you@example.org")); | |
| 435 | |
| 436 tr->send( | |
| 437 /* expeditor */ from, | |
| 438 /* recipient(s) */ to, | |
| 439 /* data */ is, | |
| 440 /* total length */ msgData.length()); | |
| 441 | |
| 442 // We have finished using the service | |
| 443 tr->disconnect(); | |
| 444 \end{lstlisting} | |
| 445 | |
| 446 \vnote{Exceptions can be thrown at any time when using a service. For better | |
| 447 clarity, exceptions are not caught here, but be sure to catch them in your own | |
| 448 application to provide error feedback to the user.} | |
| 449 | |
| 450 If you use SMTP, you can enable authentication by setting some properties | |
| 451 on the session object ({\vcode service::setProperty()} is a shortcut for | |
| 452 setting properties on the session with the correct prefix): | |
| 453 | |
| 454 \begin{lstlisting} | |
| 455 tr->setProperty("options.need-authentication", true); | |
| 456 tr->setProperty("auth.username", "user"); | |
| 457 tr->setProperty("auth.password", "password"); | |
| 458 \end{lstlisting} | |
| 459 | |
| 460 | |
| 461 % ============================================================================ | |
| 462 \section{Using store service} | |
| 463 | |
| 464 \subsection{Connecting to a store} % ----------------------------------------- | |
| 465 | |
| 466 The first basic step for using a store service is to connect to it. The | |
| 467 following example shows how to initialize a session and instanciate the | |
| 468 store service: | |
| 469 | |
| 470 \begin{lstlisting}[caption={Connecting to a store service}] | |
| 471 // Create a new session | |
| 472 vmime::utility::url url("imap://vincent:password@imap:example.org"); | |
| 473 | |
| 474 vmime::shared_ptr <vmime::net::session> sess = | |
| 475 vmime::make_shared <vmime::net::session>(); | |
| 476 | |
| 477 // Create an instance of the transport service | |
| 478 vmime::shared_ptr <vmime::net::store> store = sess->getStore(url); | |
| 479 | |
| 480 // Connect it | |
| 481 store->connect(); | |
| 482 \end{lstlisting} | |
| 483 | |
| 484 \vnote{{\vexample Example6} contains a more complete example for connecting | |
| 485 to a store service, with support for a custom authenticator.} | |
| 486 | |
| 487 \subsection{Opening a folder} % ---------------------------------------------- | |
| 488 | |
| 489 You can open a folder using two different access modes: either in | |
| 490 \emph{read-only} mode (where you can only read message flags and contents), or | |
| 491 in \emph{read-write} mode (where you can read messages, but also delete them | |
| 492 or add new ones). When you have a reference to a folder, simply call the | |
| 493 {\vcode open()} method with the desired access mode: | |
| 494 | |
| 495 \begin{lstlisting} | |
| 496 folder->open(vmime::net::folder::MODE_READ_WRITE); | |
| 497 \end{lstlisting} | |
| 498 | |
| 499 \vnote{Not all stores support the \emph{read-write} mode. By default, if the | |
| 500 \emph{read-write} mode is not available, the folder silently fall backs on | |
| 501 the \emph{read-only} mode, unless the \emph{failIfModeIsNotAvailable} argument | |
| 502 to {\vcode open()} is set to true.} | |
| 503 | |
| 504 Call {\vcode getDefaultFolder()} on the store to obtain a reference to the | |
| 505 default folder, which is usually the INBOX folder (where messages arrive when | |
| 506 they are received). | |
| 507 | |
| 508 You can also open a specific folder by specifying its path. The following | |
| 509 example will open a folder named \emph{bar}, which is a child of \emph{foo} | |
| 510 in the root folder: | |
| 511 | |
| 512 \begin{lstlisting}[caption={Opening a folder from its path}] | |
| 513 vmime::net::folder::path path; | |
| 514 path /= vmime::net::folder::path::component("foo"); | |
| 515 path /= vmime::net::folder::path::component("bar"); | |
| 516 | |
| 517 vmime::shared_ptr <vmime::net::folder> fld = store->getFolder(path); | |
| 518 fld->open(vmime::net::folder::MODE_READ_WRITE); | |
| 519 \end{lstlisting} | |
| 520 | |
| 521 \vnote{You can specify a path as a string as there is no way to get the | |
| 522 separator used to delimitate path components. Always use {\vcode operator/=} | |
| 523 or {\vcode appendComponent}.} | |
| 524 | |
| 525 \vnote{Path components are of type {\vcode vmime::word}, which means that | |
| 526 VMime supports folder names with extended characters, not only 7-bit | |
| 527 US-ASCII. However, be careful that this may not be supported by the | |
| 528 underlying store protocol (IMAP supports it, because it uses internally a | |
| 529 modified UTF-7 encoding).} | |
| 530 | |
| 531 \subsection{Fetching messages} % --------------------------------------------- | |
| 532 | |
| 533 You can fetch some information about a message without having to download the | |
| 534 whole message. Moreover, folders support fetching for multiple messages in | |
| 535 a single request, for better performance. The following items are currently | |
| 536 available for fetching: | |
| 537 | |
| 538 \begin{itemize} | |
| 539 \item {\bf envelope}: sender, recipients, date and subject; | |
| 540 \item {\bf structure}: MIME structure of the message; | |
| 541 \item {\bf content-info}: content-type of the root part; | |
| 542 \item {\bf flags}: message flags; | |
| 543 \item {\bf size}: message size; | |
| 544 \item {\bf header}: retrieve all the header fields of a message; | |
| 545 \item {\bf uid}: unique identifier of a message; | |
| 546 \item {\bf importance}: fetch header fields suitable for use with | |
| 547 {\vcode misc::importanceHelper}. | |
| 548 \end{itemize} | |
| 549 | |
| 550 \vnote{Not all services support all fetchable items. Call | |
| 551 {\vcode getFetchCapabilities()} on a folder to know which information can be | |
| 552 fetched by a service.} | |
| 553 | |
| 554 The following code shows how to list all the messages in a folder, and | |
| 555 retrieve basic information to show them to the user: | |
| 556 | |
| 557 \begin{lstlisting}[caption={Fetching information about multiple messages}] | |
| 558 std::vector <ref <vmime::net::message> > allMessages = | |
| 559 folder->getMessages(vmime::net::messageSet::byNumber(1, -1)); | |
| 560 // -1 is a special value to mean "the number of the last message in the folder" | |
| 561 | |
| 562 folder->fetchMessages(allMessages, | |
| 563 vmime::net::fetchAttributes::FLAGS | | |
| 564 vmime::net::fetchAttributes::ENVELOPE); | |
| 565 | |
| 566 for (unsigned int i = 0 ; i < allMessages.size() ; ++i) | |
| 567 { | |
| 568 vmime::shared_ptr <vmime::net::message> msg = allMessages[i]; | |
| 569 | |
| 570 const int flags = msg->getFlags(); | |
| 571 | |
| 572 std::cout << "Message " << i << ":" << std::endl; | |
| 573 | |
| 574 if (flags & vmime::net::message::FLAG_SEEN) | |
| 575 std::cout << " - is read" << std::endl; | |
| 576 if (flags & vmime::net::message::FLAG_DELETED) | |
| 577 std::cout << " - is deleted" << std::endl; | |
| 578 | |
| 579 vmime::shared_ptr <const vmime::header> hdr = msg->getHeader(); | |
| 580 | |
| 581 std::cout << " - sent on " << hdr->Date()->generate() << std::endl; | |
| 582 std::cout << " - sent by " << hdr->From()->generate() << std::endl; | |
| 583 } | |
| 584 \end{lstlisting} | |
| 585 | |
| 586 IMAP supports fetching specific header fields of a message. Here is how to use | |
| 587 the {\vcode fetchAttributes} object to do it: | |
| 588 | |
| 589 \begin{lstlisting}[caption={Using fetchAttributes object to fetch specific header fields of a message}] | |
| 590 | |
| 591 // Fetch message flags and the "Received" and "X-Mailer" header fields | |
| 592 vmime::net::fetchAttributes fetchAttribs; | |
| 593 fetchAttribs.add(vmime::net::fetchAttributes::FLAGS); | |
| 594 fetchAttribs.add("Received"); | |
| 595 fetchAttribs.add("X-Mailer"); | |
| 596 | |
| 597 folder->fetchMessages(allMessages, fetchAttribs); | |
| 598 \end{lstlisting} | |
| 599 | |
| 600 | |
| 601 \subsection{Extracting messages and parts} | |
| 602 | |
| 603 To extract the whole contents of a message (including headers), use the | |
| 604 {\vcode extract()} method on a {\vcode vmime::net::message} object. The | |
| 605 following example extracts the first message in the default folder: | |
| 606 | |
| 607 \begin{lstlisting}[caption={Extracting messages}] | |
| 608 // Get a reference to the folder and to its first message | |
| 609 vmime::shared_ptr <vmime::net::folder> folder = store->getDefaultFolder(); | |
| 610 vmime::shared_ptr <vmime::net::message> msg = folder->getMessage(1); | |
| 611 | |
| 612 // Write the message contents to the standard output | |
| 613 vmime::utility::outputStreamAdapter out(std::cout); | |
| 614 msg->extract(out); | |
| 615 \end{lstlisting} | |
| 616 | |
| 617 Some protocols (like IMAP) also support the extraction of specific MIME parts | |
| 618 of a message without downloading the whole message. This can save bandwidth | |
| 619 and time. The method {\vcode extractPart()} is used in this case: | |
| 620 | |
| 621 \begin{lstlisting}[caption={Extracting a specific MIME part of a message}] | |
| 622 // Fetching structure is required before extracting a part | |
| 623 folder->fetchMessage(msg, vmime::net::fetchAttributes::STRUCTURE); | |
| 624 | |
| 625 // Now, we can extract the part | |
| 626 msg->extractPart(msg->getStructure()->getPartAt(0)->getPartAt(1)); | |
| 627 \end{lstlisting} | |
| 628 | |
| 629 Suppose we have a message with the following structure: | |
| 630 | |
| 631 \begin{verbatim} | |
| 632 multipart/mixed | |
| 633 text/html | |
| 634 image/jpeg [*] | |
| 635 \end{verbatim} | |
| 636 | |
| 637 The previous example will extract the header and body of the \emph{image/jpeg} | |
| 638 part. | |
| 639 | |
| 640 \subsection{Deleting messages} % --------------------------------------------- | |
| 641 | |
| 642 The following example will delete the second and the third message from the | |
| 643 store. | |
| 644 | |
| 645 \begin{lstlisting}[caption={Deleting messages}] | |
| 646 vmime::shared_ptr <vmime::net::folder> folder = store->getDefaultFolder(); | |
| 647 | |
| 648 folder->deleteMessages(vmime::net::messageSet::byNumber(/* from */ 2, /* to */ 3)); | |
| 649 | |
| 650 // This is equivalent | |
| 651 std::vector <int> nums; | |
| 652 nums.push_back(2); | |
| 653 nums.push_back(3); | |
| 654 folder->deleteMessages(vmime::net::messageSet::byNumber(nums)); | |
| 655 | |
| 656 // This is also equivalent (but will require 2 roundtrips to server) | |
| 657 folder->deleteMessages(vmime::net::messageSet::byNumber(2)); | |
| 658 folder->deleteMessages(vmime::net::messageSet::byNumber(2)); // renumbered, 3 becomes 2 | |
| 659 \end{lstlisting} | |
| 660 | |
| 661 \subsection{Events} % -------------------------------------------------------- | |
| 662 | |
| 663 As a result of executing some operation (or from time to time, even if no | |
| 664 operation has been performed), a store service can send events to notify you | |
| 665 that something has changed (eg. the number of messages in a folder). These | |
| 666 events may allow you to update the user interface associated to a message | |
| 667 store. | |
| 668 | |
| 669 Currently, there are three types of event: | |
| 670 | |
| 671 \begin{itemize} | |
| 672 \item {\bf message change}: sent when the number of messages in a folder | |
| 673 has changed (ie. some messages have been added or removed); | |
| 674 \item {\bf message count change}: sent when one or more message(s) have | |
| 675 changed (eg. flags or deleted status); | |
| 676 \item {\bf folder change}: sent when a folder has been created, renamed or | |
| 677 deleted. | |
| 678 \end{itemize} | |
| 679 | |
| 680 You can register a listener for each event type by using the corresponding | |
| 681 methods on a {\vcode folder} object: {\vcode addMessageChangedListener()}, | |
| 682 {\vcode addMessageCountListener()} or {\vcode addFolderListener()}. For more | |
| 683 information, please read the class documentation for | |
| 684 {\vcode vmime::net::events} namespace. | |
| 685 | |
| 686 | |
| 687 % ============================================================================ | |
| 688 \section{Handling timeouts} | |
| 689 | |
| 690 Unexpected errors can occur while messaging services are performing | |
| 691 operations and waiting a response from the server (eg. server stops | |
| 692 responding, network link falls down). As all operations as synchronous, | |
| 693 they can be ``blocked'' a long time before returning (in fact, they loop | |
| 694 until they either receive a response from the server, or the underlying | |
| 695 socket system returns an error). | |
| 696 | |
| 697 VMime provides a mechanism to control the duration of operations. This | |
| 698 mechanism allows the program to cancel an operation that is currently | |
| 699 running. | |
| 700 | |
| 701 An interface called {\vcode timeoutHandler} is provided: | |
| 702 | |
| 703 \begin{lstlisting} | |
| 704 class timeoutHandler : public object | |
| 705 { | |
| 706 /** Called to test if the time limit has been reached. | |
| 707 * | |
| 708 * @return true if the timeout delay is elapsed | |
| 709 */ | |
| 710 virtual const bool isTimeOut() = 0; | |
| 711 | |
| 712 /** Called to reset the timeout counter. | |
| 713 */ | |
| 714 virtual void resetTimeOut() = 0; | |
| 715 | |
| 716 /** Called when the time limit has been reached (when | |
| 717 * isTimeOut() returned true). | |
| 718 * | |
| 719 * @return true to continue (and reset the timeout) | |
| 720 * or false to cancel the current operation | |
| 721 */ | |
| 722 virtual const bool handleTimeOut() = 0; | |
| 723 }; | |
| 724 \end{lstlisting} | |
| 725 | |
| 726 While the operation runs, the service calls {\vcode isTimeout()} at variable | |
| 727 intervals. If the {\vcode isTimeout()} function returns {\vcode true}, | |
| 728 then {\vcode handleTimeout()} is called. If the {\vcode handleTimeout()} | |
| 729 function returns {\vcode false}, the operation is cancelled and | |
| 730 an {\vcode operation\_timed\_out} exception is thrown. Else, if | |
| 731 {\vcode handleTimeout()} returns true, the operation continues and the | |
| 732 timeout counter is reset. | |
| 733 The function {\vcode resetTimeout()} is called each time data has | |
| 734 been received from the server to reset the timeout delay. | |
| 735 | |
| 736 When using a service, a default timeout handler is set: if an operation | |
| 737 is blocked for more than 30 seconds (ie. network link is down and no data | |
| 738 was received since 30 seconds), an {\vcode operation\_timed\_out} exception | |
| 739 is thrown. | |
| 740 | |
| 741 The following example shows how to implement a simple timeout handler: | |
| 742 | |
| 743 \begin{lstlisting}[caption={Implementing a simple timeout handler}] | |
| 744 class myTimeoutHandler : public vmime::net::timeoutHandler | |
| 745 { | |
| 746 public: | |
| 747 | |
| 748 myTimeoutHandler() | |
| 749 { | |
| 750 m_startTime = time(NULL); | |
| 751 } | |
| 752 | |
| 753 const bool isTimeOut() | |
| 754 { | |
| 755 return (time(NULL) >= m_startTime + 30); // 30 seconds timeout | |
| 756 } | |
| 757 | |
| 758 void resetTimeOut() | |
| 759 { | |
| 760 m_startTime = time(NULL); | |
| 761 } | |
| 762 | |
| 763 const bool handleTimeOut() | |
| 764 { | |
| 765 std::cout << "Operation timed out." << std::endl; | |
| 766 << "Press [Y] to continue, or [N] to " | |
| 767 << "cancel the operation." << std::endl; | |
| 768 | |
| 769 std::string response; | |
| 770 std::cin >> response; | |
| 771 | |
| 772 return (response == "y" || response == "Y"); | |
| 773 } | |
| 774 | |
| 775 private: | |
| 776 | |
| 777 time_t m_startTime; | |
| 778 }; | |
| 779 \end{lstlisting} | |
| 780 | |
| 781 To make the service use your timeout handler, you need to write a factory | |
| 782 class, to allow the service to create instances of the handler class. This | |
| 783 is required because the service can use several connections to the server | |
| 784 simultaneously, and each connection needs its own timeout handler. | |
| 785 | |
| 786 \begin{lstlisting} | |
| 787 class myTimeoutHandlerFactory : public vmime::net::timeoutHandlerFactory | |
| 788 { | |
| 789 public: | |
| 790 | |
| 791 ref <timeoutHandler> create() | |
| 792 { | |
| 793 return vmime::make_shared <myTimeoutHandler>(); | |
| 794 } | |
| 795 }; | |
| 796 \end{lstlisting} | |
| 797 | |
| 798 Then, call the {\vcode setTimeoutHandlerFactory()} method on the service object | |
| 799 to set the timeout handler factory to use during the session: | |
| 800 | |
| 801 \begin{lstlisting} | |
| 802 theService->setTimeoutHandlerFactory(vmime::make_shared <myTimeoutHandlerFactory>()); | |
| 803 \end{lstlisting} | |
| 804 | |
| 805 | |
| 806 % ============================================================================ | |
| 807 \newpage | |
| 808 \section{Secured connection using TLS/SSL} | |
| 809 | |
| 810 \subsection{Introduction} % -------------------------------------------------- | |
| 811 | |
| 812 If you have enabled TLS support in VMime, you can configure messaging services | |
| 813 so that they use a secured connection. | |
| 814 | |
| 815 Quoting from RFC-2246 - the TLS 1.0 protocol specification: \emph{`` The TLS | |
| 816 protocol provides communications privacy over the Internet. The protocol | |
| 817 allows client/server applications to communicate in a way that is designed | |
| 818 to prevent eavesdropping, tampering, or message forgery.''} | |
| 819 | |
| 820 TLS has the following advantages: | |
| 821 | |
| 822 \begin{itemize} | |
| 823 \item authentication: server identity can be verified; | |
| 824 \item privacy: transmission of data between client and server cannot be read | |
| 825 by someone in the middle of the connection; | |
| 826 \item integrity: original data which is transferred between a client and a | |
| 827 server can not be modified by an attacker without being detected. | |
| 828 \end{itemize} | |
| 829 | |
| 830 \vnote{What is the difference between SSL and TLS? SSL is a protocol designed | |
| 831 by Netscape. TLS is a standard protocol, and is partly based on version 3 of | |
| 832 the SSL protocol. The two protocols are not interoperable, but TLS does | |
| 833 support a mechanism to back down to SSL 3.} | |
| 834 | |
| 835 VMime offers two possibilities for using a secured connection: | |
| 836 | |
| 837 \begin{itemize} | |
| 838 \item you can connect to a server listening on a special port (eg. IMAPS | |
| 839 instead of IMAP): this is the classical use of SSL, but is now deprecated; | |
| 840 \item connect to a server listening on the default port, and then begin a | |
| 841 secured connection: this is STARTTLS. | |
| 842 \end{itemize} | |
| 843 | |
| 844 | |
| 845 \subsection{Setting up a secured connection} % ------------------------------- | |
| 846 | |
| 847 \subsubsection{Connecting to a ``secured'' port} % ........................... | |
| 848 | |
| 849 To use the classical SSL/TLS way, simply use the ``S'' version of the protocol | |
| 850 to connect to the server (eg. \emph{imaps} instead of \emph{imap}). This is | |
| 851 currently available for SMTP, POP3 and IMAP. | |
| 852 | |
| 853 \begin{lstlisting} | |
| 854 vmime::shared_ptr <vmime::net::store> store = | |
| 855 theSession->getStore(vmime::utility::url("imaps://example.org")); | |
| 856 \end{lstlisting} | |
| 857 | |
| 858 \subsubsection{Using STARTTLS} % ............................................. | |
| 859 | |
| 860 To make the service start a secured session using the STARTTLS method, simply | |
| 861 set the \emph{connection.tls} property: | |
| 862 | |
| 863 \begin{lstlisting} | |
| 864 theService->setProperty("connection.tls", true); | |
| 865 \end{lstlisting} | |
| 866 | |
| 867 \vnote{If, for some reason, a secured connection cannot be started, the | |
| 868 default behaviour is to fallback on a normal connection. To make | |
| 869 {\vcode connect()} fail if STARTTLS fails, set the | |
| 870 \emph{connection.tls.required} to \emph{true}.} | |
| 871 | |
| 872 \subsection{Certificate verification} % -------------------------------------- | |
| 873 | |
| 874 \subsubsection{How it works} % ............................................... | |
| 875 | |
| 876 If you tried the previous examples, a | |
| 877 {\vcode certificateException} might have been thrown. | |
| 878 This is because the default certificate verifier in VMime did not manage to | |
| 879 verify the certificate, and so could not trust it. | |
| 880 | |
| 881 Basically, when you connect to a server using TLS, the server responds with | |
| 882 a list of certificates, called a certificate chain (usually, certificates are | |
| 883 of type X.509\footnote{And VMime currently supports only X.509 certificates}). | |
| 884 The certificate chain is ordered so that the first certificate is the subject | |
| 885 certificate, the second is the subject's issuer one, the third is the issuer's | |
| 886 issuer, and so on. | |
| 887 | |
| 888 To decide whether the server can be trusted or not, you have to verify that | |
| 889 \emph{each} certificate is valid (ie. is trusted). For more information | |
| 890 about X.509 and certificate verification, see related articles on Wikipedia | |
| 891 \footnote{See \url{http://wikipedia.org/wiki/Public\_key\_certificate}}. | |
| 892 | |
| 893 \subsubsection{Using the default certificate verifier} % ..................... | |
| 894 | |
| 895 The default certificate verifier maintains a list of root (CAs) and user | |
| 896 certificates that are trusted. By default, the list is empty. So, you have | |
| 897 to initialize it before using the verifier. | |
| 898 | |
| 899 The algorithm\footnote{See | |
| 900 \url{http://wikipedia.org/wiki/Certification\_path\_validation\_algorithm}} | |
| 901 used is quite simple: | |
| 902 | |
| 903 \begin{enumerate} | |
| 904 \item for every certificate in the chain, verify that the certificate has been | |
| 905 issued by the next certificate in the chain; | |
| 906 \item for every certificate in the chain, verify that the certificate is valid | |
| 907 at the current time; | |
| 908 \item ensure that the first certificate's subject name matches the hostname | |
| 909 of the server; | |
| 910 \item decide whether the subject's certificate can be trusted: | |
| 911 \begin{itemize} | |
| 912 \item first, verify that the the last certificate in the chain was | |
| 913 issued by a third-party that we trust (root CAs); | |
| 914 \item if the issuer certificate cannot be verified against root CAs, | |
| 915 compare the subject's certificate against the trusted certificates | |
| 916 (the certificates the user has decided to trust). | |
| 917 \end{itemize} | |
| 918 \end{enumerate} | |
| 919 | |
| 920 First, we need some code to load existing X.509 certificates: | |
| 921 | |
| 922 \begin{lstlisting}[caption={Reading a X.509 certificate from a file}] | |
| 923 vmime::shared_ptr <vmime::security::cert::X509Certificate> | |
| 924 loadX509CertificateFromFile(const std::string& path) | |
| 925 { | |
| 926 std::ifstream certFile; | |
| 927 certFile.open(path.c_str(), std::ios::in | std::ios::binary); | |
| 928 | |
| 929 if (!certFile) | |
| 930 { | |
| 931 // ...handle error... | |
| 932 } | |
| 933 | |
| 934 vmime::utility::inputStreamAdapter is(certFile); | |
| 935 vmime::shared_ptr <vmime::security::cert::X509Certificate> cert; | |
| 936 | |
| 937 // Try DER format | |
| 938 cert = vmime::security::cert::X509Certificate::import | |
| 939 (is, vmime::security::cert::X509Certificate::FORMAT_DER); | |
| 940 | |
| 941 if (cert != NULL) | |
| 942 return cert; | |
| 943 | |
| 944 // Try PEM format | |
| 945 is.reset(); | |
| 946 cert = vmime::security::cert::X509Certificate::import | |
| 947 (is, vmime::security::cert::X509Certificate::FORMAT_PEM); | |
| 948 | |
| 949 return cert; | |
| 950 } | |
| 951 \end{lstlisting} | |
| 952 | |
| 953 Then, we can use the {\vcode loadX509CertificateFromFile} function to load | |
| 954 certificates and initialize the certificate verifier: | |
| 955 | |
| 956 \begin{lstlisting}[caption={Using the default certificate verifier}] | |
| 957 vmime::shared_ptr <vmime::security::cert::defaultCertificateVerifier> vrf = | |
| 958 vmime::make_shared <vmime::security::cert::defaultCertificateVerifier>(); | |
| 959 | |
| 960 // Load root CAs (such as Verisign or Thawte) | |
| 961 std::vector <vmime::shared_ptr <vmime::security::cert::X509Certificate> > rootCAs; | |
| 962 | |
| 963 rootCAs.push_back(loadX509CertificateFromFile("/path/to/root-ca1.cer"); | |
| 964 rootCAs.push_back(loadX509CertificateFromFile("/path/to/root-ca2.cer"); | |
| 965 rootCAs.push_back(loadX509CertificateFromFile("/path/to/root-ca3.cer"); | |
| 966 | |
| 967 vrf->setX509RootCAs(rootCAs); | |
| 968 | |
| 969 // Then, load certificates that the user explicitely chose to trust | |
| 970 std::vector <vmime::shared_ptr <vmime::security::cert::X509Certificate> > trusted; | |
| 971 | |
| 972 trusted.push_back(loadX509CertificateFromFile("/path/to/trusted-site1.cer"); | |
| 973 trusted.push_back(loadX509CertificateFromFile("/path/to/trusted-site2.cer"); | |
| 974 | |
| 975 vrf->setX509TrustedCerts(trusted); | |
| 976 \end{lstlisting} | |
| 977 | |
| 978 | |
| 979 \subsubsection{Writing your own certificate verifier} % ...................... | |
| 980 | |
| 981 If you need to do more complex verifications on certificates, you will have to | |
| 982 write your own verifier. Your verifier should inherit from the | |
| 983 {\vcode vmime::security::cert::certificateVerifier} class and implement the | |
| 984 method {\vcode verify()}. Then, if the specified certificate chain is trusted, | |
| 985 simply return from the function, or else throw a | |
| 986 {\vcode certificateException}. | |
| 987 | |
| 988 The following example shows how to implement an interactive certificate | |
| 989 verifier which relies on the user's decision, and nothing else (you SHOULD NOT | |
| 990 use this in a production application as this is obviously a serious security | |
| 991 issue): | |
| 992 | |
| 993 \begin{lstlisting}[caption={A custom certificate verifier}] | |
| 994 class myCertVerifier : public vmime::security::cert::certificateVerifier | |
| 995 { | |
| 996 public: | |
| 997 | |
| 998 void verify(vmime::shared_ptr <certificateChain> certs) | |
| 999 { | |
| 1000 // Obtain the subject's certificate | |
| 1001 vmime::shared_ptr <vmime::security::cert::certificate> cert = chain->getAt(0); | |
| 1002 | |
| 1003 std::cout << std::endl; | |
| 1004 std::cout << "Server sent a '" << cert->getType() << "'" | |
| 1005 << " certificate." << std::endl; | |
| 1006 std::cout << "Do you want to accept this certificate? (Y/n) "; | |
| 1007 std::cout.flush(); | |
| 1008 | |
| 1009 std::string answer; | |
| 1010 std::getline(std::cin, answer); | |
| 1011 | |
| 1012 if (answer.length() != 0 && (answer[0] == 'Y' || answer[0] == 'y')) | |
| 1013 return; // OK, we trust the certificate | |
| 1014 | |
| 1015 // Don't trust this certificate | |
| 1016 throw vmime::security::cert::certificateException(); | |
| 1017 } | |
| 1018 }; | |
| 1019 \end{lstlisting} | |
| 1020 | |
| 1021 \vnote{In production code, it may be a good idea to remember user's decisions | |
| 1022 about which certificates to trust and which not. See {\vexample Example6} for | |
| 1023 a basic cache implementation.} | |
| 1024 | |
| 1025 Finally, to make the service use your own certificate verifier, simply write: | |
| 1026 | |
| 1027 \begin{lstlisting} | |
| 1028 theService->setCertificateVerifier(vmime::make_shared <myCertVerifier>()); | |
| 1029 \end{lstlisting} | |
| 1030 | |
| 1031 \subsection{SSL/TLS Properties} % -------------------------------------------- | |
| 1032 | |
| 1033 If you want to customize behavior or set some options on TLS/SSL connection, | |
| 1034 you may use the TLSProperties object, and pass it to the service session. The | |
| 1035 TLS/SSL options must be set {\em before} creating any service with the session | |
| 1036 (ie. before calling either {\vcode getStore()} or {\vcode getTransport()} on | |
| 1037 the session), or they will not be used. | |
| 1038 | |
| 1039 The following example shows how to set the cipher suite preferences for TLS: | |
| 1040 | |
| 1041 \begin{lstlisting}[caption={Setting TLS cipher suite preferences}] | |
| 1042 vmime::shared_ptr <vmime::net::session> sess = /* ... */; | |
| 1043 | |
| 1044 vmime::shared_ptr <vmime::net::tls::TLSProperties> tlsProps = | |
| 1045 vmime::make_shared <vmime::net::tls::TLSProperties>(); | |
| 1046 | |
| 1047 // for OpenSSL | |
| 1048 tlsProps->setCipherString("HIGH:!ADH:@STRENGTH"); | |
| 1049 | |
| 1050 // for GNU TLS | |
| 1051 tlsProps->setCipherString("NORMAL:%SSL3_RECORD_VERSION"); | |
| 1052 | |
| 1053 sess->setTLSProperties(tlsProps); | |
| 1054 \end{lstlisting} | |
| 1055 | |
| 1056 Please note that the cipher suite string format and meaning depend on the | |
| 1057 underlying TLS library (either OpenSSL or GNU TLS): | |
| 1058 | |
| 1059 \begin{itemize} | |
| 1060 \item for GNU TLS, read this: \newline | |
| 1061 \url{http://gnutls.org/manual/html\_node/Priority-Strings.html} | |
| 1062 | |
| 1063 \item for OpenSSL, read this: \newline | |
| 1064 \url{http://www.openssl.org/docs/apps/ciphers.html#CIPHER\_STRINGS} | |
| 1065 \end{itemize} | |
| 1066 | |
| 1067 You may also set cipher suite preferences using predefined constants that | |
| 1068 map to generic security modes: | |
| 1069 | |
| 1070 \begin{lstlisting}[caption={Setting TLS cipher suite preferences using predefined modes}] | |
| 1071 sess->setCipherSuite(vmime::net::tls::TLSProperties::CIPHERSUITE_HIGH); | |
| 1072 \end{lstlisting} | |
| 1073 | |
| 1074 The following constants are available: | |
| 1075 | |
| 1076 \noindent\begin{tabularx}{1.0\textwidth}{|l|X|} | |
| 1077 \hline | |
| 1078 {\bf Constant} & | |
| 1079 {\bf Meaning} \\ | |
| 1080 \hline | |
| 1081 CIPHERSUITE\_HIGH & | |
| 1082 High encryption cipher suites ($>$ 128 bits) \\ | |
| 1083 \hline | |
| 1084 CIPHERSUITE\_MEDIUM & | |
| 1085 Medium encryption cipher suites ($>=$ 128 bits) \\ | |
| 1086 \hline | |
| 1087 CIPHERSUITE\_LOW & | |
| 1088 Low encryption cipher suites ($>=$ 64 bits) \\ | |
| 1089 \hline | |
| 1090 CIPHERSUITE\_DEFAULT & | |
| 1091 Default cipher suite (actual cipher suites used depends | |
| 1092 on the underlying SSL/TLS library) \\ | |
| 1093 \hline | |
| 1094 \end{tabularx} | |
| 1095 |
