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