aboutsummaryrefslogtreecommitdiff
path: root/vmime-master/doc/book/net.tex
blob: 3fab903a8f912e3d144849eb2ecc76ae90ee5398 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
\chapter{Working with Messaging Services}

% ============================================================================
\section{Introduction}

In addition to parsing and building MIME messages, VMime also offers a lot of
features to work with messaging services. This includes connecting to remote
messaging stores (like IMAP or POP3), local stores (maildir) and transport
services (send messages over SMTP or local sendmail), through an unified
interface (see Figure \ref{uml_messaging_module}). That means that you can
use independently IMAP of POP3 without having to change any line of code.

Source code of {\vexample Example6} covers all features presented in this
chapter, so it is important you take some time to read it.

\begin{figure}
	\center\includegraphics[width=0.9\textwidth]
		{images/messaging-services.png}\endcenter
	\caption{Overall structure of the messaging module}
	\label{uml_messaging_module}
\end{figure}

The interface is composed of five classes:

\begin{itemize}
\item {\vcode vmime::net::service}: this is the base interface for a
messaging service. It can be either a store service or a transport
service.

\item {\vcode vmime::net::serviceFactory}: create instances of a service.
This is used internally by the session object (see below).

\item {\vcode vmime::net::store}: interface for a store service. A store
service offers access to a set of folders containing messages. This is
used for IMAP, POP3 and maildir.

\item {\vcode vmime::net::transport}: interface for a transport service.
A transport service is capable of sending messages. This is used for
SMTP and sendmail.

\item {\vcode vmime::net::session}: a session object is used to store the
parameters used by a service (eg. connection parameters). Each service
instance is associated with only one session. The session object is capable
of creating instances of services.
\end{itemize}

The following classes are specific to store services:

\begin{itemize}
\item {\vcode vmime::net::folder}: a folder can either contain other folders
or messages, or both.

\item {\vcode vmime::net::message}: this is the interface for dealing with
messages. For a given message, you can have access to its flags, its MIME
structure and you can also extract the whole message data or given parts (if
supported by the underlying protocol).
\end{itemize}


% ============================================================================
\section{Working with sessions}

\subsection{Setting properties} % --------------------------------------------

Sessions are used to store configuration parameters for services. They
contains a set of typed properties that can modify the behaviour of the
services. Before using a messaging service, you must create and
initialize a session object:

\begin{lstlisting}
vmime::shared_ptr <vmime::net::session> theSession = vmime::net::session::create();
\end{lstlisting}

Session properties include:

\begin{itemize}
\item connection parameters: host and port to connect to;
\item authentication parameters: user credentials required to use the
service (if any);
\item protocol-specific parameters: enable or disable extensions (eg. APOP
support in POP3).
\end{itemize}

Properties are stored using a dotted notation, to specify the service type,
the protocol name, the category and the name of the property:

\begin{verbatim}
   {service_type}.{protocol}.category.name
\end{verbatim}

An example of property is \emph{store.pop3.options.apop} (used to enable or
disable the use of APOP authentication). The \emph{store.pop3} part is called
the \emph{prefix}. This allow specifying different values for the same
property depending on the protocol used.

The session properties are stored in a {\vcode vmime::propertySet} object.
To set the value of a property, you can use either:

\begin{lstlisting}
theSession->getProperties().setProperty("property-name", value);
\end{lstlisting}

or:

\begin{lstlisting}
theSession->getProperties()["property-name"] = value;
\end{lstlisting}


\subsection{Available properties} % ------------------------------------------

Following is a list of available properties and the protocols they apply to,
as the time of writing this documentation\footnote{You can get an up-to-date
list of the properties by running \vexample{Example7}}. For better clarity,
the prefixes do not appear in this table.

\begin{table}[!ht]
\noindent\begin{tabularx}{1.0\textwidth}{|l|c|X|c|c|c|c|c|c|c|c|}
\hline
	{\bf Property name} &
	{\bf Type} &
	{\bf Description} &
	\verti{\bf POP3} &
	\verti{\bf POP3S} &
	\verti{\bf IMAP} &
	\verti{\bf IMAPS} &
	\verti{\bf SMTP} &
	\verti{\bf SMTPS} &
	\verti{\bf maildir} &
	\verti{\bf sendmail} \\
\hline
\hline
options.sasl & bool & Set to {\vcode true} to use SASL authentication, if
available. & \vdot & \vdot & \vdot & \vdot & \vdot & \vdot & & \\
\hline
options.sasl.fallback & bool & Fail if SASL authentication failed (do not
try other authentication mechanisms). & \vdot & \vdot & \vdot & \vdot &
\vdot & \vdot & & \\
\hline
auth.username\footnote{You should use authenticators
instead.\label{fn_auth_username}} & string & Set the username of the account
to connect to. & \vdot & \vdot & \vdot & \vdot & \vdot & \vdot & & \\
\hline
auth.password\footref{fn_auth_username} & string & Set the password of the
account. & \vdot & \vdot & \vdot & \vdot & \vdot & \vdot & & \\
\hline
connection.tls & bool & Set to {\vcode true} to start a secured connection
using STARTTLS extension, if available. & \vdot & & \vdot & & \vdot & & & \\
\hline
connection.tls.required & bool & Fail if a secured connection cannot be
started. & \vdot & & \vdot & & \vdot & & & \\
\hline
server.address & string & Server host name or IP address. &\vdot & \vdot &
\vdot & \vdot & \vdot & \vdot & & \\
\hline
server.port & int & Server port. & \vdot & \vdot & \vdot & \vdot &
\vdot & \vdot & & \\
\hline
server.rootpath & string & Root directory for mail repository (eg.
\emph{/home/vincent/Mail}). & & & & & & & \vdot & \\
\hline
\end{tabularx}
\caption{Properties common to all protocols}
\end{table}

