3131#include " vmime/vmime.hpp"
3232#include " vmime/platforms/posix/posixHandler.hpp"
3333
34+ #include " example6_tracer.hpp"
35+ #include " example6_authenticator.hpp"
36+ #include " example6_certificateVerifier.hpp"
37+ #include " example6_timeoutHandler.hpp"
38+
3439
3540// Global session object
3641static vmime::shared_ptr <vmime::net::session> g_session
3742 = vmime::make_shared <vmime::net::session>();
3843
3944
40- #if VMIME_HAVE_SASL_SUPPORT
41-
42- // SASL authentication handler
43- class interactiveAuthenticator : public vmime ::security::sasl::defaultSASLAuthenticator
44- {
45- const std::vector <vmime::shared_ptr <vmime::security::sasl::SASLMechanism> > getAcceptableMechanisms
46- (const std::vector <vmime::shared_ptr <vmime::security::sasl::SASLMechanism> >& available,
47- vmime::shared_ptr <vmime::security::sasl::SASLMechanism> suggested) const
48- {
49- std::cout << std::endl << " Available SASL mechanisms:" << std::endl;
50-
51- for (unsigned int i = 0 ; i < available.size () ; ++i)
52- {
53- std::cout << " " << available[i]->getName ();
54-
55- if (suggested && available[i]->getName () == suggested->getName ())
56- std::cout << " (suggested)" ;
57- }
58-
59- std::cout << std::endl << std::endl;
60-
61- return defaultSASLAuthenticator::getAcceptableMechanisms (available, suggested);
62- }
63-
64- void setSASLMechanism (vmime::shared_ptr <vmime::security::sasl::SASLMechanism> mech)
65- {
66- std::cout << " Trying '" << mech->getName () << " ' authentication mechanism" << std::endl;
67-
68- defaultSASLAuthenticator::setSASLMechanism (mech);
69- }
70-
71- const vmime::string getUsername () const
72- {
73- if (m_username.empty ())
74- m_username = getUserInput (" Username" );
75-
76- return m_username;
77- }
78-
79- const vmime::string getPassword () const
80- {
81- if (m_password.empty ())
82- m_password = getUserInput (" Password" );
83-
84- return m_password;
85- }
86-
87- static const vmime::string getUserInput (const std::string& prompt)
88- {
89- std::cout << prompt << " : " ;
90- std::cout.flush ();
91-
92- vmime::string res;
93- std::getline (std::cin, res);
94-
95- return res;
96- }
97-
98- private:
99-
100- mutable vmime::string m_username;
101- mutable vmime::string m_password;
102- };
103-
104- #else // !VMIME_HAVE_SASL_SUPPORT
105-
106- // Simple authentication handler
107- class interactiveAuthenticator : public vmime ::security::defaultAuthenticator
108- {
109- const vmime::string getUsername () const
110- {
111- if (m_username.empty ())
112- m_username = getUserInput (" Username" );
113-
114- return m_username;
115- }
116-
117- const vmime::string getPassword () const
118- {
119- if (m_password.empty ())
120- m_password = getUserInput (" Password" );
121-
122- return m_password;
123- }
124-
125- static const vmime::string getUserInput (const std::string& prompt)
126- {
127- std::cout << prompt << " : " ;
128- std::cout.flush ();
129-
130- vmime::string res;
131- std::getline (std::cin, res);
132-
133- return res;
134- }
135-
136- private:
137-
138- mutable vmime::string m_username;
139- mutable vmime::string m_password;
140- };
141-
142- #endif // VMIME_HAVE_SASL_SUPPORT
143-
144-
145- #if VMIME_HAVE_TLS_SUPPORT
146-
147- // Certificate verifier (TLS/SSL)
148- class interactiveCertificateVerifier : public vmime ::security::cert::defaultCertificateVerifier
149- {
150- public:
151-
152- void verify (vmime::shared_ptr <vmime::security::cert::certificateChain> chain, const vmime::string& hostname)
153- {
154- try
155- {
156- setX509TrustedCerts (m_trustedCerts);
157-
158- defaultCertificateVerifier::verify (chain, hostname);
159- }
160- catch (vmime::exceptions::certificate_verification_exception&)
161- {
162- // Obtain subject's certificate
163- vmime::shared_ptr <vmime::security::cert::certificate> cert = chain->getAt (0 );
164-
165- std::cout << std::endl;
166- std::cout << " Server sent a '" << cert->getType () << " '" << " certificate." << std::endl;
167- std::cout << " Do you want to accept this certificate? (Y/n) " ;
168- std::cout.flush ();
169-
170- std::string answer;
171- std::getline (std::cin, answer);
172-
173- if (answer.length () != 0 &&
174- (answer[0 ] == ' Y' || answer[0 ] == ' y' ))
175- {
176- // Accept it, and remember user's choice for later
177- if (cert->getType () == " X.509" )
178- {
179- m_trustedCerts.push_back (vmime::dynamicCast
180- <vmime::security::cert::X509Certificate>(cert));
181-
182- setX509TrustedCerts (m_trustedCerts);
183- defaultCertificateVerifier::verify (chain, hostname);
184- }
185-
186- return ;
187- }
188-
189- throw vmime::exceptions::certificate_verification_exception
190- (" User did not accept the certificate." );
191- }
192- }
193-
194- private:
195-
196- static std::vector <vmime::shared_ptr <vmime::security::cert::X509Certificate> > m_trustedCerts;
197- };
198-
199-
200- std::vector <vmime::shared_ptr <vmime::security::cert::X509Certificate> >
201- interactiveCertificateVerifier::m_trustedCerts;
202-
203- #endif // VMIME_HAVE_TLS_SUPPORT
204-
205-
20645/* * Returns the messaging protocols supported by VMime.
20746 *
20847 * @param type service type (vmime::net::service::TYPE_STORE or
@@ -290,53 +129,6 @@ static std::ostream& operator<<(std::ostream& os, const vmime::exception& e)
290129}
291130
292131
293- /* * Time out handler.
294- * Used to stop the current operation after too much time, or if the user
295- * requested cancellation.
296- */
297- class timeoutHandler : public vmime ::net::timeoutHandler
298- {
299- public:
300-
301- bool isTimeOut ()
302- {
303- // This is a cancellation point: return true if you want to cancel
304- // the current operation. If you return true, handleTimeOut() will
305- // be called just after this, and before actually cancelling the
306- // operation
307- return false ;
308- }
309-
310- void resetTimeOut ()
311- {
312- // Called at the beginning of an operation (eg. connecting,
313- // a read() or a write() on a socket...)
314- }
315-
316- bool handleTimeOut ()
317- {
318- // If isTimeOut() returned true, this function will be called. This
319- // allows you to interact with the user, ie. display a prompt to
320- // know whether he wants to cancel the operation.
321-
322- // If you return true here, the operation will be actually cancelled.
323- // If not, the time out is reset and the operation continues.
324- return true ;
325- }
326- };
327-
328-
329- class timeoutHandlerFactory : public vmime ::net::timeoutHandlerFactory
330- {
331- public:
332-
333- vmime::shared_ptr <vmime::net::timeoutHandler> create ()
334- {
335- return vmime::make_shared <timeoutHandler>();
336- }
337- };
338-
339-
340132/* * Print the MIME structure of a message on the standard output.
341133 *
342134 * @param s structure object
@@ -445,8 +237,12 @@ static void sendMessage()
445237
446238 vmime::utility::url url (urlString);
447239
448- vmime::shared_ptr <vmime::net::transport> tr =
449- g_session->getTransport (url, vmime::make_shared <interactiveAuthenticator>());
240+ vmime::shared_ptr <vmime::net::transport> tr;
241+
242+ if (url.getUsername ().empty () || url.getPassword ().empty ())
243+ tr = g_session->getTransport (url, vmime::make_shared <interactiveAuthenticator>());
244+ else
245+ tr = g_session->getTransport (url);
450246
451247#if VMIME_HAVE_TLS_SUPPORT
452248
@@ -465,7 +261,12 @@ static void sendMessage()
465261
466262 // You can also set some properties (see example7 to know the properties
467263 // available for each service). For example, for SMTP:
468- // tr->setProperty("options.need-authentication", true);
264+ if (!url.getUsername ().empty () || !url.getPassword ().empty ())
265+ tr->setProperty (" options.need-authentication" , true );
266+
267+ // Trace communication between client and server
268+ vmime::shared_ptr <std::ostringstream> traceStream = vmime::make_shared <std::ostringstream>();
269+ tr->setTracerFactory (vmime::make_shared <myTracerFactory>(traceStream));
469270
470271 // Information about the mail
471272 std::cout << " Enter email of the expeditor (eg. me@somewhere.com): " ;
@@ -520,6 +321,12 @@ static void sendMessage()
520321 // ...
521322 // tr->send(&msg);
522323
324+ // Display connection log
325+ std::cout << std::endl;
326+ std::cout << " Connection Trace:" << std::endl;
327+ std::cout << " =================" << std::endl;
328+ std::cout << traceStream->str ();
329+
523330 tr->disconnect ();
524331 }
525332 catch (vmime::exception& e)
@@ -580,6 +387,10 @@ static void connectStore()
580387
581388#endif // VMIME_HAVE_TLS_SUPPORT
582389
390+ // Trace communication between client and server
391+ vmime::shared_ptr <std::ostringstream> traceStream = vmime::make_shared <std::ostringstream>();
392+ st->setTracerFactory (vmime::make_shared <myTracerFactory>(traceStream));
393+
583394 // Connect to the mail store
584395 st->connect ();
585396
@@ -621,6 +432,7 @@ static void connectStore()
621432 choices.push_back (" Change folder" );
622433 choices.push_back (" Add message (to the current folder)" );
623434 choices.push_back (" Copy message (into the current folder)" );
435+ choices.push_back (" Display trace output" );
624436 choices.push_back (" Return to main menu" );
625437
626438 const int choice = printMenu (choices);
@@ -928,9 +740,18 @@ static void connectStore()
928740
929741 break ;
930742 }
931- // Main menu
743+ // Display trace output
932744 case 12 :
933745
746+ std::cout << std::endl;
747+ std::cout << " Connection Trace:" << std::endl;
748+ std::cout << " =================" << std::endl;
749+ std::cout << traceStream->str ();
750+ break ;
751+
752+ // Main menu
753+ case 13 :
754+
934755 f->close (true ); // 'true' to expunge deleted messages
935756 cont = false ;
936757 break ;
@@ -979,7 +800,9 @@ static void connectStore()
979800 std::cerr << std::endl;
980801 std::cerr << " std::exception: " << e.what () << std::endl;
981802 }
982- }
803+ } // for(cont)
804+
805+ st->disconnect ();
983806 }
984807 catch (vmime::exception& e)
985808 {
0 commit comments