Skip to content

Commit 84e570b

Browse files
Connection trace facility.
1 parent cfe9c6b commit 84e570b

35 files changed

+810
-287
lines changed

examples/example6.cpp

Lines changed: 41 additions & 218 deletions
Original file line numberDiff line numberDiff line change
@@ -31,178 +31,17 @@
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
3641
static 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

Comments
 (0)