\newpage
These are the protocol-specific options:

\begin{table}[!ht]
\noindent\begin{tabularx}{1.0\textwidth}{|l|c|X|}
\hline
	{\bf Property name} &
	{\bf Type} &
	{\bf Description} \\
% POP3/POP3S
\hline
\multicolumn{3}{|c|}{POP3, POP3S} \\
\hline
store.pop3.options.apop & bool & Enable or disable authentication with
APOP (if SASL is enabled, this occurs after all SASL mechanisms have been
tried). \\
\hline
store.pop3.options.apop.fallback & bool & If set to {\vcode true} and
APOP fails, the authentication process fails (ie. unsecure plain text
authentication is not used). \\
\hline
% SMTP
\multicolumn{3}{|c|}{SMTP, SMTPS} \\
\hline
transport.smtp.options.need-authentication & bool & Set to \emph{true} if
the server requires to authenticate before sending messages. \\
\hline
transport.smtp.options.pipelining & bool & Set to {\vcode false} to disable
command pipelining, if the server supports it (default is {\vcode true}). \\
\hline
transport.smtp.options.chunking & bool & Set to {\vcode false} to disable
CHUNKING extension, if the server supports it (default is {\vcode true}). \\
\hline
% sendmail
\multicolumn{3}{|c|}{sendmail} \\
\hline
transport.sendmail.binpath & string & The path to the \emph{sendmail}
executable on your system. The default is the one found by the configuration
script when VMime was built. \\
\hline
\end{tabularx}
\caption{Protocol-specific options}
\end{table}


\subsection{Instanciating services} % ----------------------------------------

You can create a service either by specifying its protocol name, or by
specifying the URL of the service. Creation by name is deprecated so
this chapter only presents the latter option.

The URL scheme for connecting to services is:

\begin{verbatim}
   protocol://[username[:password]@]host[:port]/[root-path]
\end{verbatim}

\vnote{For local services (ie. \emph{sendmail} and \emph{maildir}), the host
part is not used, but it must not be empty (you can use "localhost").}

The following table shows an example URL for each service:

\noindent\begin{tabularx}{1.0\textwidth}{|c|X|}
\hline
	{\bf Service} &
	{\bf Connection URL} \\
\hline
imap, imaps & {\tt imap://imap.example.com},
{\tt imaps://vincent:pass@example.com} \\
\hline
pop3, pop3s & {\tt pop3://pop3.example.com} \\
\hline
smtp, smtps & {\tt smtp://smtp.example.com} \\
\hline
maildir & {\tt maildir://localhost/home/vincent/Mail} (host not used) \\
\hline
sendmail & {\tt sendmail://localhost} (host not used, always localhost) \\
\hline
\end{tabularx}

\newpage

When you have the connection URL, instanciating the service is quite simple.
Depending on the type of service, you will use either {\vcode getStore()} or
{\vcode getTransport()}. For example, for store services, use:

\begin{lstlisting}
vmime::utility:url url("imap://user:pass@imap.example.com");
vmime::shared_ptr <vmime::net::store> st = sess->getStore(url);
\end{lstlisting}

and for transport services:

\begin{lstlisting}
vmime::utility:url url("smtp://smtp.example.com");
vmime::shared_ptr <vmime::net::transport> tr = sess->getTransport(url);
\end{lstlisting}


% ============================================================================
\section{User credentials and authenticators}

Some services need some user credentials (eg. username and password) to open
a session. In VMime, user credentials can be specified in the session
properties or by using a custom authenticator (callback).

\begin{lstlisting}[caption={Setting user credentials using session
properties}]
vmime::shared_ptr <vmime::net::session> sess;  // Suppose we have a session

sess->getProperties()["store.imap.auth.username"] = "vincent";
sess->getProperties()["store.imap.auth.password"] = "my-password";
\end{lstlisting}

Although not recommended, you can also specify username and password
directly in the connection URL,
ie: \emph{imap://username:password@imap.example.com/}. This works only for
services requiring an username and a password as user credentials, and no
other information.

Sometimes, it may not be very convenient to set username/password in the
session properties, or not possible (eg. extended SASL mechanisms) . That's
why VMime offers an alternate way of getting user credentials: the
{\vcode authenticator} object. Basically, an authenticator is an object that
can return user credentials on-demand (like a callback).

Currently, there are two types of authenticator in VMime: a basic
authenticator (class {\vcode vmime::security::authenticator}) and, if SASL
support is enabled, a SASL authenticator
(class {\vcode vmime::security::sasl::SASLAuthenticator}). Usually, you
should use the default implementations, or at least make your own
implementation inherit from them.

The following example shows how to use a custom authenticator to request
the user to enter her/his credentials:

\begin{lstlisting}[caption={A simple interactive authenticator}]
class myAuthenticator : public vmime::security::defaultAuthenticator {

   const string getUsername() const {

      std::cout << "Enter your username: " << std::endl;

      vmime::string res;
      std::getline(std::cin, res);

      return res;
   }

   const string getPassword() const {

      std::cout << "Enter your password: " << std::endl;

      vmime::string res;
      std::getline(std::cin, res);

      return res;
   }
};
\end{lstlisting}

This is how to use it:

\begin{lstlisting}
// First, create a session
vmime::shared_ptr <vmime::net::session> sess = vmime::net::session::create();

// Next, initialize a service which will use our authenticator
vmime::shared_ptr <vmime::net::store> st = sess->getStore(
   vmime::utility::url("imap://imap.example.com"),
   /* use our authenticator */ vmime::make_shared <myAuthenticator>()
);
\end{lstlisting}

\vnote{An authenticator object should be used with one and only one service
at a time. This is required because the authentication process may need to
retrieve the service name (SASL).}

Of course, this example is quite simplified. For example, if several
authentication mechanisms are tried, the user may be requested to enter the
same information multiple times. See  {\vexample Example6} for a more complex
implementation of an authenticator, with caching support.

If you want to use SASL (ie. if \emph{options.sasl} is set to \emph{true}),
your authenticator must inherit from
{\vcode vmime::security::sasl::SASLAuthenticator} or
{\vcode vmime::security::sasl::defaultSASLAuthenticator}, even if you do not
use the SASL-specific methods {\vcode getAcceptableMechanisms()} and
{\vcode setSASLMechanism()}. Have a look at {\vexample Example6} to see an
implementation of an SASL authenticator.

\begin{lstlisting}[caption={A simple SASL authenticator}]
class mySASLAuthenticator : public vmime::security::sasl::defaultSASLAuthenticator {

   typedef vmime::security::sasl::SASLMechanism mechanism;  // save us typing

   const std::vector <vmime::shared_ptr <mechanism> > getAcceptableMechanisms(
      const std::vector <vmime::shared_ptr <mechanism> >& available,
      const vmime::shared_ptr <mechanism>& suggested
   ) const {

      // Here, you can sort the SASL mechanisms in the order they will be
      // tried. If no SASL mechanism is acceptable (ie. for example, not
      // enough secure), you can return an empty list.
      //
      // If you do not want to bother with this, you can simply return
      // the default list, which is ordered by security strength.
      return defaultSASLAuthenticator::
         getAcceptableMechanisms(available, suggested);
   }

   void setSASLMechanism(const vmime::shared_ptr <mechanism>& mech) {

      // This is called when the authentication process is going to
      // try the specified mechanism.
      //
      // The mechanism name is in mech->getName()

      defaultSASLAuthenticator::setSASLMechanism(mech);
   }

   // ...implement getUsername() and getPassword()...
};
\end{lstlisting}


% ============================================================================
\section{Using transport service}

You have two possibilities for giving message data to the service when you
want to send a message:

\begin{itemize}
\item either you have a reference to a message (type {\vcode vmime::message})
and you can simply call {\vcode send(msg)};
\item or you only have raw message data (as a string, for example), and you
have to call the second overload of {\vcode send()}, which takes additional
parameters (corresponding to message envelope);
\end{itemize}

The following example illustrates the use of a transport service to send a
message using the second method:

\begin{lstlisting}[caption={Using a transport service}]
const vmime::string msgData =
   "From: me@example.org \r\n"
   "To: you@example.org \r\n"
   "Date: Sun, Oct 30 2005 17:06:42 +0200 \r\n"
   "Subject: Test \r\n"
   "\r\n"
   "Message body";

// Create a new session
vmime::utility::url url("smtp://example.com");

vmime::shared_ptr <vmime::net::session> sess = vmime::net::session::create();

// Create an instance of the transport service
vmime::shared_ptr <vmime::net::transport> tr = sess->getTransport(url);

// Connect it
tr->connect();

// Send the message
vmime::utility::inputStreamStringAdapter is(msgData);

vmime::mailbox from("me@example.org");
vmime::mailboxList to;
to.appendMailbox(vmime::make_shared <vmime::mailbox>("you@example.org"));

tr->send(
   /* expeditor */    from,
   /* recipient(s) */ to,
   /* data */         is,
   /* total length */ msgData.length()
);

// We have finished using the service
tr->disconnect();
\end{lstlisting}

\vnote{Exceptions can be thrown at any time when using a service. For better
clarity, exceptions are not caught here, but be sure to catch them in your own
application to provide error feedback to the user.}

If you use SMTP, you can enable authentication by setting some properties
on the session object ({\vcode service::setProperty()} is a shortcut for
setting properties on the session with the correct prefix):

\begin{lstlisting}
tr->setProperty("options.need-authentication", true);
tr->setProperty("auth.username", "user");
tr->setProperty("auth.password", "password");
\end{lstlisting}


% ============================================================================
\section{Using store service}

\subsection{Connecting to a store} % -----------------------------------------

The first basic step for using a store service is to connect to it. The
following example shows how to initialize a session and instanciate the
store service:

\begin{lstlisting}[caption={Connecting to a store service}]
// Create a new session
vmime::utility::url url("imap://vincent:password@imap:example.org");

vmime::shared_ptr <vmime::net::session> sess = vmime::net::session::create();

// Create an instance of the transport service
vmime::shared_ptr <vmime::net::store> store = sess->getStore(url);

// Connect it
store->connect();
\end{lstlisting}

\vnote{{\vexample Example6} contains a more complete example for connecting
to a store service, with support for a custom authenticator.}

\subsection{Opening a folder} % ----------------------------------------------

You can open a folder using two different access modes: either in
\emph{read-only} mode (where you can only read message flags and contents), or
in \emph{read-write} mode (where you can read messages, but also delete them
or add new ones). When you have a reference to a folder, simply call the
{\vcode open()} method with the desired access mode:

\begin{lstlisting}
folder->open(vmime::net::folder::MODE_READ_WRITE);
\end{lstlisting}

\vnote{Not all stores support the \emph{read-write} mode. By default, if the
\emph{read-write} mode is not available, the folder silently fall backs on
the \emph{read-only} mode, unless the \emph{failIfModeIsNotAvailable} argument
to {\vcode open()} is set to true.}

Call {\vcode getDefaultFolder()} on the store to obtain a reference to the
default folder, which is usually the INBOX folder (where messages arrive when
they are received).

You can also open a specific folder by specifying its path. The following
example will open a folder named \emph{bar}, which is a child of \emph{foo}
in the root folder:

\begin{lstlisting}[caption={Opening a folder from its path}]
vmime::net::folder::path path;
path /= vmime::net::folder::path::component("foo");
path /= vmime::net::folder::path::component("bar");

vmime::shared_ptr <vmime::net::folder> fld = store->getFolder(path);
fld->open(vmime::net::folder::MODE_READ_WRITE);
\end{lstlisting}

\vnote{You can specify a path as a string as there is no way to get the
separator used to delimitate path components. Always use {\vcode operator/=}
or {\vcode appendComponent}.}

\vnote{Path components are of type {\vcode vmime::word}, which means that
VMime supports folder names with extended characters, not only 7-bit
US-ASCII. However, be careful that this may not be supported by the
underlying store protocol (IMAP supports it, because it uses internally a
modified UTF-7 encoding).}

\subsection{Fetching messages} % ---------------------------------------------

You can fetch some information about a message without having to download the
whole message. Moreover, folders support fetching for multiple messages in
a single request, for better performance. The following items are currently
available for fetching:

\begin{itemize}
\item {\bf envelope}: sender, recipients, date and subject;
\item {\bf structure}: MIME structure of the message;
\item {\bf content-info}: content-type of the root part;
\item {\bf flags}: message flags;
\item {\bf size}: message size;
\item {\bf header}: retrieve all the header fields of a message;
\item {\bf uid}: unique identifier of a message;
\item {\bf importance}: fetch header fields suitable for use with
{\vcode misc::importanceHelper}.
\end{itemize}

\vnote{Not all services support all fetchable items. Call
{\vcode getFetchCapabilities()} on a folder to know which information can be
fetched by a service.}

The following code shows how to list all the messages in a folder, and
retrieve basic information to show them to the user:

\begin{lstlisting}[caption={Fetching information about multiple messages}]
std::vector <ref <vmime::net::message> > allMessages =
   folder->getMessages(vmime::net::messageSet::byNumber(1, -1));
      // -1 is a special value to mean "the number of the last message in the folder"

folder->fetchMessages(
   allMessages,
   vmime::net::fetchAttributes::FLAGS |
   vmime::net::fetchAttributes::ENVELOPE
);

for (unsigned int i = 0 ; i < allMessages.size() ; ++i) {

   vmime::shared_ptr <vmime::net::message> msg = allMessages[i];

   const int flags = msg->getFlags();

   std::cout << "Message " << i << ":" << std::endl;

   if (flags & vmime::net::message::FLAG_SEEN) {
      std::cout << " - is read" << std::endl;
   }
   if (flags & vmime::net::message::FLAG_DELETED) {
      std::cout << " - is deleted" << std::endl;
   }

   vmime::shared_ptr <const vmime::header> hdr = msg->getHeader();

   std::cout << " - sent on " << hdr->Date()->generate() << std::endl;
   std::cout << " - sent by " << hdr->From()->generate() << std::endl;
}
\end{lstlisting}

IMAP supports fetching specific header fields of a message. Here is how to use
the {\vcode fetchAttributes} object to do it:

\begin{lstlisting}[caption={Using fetchAttributes object to fetch specific header fields of a message}]

// Fetch message flags and the "Received" and "X-Mailer" header fields
vmime::net::fetchAttributes fetchAttribs;
fetchAttribs.add(vmime::net::fetchAttributes::FLAGS);
fetchAttribs.add("Received");
fetchAttribs.add("X-Mailer");

folder->fetchMessages(allMessages, fetchAttribs);
\end{lstlisting}


\subsection{Extracting messages and parts}

To extract the whole contents of a message (including headers), use the
{\vcode extract()} method on a {\vcode vmime::net::message} object. The
following example extracts the first message in the default folder:

\begin{lstlisting}[caption={Extracting messages}]
// Get a reference to the folder and to its first message
vmime::shared_ptr <vmime::net::folder> folder = store->getDefaultFolder();
vmime::shared_ptr <vmime::net::message> msg = folder->getMessage(1);

// Write the message contents to the standard output
vmime::utility::outputStreamAdapter out(std::cout);
msg->extract(out);
\end{lstlisting}

Some protocols (like IMAP) also support the extraction of specific MIME parts
of a message without downloading the whole message. This can save bandwidth
and time. The method {\vcode extractPart()} is used in this case:

\begin{lstlisting}[caption={Extracting a specific MIME part of a message}]
// Fetching structure is required before extracting a part
folder->fetchMessage(msg, vmime::net::fetchAttributes::STRUCTURE);

// Now, we can extract the part
msg->extractPart(msg->getStructure()->getPartAt(0)->getPartAt(1));
\end{lstlisting}

Suppose we have a message with the following structure:

\begin{verbatim}
   multipart/mixed
      text/html
      image/jpeg [*]
\end{verbatim}

The previous example will extract the header and body of the \emph{image/jpeg}
part.

\subsection{Deleting messages} % ---------------------------------------------

The following example will delete the second and the third message from the
store.

\begin{lstlisting}[caption={Deleting messages}]
vmime::shared_ptr <vmime::net::folder> folder = store->getDefaultFolder();

folder->deleteMessages(vmime::net::messageSet::byNumber(/* from */ 2, /* to */ 3));

// This is equivalent
std::vector <int> nums;
nums.push_back(2);
nums.push_back(3);
folder->deleteMessages(vmime::net::messageSet::byNumber(nums));

// This is also equivalent (but will require 2 roundtrips to server)
folder->deleteMessages(vmime::net::messageSet::byNumber(2));
folder->deleteMessages(vmime::net::messageSet::byNumber(2)); // renumbered, 3 becomes 2
\end{lstlisting}

\subsection{Events} % --------------------------------------------------------

As a result of executing some operation (or from time to time, even if no
operation has been performed), a store service can send events to notify you
that something has changed (eg. the number of messages in a folder). These
events may allow you to update the user interface associated to a message
store.

Currently, there are three types of event:

\begin{itemize}
\item {\bf message change}: sent when the number of messages in a folder
has changed (ie. some messages have been added or removed);
\item {\bf message count change}: sent when one or more message(s) have
changed (eg. flags or deleted status);
\item {\bf folder change}: sent when a folder has been created, renamed or
deleted.
\end{itemize}

You can register a listener for each event type by using the corresponding
methods on a {\vcode folder} object: {\vcode addMessageChangedListener()},
{\vcode addMessageCountListener()} or {\vcode addFolderListener()}. For more
information, please read the class documentation for
{\vcode vmime::net::events} namespace.


% ============================================================================
\section{Handling timeouts}

Unexpected errors can occur while messaging services are performing
operations and waiting a response from the server (eg. server stops
responding, network link falls down). As all operations as synchronous,
they can be ``blocked'' a long time before returning (in fact, they loop
until they either receive a response from the server, or the underlying
socket system returns an error).

VMime provides a mechanism to control the duration of operations. This
mechanism allows the program to cancel an operation that is currently
running.

An interface called {\vcode timeoutHandler} is provided:

\begin{lstlisting}
class timeoutHandler : public object {

   /** Called to test if the time limit has been reached.
     *
     * @return true if the timeout delay is elapsed
     */
   virtual const bool isTimeOut() = 0;

   /** Called to reset the timeout counter.
     */
   virtual void resetTimeOut() = 0;

   /** Called when the time limit has been reached (when
     * isTimeOut() returned true).
     *
     * @return true to continue (and reset the timeout)
     * or false to cancel the current operation
     */
   virtual const bool handleTimeOut() = 0;
};
\end{lstlisting}

While the operation runs, the service calls {\vcode isTimeout()} at variable
intervals. If the {\vcode isTimeout()} function returns {\vcode true},
then {\vcode handleTimeout()} is called. If the {\vcode handleTimeout()}
function returns {\vcode false}, the operation is cancelled and
an {\vcode operation\_timed\_out} exception is thrown. Else, if
{\vcode handleTimeout()} returns true, the operation continues and the
timeout counter is reset.
The function {\vcode resetTimeout()} is called each time data has
been received from the server to reset the timeout delay.

When using a service, a default timeout handler is set: if an operation
is blocked for more than 30 seconds (ie. network link is down and no data
was received since 30 seconds), an {\vcode operation\_timed\_out} exception
is thrown.

The following example shows how to implement a simple timeout handler:

\begin{lstlisting}[caption={Implementing a simple timeout handler}]
class myTimeoutHandler : public vmime::net::timeoutHandler {

public:

   myTimeoutHandler() {

      m_startTime = time(NULL);
   }

   const bool isTimeOut() {

      return time(NULL) >= m_startTime + 30;  // 30 seconds timeout
   }

   void resetTimeOut() {

      m_startTime = time(NULL);
   }

   const bool handleTimeOut() {

      std::cout << "Operation timed out." << std::endl;
                << "Press [Y] to continue, or [N] to "
                << "cancel the operation." << std::endl;

      std::string response;
      std::cin >> response;

      return response == "y" || response == "Y";
   }

private:

   time_t m_startTime;
};
\end{lstlisting}

To make the service use your timeout handler, you need to write a factory
class, to allow the service to create instances of the handler class. This
is required because the service can use several connections to the server
simultaneously, and each connection needs its own timeout handler.

\begin{lstlisting}
class myTimeoutHandlerFactory : public vmime::net::timeoutHandlerFactory {

public:

   ref <timeoutHandler> create() {

      return vmime::make_shared <myTimeoutHandler>();
   }
};
\end{lstlisting}

Then, call the {\vcode setTimeoutHandlerFactory()} method on the service object
to set the timeout handler factory to use during the session:

\begin{lstlisting}
theService->setTimeoutHandlerFactory(vmime::make_shared <myTimeoutHandlerFactory>());
\end{lstlisting}


% ============================================================================
\newpage
\section{Secured connection using TLS/SSL}

\subsection{Introduction} % --------------------------------------------------

If you have enabled TLS support in VMime, you can configure messaging services
so that they use a secured connection.

Quoting from RFC-2246 - the TLS 1.0 protocol specification: \emph{`` The TLS
protocol provides communications privacy over the Internet. The protocol
allows client/server applications to communicate in a way that is designed
to prevent eavesdropping, tampering, or message forgery.''}

TLS has the following advantages:

\begin{itemize}
\item authentication: server identity can be verified;
\item privacy: transmission of data between client and server cannot be read
by someone in the middle of the connection;
\item integrity: original data which is transferred between a client and a
server can not be modified by an attacker without being detected.
\end{itemize}

\vnote{What is the difference between SSL and TLS? SSL is a protocol designed
by Netscape. TLS is a standard protocol, and is partly based on version 3 of
the SSL protocol. The two protocols are not interoperable, but TLS does
support a mechanism to back down to SSL 3.}

VMime offers two possibilities for using a secured connection:

\begin{itemize}
\item you can connect to a server listening on a special port (eg. IMAPS
instead of IMAP): this is the classical use of SSL, but is now deprecated;
\item connect to a server listening on the default port, and then begin a
secured connection: this is STARTTLS.
\end{itemize}


\subsection{Setting up a secured connection} % -------------------------------

\subsubsection{Connecting to a ``secured'' port} % ...........................

To use the classical SSL/TLS way, simply use the ``S'' version of the protocol
to connect to the server (eg. \emph{imaps} instead of \emph{imap}). This is
currently available for SMTP, POP3 and IMAP.

\begin{lstlisting}
vmime::shared_ptr <vmime::net::store> store =
   theSession->getStore(vmime::utility::url("imaps://example.org"));
\end{lstlisting}

\subsubsection{Using STARTTLS} % .............................................

To make the service start a secured session using the STARTTLS method, simply
set the \emph{connection.tls} property:

\begin{lstlisting}
theService->setProperty("connection.tls", true);
\end{lstlisting}

\vnote{If, for some reason, a secured connection cannot be started, the
default behaviour is to fallback on a normal connection. To make
{\vcode connect()} fail if STARTTLS fails, set the
\emph{connection.tls.required} to \emph{true}.}

\subsection{Certificate verification} % --------------------------------------

\subsubsection{How it works} % ...............................................

If you tried the previous examples, a
{\vcode certificateException} might have been thrown.
This is because the default certificate verifier in VMime did not manage to
verify the certificate, and so could not trust it.

Basically, when you connect to a server using TLS, the server responds with
a list of certificates, called a certificate chain (usually, certificates are
of type X.509\footnote{And VMime currently supports only X.509 certificates}).
The certificate chain is ordered so that the first certificate is the subject
certificate, the second is the subject's issuer one, the third is the issuer's
issuer, and so on.

To decide whether the server can be trusted or not, you have to verify that
\emph{each} certificate is valid (ie. is trusted). For more information
about X.509 and certificate verification, see related articles on Wikipedia
\footnote{See \url{http://wikipedia.org/wiki/Public\_key\_certificate}}.

\subsubsection{Using the default certificate verifier} % .....................

The default certificate verifier maintains a list of root (CAs) and user
certificates that are trusted. By default, the list is empty. So, you have
to initialize it before using the verifier.

The algorithm\footnote{See
\url{http://wikipedia.org/wiki/Certification\_path\_validation\_algorithm}}
used is quite simple:

\begin{enumerate}
\item for every certificate in the chain, verify that the certificate has been
issued by the next certificate in the chain;
\item for every certificate in the chain, verify that the certificate is valid
at the current time;
\item ensure that the first certificate's subject name matches the hostname
of the server;
\item decide whether the subject's certificate can be trusted:
	\begin{itemize}
	\item first, verify that the the last certificate in the chain was
	issued by a third-party that we trust (root CAs);
	\item if the issuer certificate cannot be verified against root CAs,
	compare the subject's certificate against the trusted certificates
	(the certificates the user has decided to trust).
	\end{itemize}
\end{enumerate}

First, we need some code to load existing X.509 certificates:

\begin{lstlisting}[caption={Reading a X.509 certificate from a file}]
vmime::shared_ptr <vmime::security::cert::X509Certificate>
   loadX509CertificateFromFile(const std::string& path) {

   std::ifstream certFile;
   certFile.open(path.c_str(), std::ios::in | std::ios::binary);

   if (!certFile) {
      // ...handle error...
   }

   vmime::utility::inputStreamAdapter is(certFile);
   vmime::shared_ptr <vmime::security::cert::X509Certificate> cert;

   cert = vmime::security::cert::X509Certificate::import(is);

   return cert;
}
\end{lstlisting}

Then, we can use the {\vcode loadX509CertificateFromFile} function to load
certificates and initialize the certificate verifier:

\begin{lstlisting}[caption={Using the default certificate verifier}]
vmime::shared_ptr <vmime::security::cert::defaultCertificateVerifier> vrf =
   vmime::make_shared <vmime::security::cert::defaultCertificateVerifier>();

// Load root CAs (such as Verisign or Thawte)
std::vector <vmime::shared_ptr <vmime::security::cert::X509Certificate> > rootCAs;

rootCAs.push_back(loadX509CertificateFromFile("/path/to/root-ca1.cer");
rootCAs.push_back(loadX509CertificateFromFile("/path/to/root-ca2.cer");
rootCAs.push_back(loadX509CertificateFromFile("/path/to/root-ca3.cer");

vrf->setX509RootCAs(rootCAs);

// Then, load certificates that the user explicitely chose to trust
std::vector <vmime::shared_ptr <vmime::security::cert::X509Certificate> > trusted;

trusted.push_back(loadX509CertificateFromFile("/path/to/trusted-site1.cer");
trusted.push_back(loadX509CertificateFromFile("/path/to/trusted-site2.cer");

vrf->setX509TrustedCerts(trusted);
\end{lstlisting}


\subsubsection{Writing your own certificate verifier} % ......................

If you need to do more complex verifications on certificates, you will have to
write your own verifier. Your verifier should inherit from the
{\vcode vmime::security::cert::certificateVerifier} class and implement the
method {\vcode verify()}. Then, if the specified certificate chain is trusted,
simply return from the function, or else throw a
{\vcode certificateException}.

The following example shows how to implement an interactive certificate
verifier which relies on the user's decision, and nothing else (you SHOULD NOT
use this in a production application as this is obviously a serious security
issue):

\begin{lstlisting}[caption={A custom certificate verifier}]
class myCertVerifier : public vmime::security::cert::certificateVerifier {

public:

   void verify(const vmime::shared_ptr <certificateChain>& certs) {

      // Obtain the subject's certificate
      vmime::shared_ptr <vmime::security::cert::certificate> cert = chain->getAt(0);

      std::cout << std::endl;
      std::cout << "Server sent a '" << cert->getType() << "'"
         << " certificate." << std::endl;
      std::cout << "Do you want to accept this certificate? (Y/n) ";
      std::cout.flush();

      std::string answer;
      std::getline(std::cin, answer);

      if (answer.length() != 0 && (answer[0] == 'Y' || answer[0] == 'y')) {
         return;  // OK, we trust the certificate
      }

      // Don't trust this certificate
      throw vmime::security::cert::certificateException();
   }
};
\end{lstlisting}

\vnote{In production code, it may be a good idea to remember user's decisions
about which certificates to trust and which not. See {\vexample Example6} for
a basic cache implementation.}

Finally, to make the service use your own certificate verifier, simply write:

\begin{lstlisting}
theService->setCertificateVerifier(vmime::make_shared <myCertVerifier>());
\end{lstlisting}

\subsection{SSL/TLS Properties} % --------------------------------------------

If you want to customize behavior or set some options on TLS/SSL connection,
you may use the TLSProperties object, and pass it to the service session. The
TLS/SSL options must be set {\em before} creating any service with the session
(ie. before calling either {\vcode getStore()} or {\vcode getTransport()} on
the session), or they will not be used.

The following example shows how to set the cipher suite preferences for TLS:

\begin{lstlisting}[caption={Setting TLS cipher suite preferences}]
vmime::shared_ptr <vmime::net::session> sess = /* ... */;

vmime::shared_ptr <vmime::net::tls::TLSProperties> tlsProps =
	vmime::make_shared <vmime::net::tls::TLSProperties>();

// for OpenSSL
tlsProps->setCipherString("HIGH:!ADH:@STRENGTH");

// for GNU TLS
tlsProps->setCipherString("NORMAL:%SSL3_RECORD_VERSION");

sess->setTLSProperties(tlsProps);
\end{lstlisting}

Please note that the cipher suite string format and meaning depend on the
underlying TLS library (either OpenSSL or GNU TLS):

\begin{itemize}
\item for GNU TLS, read this: \newline
\url{http://gnutls.org/manual/html\_node/Priority-Strings.html}

\item for OpenSSL, read this: \newline
\url{http://www.openssl.org/docs/apps/ciphers.html#CIPHER\_STRINGS}
\end{itemize}

You may also set cipher suite preferences using predefined constants that
map to generic security modes:

\begin{lstlisting}[caption={Setting TLS cipher suite preferences using predefined modes}]
sess->setCipherSuite(vmime::net::tls::TLSProperties::CIPHERSUITE_HIGH);
\end{lstlisting}

The following constants are available:

\noindent\begin{tabularx}{1.0\textwidth}{|l|X|}
\hline
	{\bf Constant} &
	{\bf Meaning} \\
\hline
	CIPHERSUITE\_HIGH &
	High encryption cipher suites ($>$ 128 bits) \\
\hline
	CIPHERSUITE\_MEDIUM &
	Medium encryption cipher suites ($>=$ 128 bits) \\
\hline
	CIPHERSUITE\_LOW &
	Low encryption cipher suites ($>=$ 64 bits) \\
\hline
	CIPHERSUITE\_DEFAULT &
	Default cipher suite (actual cipher suites used depends
	on the underlying SSL/TLS library) \\
\hline
\end{tabularx}


% ============================================================================
\section{Tracing connection}

Connection tracing is used to log what is sent and received on the wire
between the client and the server, and may help debugging.

First, you have to create your own tracer, which must implement the
{\vcode vmime::net::tracer} interface. Here is an example of a tracer which
simply logs to the standard output:

\begin{lstlisting}[caption={A simple tracer}]
class myTracer : public vmime::net::tracer {

public:

   myTracer(const vmime::string& proto, const int connectionId)
      : m_proto(proto),
        m_connectionId(connectionId) {

   }

   // Called by VMime to trace what is sent on the socket
   void traceSend(const vmime::string& line) {

      std::cout << "[" << m_proto << ":" << m_connectionId
                << "] C: " << line << std::endl;
   }

   // Called by VMime to trace what is received from the socket
   void traceReceive(const vmime::string& line) {

      std::cout << "[" < < m_proto << ":" << m_connectionId
                << "] S: " << line << std::endl;
   }

private:

   const vmime::string m_proto;
   const int m_connectionId;
};
\end{lstlisting}

Also create a factory class, used to instanciate your tracer objects:

\begin{lstlisting}
class myTracerFactory : public vmime::net::tracerFactory {

public:

   vmime::shared_ptr <vmime::net::tracer> create(
      const vmime::shared_ptr <vmime::net::service>& serv,
      const int connectionId
   ) {

      return vmime::make_shared <myTracer>(
         serv->getProtocolName(), connectionId
      );
   }
};
\end{lstlisting}

Next, we have to tell VMime to use it. When you create your service
(either store or transport), simply call the {\vcode setTracerFactory}
on the service and pass an instance of your factory class:

\begin{lstlisting}[caption={Enabling tracer on a connection}]
vmime::shared_ptr <vmime::net::transport> store =
   session->getStore("imaps://user:password@imap.myserver.com");

// Enable tracing communication between client and server
store->setTracerFactory(vmime::make_shared <myTracerFactory>());
\end{lstlisting}

That's all! Now, everything which is sent on/received from the socket
will be logged using your tracer object. Here is an example of a trace
session for IMAP:

\begin{verbatim}
[imaps:1] S: * OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR
   LOGIN-REFERRALS ID ENABLE IDLE AUTH=PLAIN] Dovecot ready.
[imaps:1] C: a001 AUTHENTICATE PLAIN
[imaps:1] S: +
[imaps:1] C: {...SASL exchange: 52 bytes of data...}
[imaps:1] S: a001 OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR
   LOGIN-REFERRALS ID ENABLE IDLE SORT SPECIAL-USE QUOTA] Logged in
[imaps:1] C: a002 LIST "" ""
[imaps:1] S: * LIST (\Noselect) "." ""
[imaps:1] S: a002 OK List completed.
[imaps:1] C: a003 CAPABILITY
[imaps:1] S: * CAPABILITY IMAP4rev1 LITERAL+ SASL-IR
   LOGIN-REFERRALS ID ENABLE IDLE SORT SPECIAL-USE QUOTA
[imaps:1] S: a003 OK Capability completed.
[imaps:1] C: a003 SELECT INBOX (CONDSTORE)
[imaps:1] S: * FLAGS (\Answered \Flagged \Deleted \Seen \Draft
   $NotJunk NonJunk JunkRecorded $MDNSent NotJunk $Forwarded
   Junk $Junk Forwarded $MailFlagBit1)
[imaps:1] S: * OK [PERMANENTFLAGS (\Answered \Flagged \Deleted
   \Seen \Draft $NotJunk NonJunk JunkRecorded $MDNSent NotJunk
   $Forwarded Junk $Junk Forwarded $MailFlagBit1 \*)]
   Flags permitted.
[imaps:1] S: * 104 EXISTS
[imaps:1] S: * 0 RECENT
[imaps:1] S: * OK [UNSEEN 6] First unseen.
[imaps:1] S: * OK [UIDVALIDITY 1268127585] UIDs valid
[imaps:1] S: * OK [UIDNEXT 32716] Predicted next UID
[imaps:1] S: * OK [HIGHESTMODSEQ 148020] Highest
[imaps:1] S: a003 OK [READ-WRITE] Select completed.
\end{verbatim}

Please note that no sensitive data (ie. login or password) will be traced.
Same, {\em blob} data such as message content or SASL exchanges will be logged
as a marker which indicates how many bytes were sent/received (eg. "{...SASL
exchange: 52 bytes of data...}"").