annotate 3rdparty/vmime/examples/example6.cpp @ 0:a4671277546c tip

created the repository for the thymian project
author ferencd
date Tue, 17 Aug 2021 11:19:54 +0200
parents
children
rev   line source
ferencd@0 1 //
ferencd@0 2 // VMime library (http://www.vmime.org)
ferencd@0 3 // Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org>
ferencd@0 4 //
ferencd@0 5 // This program is free software; you can redistribute it and/or
ferencd@0 6 // modify it under the terms of the GNU General Public License as
ferencd@0 7 // published by the Free Software Foundation; either version 3 of
ferencd@0 8 // the License, or (at your option) any later version.
ferencd@0 9 //
ferencd@0 10 // This program is distributed in the hope that it will be useful,
ferencd@0 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
ferencd@0 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
ferencd@0 13 // General Public License for more details.
ferencd@0 14 //
ferencd@0 15 // You should have received a copy of the GNU General Public License along
ferencd@0 16 // with this program; if not, write to the Free Software Foundation, Inc.,
ferencd@0 17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
ferencd@0 18 //
ferencd@0 19 // Linking this library statically or dynamically with other modules is making
ferencd@0 20 // a combined work based on this library. Thus, the terms and conditions of
ferencd@0 21 // the GNU General Public License cover the whole combination.
ferencd@0 22 //
ferencd@0 23
ferencd@0 24 #include <iostream>
ferencd@0 25 #include <sstream>
ferencd@0 26 #include <vector>
ferencd@0 27 #include <map>
ferencd@0 28 #include <locale>
ferencd@0 29 #include <clocale>
ferencd@0 30
ferencd@0 31 #include "vmime/vmime.hpp"
ferencd@0 32 #include "vmime/platforms/posix/posixHandler.hpp"
ferencd@0 33
ferencd@0 34 #include "example6_tracer.hpp"
ferencd@0 35 #include "example6_authenticator.hpp"
ferencd@0 36 #include "example6_certificateVerifier.hpp"
ferencd@0 37 #include "example6_timeoutHandler.hpp"
ferencd@0 38
ferencd@0 39
ferencd@0 40 // Global session object
ferencd@0 41 static vmime::shared_ptr <vmime::net::session> g_session
ferencd@0 42 = vmime::make_shared <vmime::net::session>();
ferencd@0 43
ferencd@0 44
ferencd@0 45 /** Returns the messaging protocols supported by VMime.
ferencd@0 46 *
ferencd@0 47 * @param type service type (vmime::net::service::TYPE_STORE or
ferencd@0 48 * vmime::net::service::TYPE_TRANSPORT)
ferencd@0 49 */
ferencd@0 50 static const std::string findAvailableProtocols(const vmime::net::service::Type type)
ferencd@0 51 {
ferencd@0 52 vmime::shared_ptr <vmime::net::serviceFactory> sf =
ferencd@0 53 vmime::net::serviceFactory::getInstance();
ferencd@0 54
ferencd@0 55 std::ostringstream res;
ferencd@0 56 int count = 0;
ferencd@0 57
ferencd@0 58 for (int i = 0 ; i < sf->getServiceCount() ; ++i)
ferencd@0 59 {
ferencd@0 60 const vmime::net::serviceFactory::registeredService& serv = *sf->getServiceAt(i);
ferencd@0 61
ferencd@0 62 if (serv.getType() == type)
ferencd@0 63 {
ferencd@0 64 if (count != 0)
ferencd@0 65 res << ", ";
ferencd@0 66
ferencd@0 67 res << serv.getName();
ferencd@0 68 ++count;
ferencd@0 69 }
ferencd@0 70 }
ferencd@0 71
ferencd@0 72 return res.str();
ferencd@0 73 }
ferencd@0 74
ferencd@0 75
ferencd@0 76 // Exception helper
ferencd@0 77 static std::ostream& operator<<(std::ostream& os, const vmime::exception& e)
ferencd@0 78 {
ferencd@0 79 os << "* vmime::exceptions::" << e.name() << std::endl;
ferencd@0 80 os << " what = " << e.what() << std::endl;
ferencd@0 81
ferencd@0 82 // More information for special exceptions
ferencd@0 83 if (dynamic_cast <const vmime::exceptions::command_error*>(&e))
ferencd@0 84 {
ferencd@0 85 const vmime::exceptions::command_error& cee =
ferencd@0 86 dynamic_cast <const vmime::exceptions::command_error&>(e);
ferencd@0 87
ferencd@0 88 os << " command = " << cee.command() << std::endl;
ferencd@0 89 os << " response = " << cee.response() << std::endl;
ferencd@0 90 }
ferencd@0 91
ferencd@0 92 if (dynamic_cast <const vmime::exceptions::invalid_response*>(&e))
ferencd@0 93 {
ferencd@0 94 const vmime::exceptions::invalid_response& ir =
ferencd@0 95 dynamic_cast <const vmime::exceptions::invalid_response&>(e);
ferencd@0 96
ferencd@0 97 os << " response = " << ir.response() << std::endl;
ferencd@0 98 }
ferencd@0 99
ferencd@0 100 if (dynamic_cast <const vmime::exceptions::connection_greeting_error*>(&e))
ferencd@0 101 {
ferencd@0 102 const vmime::exceptions::connection_greeting_error& cgee =
ferencd@0 103 dynamic_cast <const vmime::exceptions::connection_greeting_error&>(e);
ferencd@0 104
ferencd@0 105 os << " response = " << cgee.response() << std::endl;
ferencd@0 106 }
ferencd@0 107
ferencd@0 108 if (dynamic_cast <const vmime::exceptions::authentication_error*>(&e))
ferencd@0 109 {
ferencd@0 110 const vmime::exceptions::authentication_error& aee =
ferencd@0 111 dynamic_cast <const vmime::exceptions::authentication_error&>(e);
ferencd@0 112
ferencd@0 113 os << " response = " << aee.response() << std::endl;
ferencd@0 114 }
ferencd@0 115
ferencd@0 116 if (dynamic_cast <const vmime::exceptions::filesystem_exception*>(&e))
ferencd@0 117 {
ferencd@0 118 const vmime::exceptions::filesystem_exception& fse =
ferencd@0 119 dynamic_cast <const vmime::exceptions::filesystem_exception&>(e);
ferencd@0 120
ferencd@0 121 os << " path = " << vmime::platform::getHandler()->
ferencd@0 122 getFileSystemFactory()->pathToString(fse.path()) << std::endl;
ferencd@0 123 }
ferencd@0 124
ferencd@0 125 if (e.other() != NULL)
ferencd@0 126 os << *e.other();
ferencd@0 127
ferencd@0 128 return os;
ferencd@0 129 }
ferencd@0 130
ferencd@0 131
ferencd@0 132 /** Print the MIME structure of a message on the standard output.
ferencd@0 133 *
ferencd@0 134 * @param s structure object
ferencd@0 135 * @param level current depth
ferencd@0 136 */
ferencd@0 137 static void printStructure(vmime::shared_ptr <const vmime::net::messageStructure> s, const int level = 0)
ferencd@0 138 {
ferencd@0 139 for (int i = 0 ; i < s->getPartCount() ; ++i)
ferencd@0 140 {
ferencd@0 141 vmime::shared_ptr <const vmime::net::messagePart> part = s->getPartAt(i);
ferencd@0 142
ferencd@0 143 for (int j = 0 ; j < level * 2 ; ++j)
ferencd@0 144 std::cout << " ";
ferencd@0 145
ferencd@0 146 std::cout << (part->getNumber() + 1) << ". "
ferencd@0 147 << part->getType().generate()
ferencd@0 148 << " [" << part->getSize() << " byte(s)]"
ferencd@0 149 << std::endl;
ferencd@0 150
ferencd@0 151 printStructure(part->getStructure(), level + 1);
ferencd@0 152 }
ferencd@0 153 }
ferencd@0 154
ferencd@0 155
ferencd@0 156 static const vmime::string getFolderPathString(vmime::shared_ptr <vmime::net::folder> f)
ferencd@0 157 {
ferencd@0 158 const vmime::string n = f->getName().getBuffer();
ferencd@0 159
ferencd@0 160 if (n.empty()) // root folder
ferencd@0 161 {
ferencd@0 162 return "/";
ferencd@0 163 }
ferencd@0 164 else
ferencd@0 165 {
ferencd@0 166 vmime::shared_ptr <vmime::net::folder> p = f->getParent();
ferencd@0 167 return getFolderPathString(p) + n + "/";
ferencd@0 168 }
ferencd@0 169 }
ferencd@0 170
ferencd@0 171
ferencd@0 172 /** Print folders and sub-folders on the standard output.
ferencd@0 173 *
ferencd@0 174 * @param folder current folder
ferencd@0 175 */
ferencd@0 176 static void printFolders(vmime::shared_ptr <vmime::net::folder> folder, const int level = 0)
ferencd@0 177 {
ferencd@0 178 for (int j = 0 ; j < level * 2 ; ++j)
ferencd@0 179 std::cout << " ";
ferencd@0 180
ferencd@0 181 std::cout << getFolderPathString(folder) << std::endl;
ferencd@0 182
ferencd@0 183 std::vector <vmime::shared_ptr <vmime::net::folder> > subFolders = folder->getFolders(false);
ferencd@0 184
ferencd@0 185 for (unsigned int i = 0 ; i < subFolders.size() ; ++i)
ferencd@0 186 printFolders(subFolders[i], level + 1);
ferencd@0 187 }
ferencd@0 188
ferencd@0 189
ferencd@0 190 /** Print a menu on the standard output.
ferencd@0 191 *
ferencd@0 192 * @param choices menu choices
ferencd@0 193 */
ferencd@0 194 static unsigned int printMenu(const std::vector <std::string>& choices)
ferencd@0 195 {
ferencd@0 196 std::cout << std::endl;
ferencd@0 197
ferencd@0 198 for (unsigned int i = 0 ; i < choices.size() ; ++i)
ferencd@0 199 std::cout << " " << (i + 1) << ". " << choices[i] << std::endl;
ferencd@0 200
ferencd@0 201 std::cout << std::endl;
ferencd@0 202 std::cout << " Your choice? [1-" << choices.size() << "] ";
ferencd@0 203 std::cout.flush();
ferencd@0 204
ferencd@0 205 std::string line;
ferencd@0 206 std::getline(std::cin, line);
ferencd@0 207
ferencd@0 208 std::istringstream iss(line);
ferencd@0 209
ferencd@0 210 unsigned int choice = 0;
ferencd@0 211 iss >> choice;
ferencd@0 212
ferencd@0 213 std::cout << std::endl;
ferencd@0 214
ferencd@0 215 if (choice < 1 || choice > choices.size())
ferencd@0 216 return 0;
ferencd@0 217 else
ferencd@0 218 return choice;
ferencd@0 219 }
ferencd@0 220
ferencd@0 221
ferencd@0 222 /** Send a message interactively.
ferencd@0 223 */
ferencd@0 224 static void sendMessage()
ferencd@0 225 {
ferencd@0 226 try
ferencd@0 227 {
ferencd@0 228 // Request user to enter an URL
ferencd@0 229 std::cout << "Enter an URL to connect to transport service." << std::endl;
ferencd@0 230 std::cout << "Available protocols: " << findAvailableProtocols(vmime::net::service::TYPE_TRANSPORT) << std::endl;
ferencd@0 231 std::cout << "(eg. smtp://myserver.com, sendmail://localhost)" << std::endl;
ferencd@0 232 std::cout << "> ";
ferencd@0 233 std::cout.flush();
ferencd@0 234
ferencd@0 235 vmime::string urlString;
ferencd@0 236 std::getline(std::cin, urlString);
ferencd@0 237
ferencd@0 238 vmime::utility::url url(urlString);
ferencd@0 239
ferencd@0 240 vmime::shared_ptr <vmime::net::transport> tr;
ferencd@0 241
ferencd@0 242 if (url.getUsername().empty() || url.getPassword().empty())
ferencd@0 243 tr = g_session->getTransport(url, vmime::make_shared <interactiveAuthenticator>());
ferencd@0 244 else
ferencd@0 245 tr = g_session->getTransport(url);
ferencd@0 246
ferencd@0 247 #if VMIME_HAVE_TLS_SUPPORT
ferencd@0 248
ferencd@0 249 // Enable TLS support if available
ferencd@0 250 tr->setProperty("connection.tls", true);
ferencd@0 251
ferencd@0 252 // Set the time out handler
ferencd@0 253 tr->setTimeoutHandlerFactory(vmime::make_shared <timeoutHandlerFactory>());
ferencd@0 254
ferencd@0 255 // Set the object responsible for verifying certificates, in the
ferencd@0 256 // case a secured connection is used (TLS/SSL)
ferencd@0 257 tr->setCertificateVerifier
ferencd@0 258 (vmime::make_shared <interactiveCertificateVerifier>());
ferencd@0 259
ferencd@0 260 #endif // VMIME_HAVE_TLS_SUPPORT
ferencd@0 261
ferencd@0 262 // You can also set some properties (see example7 to know the properties
ferencd@0 263 // available for each service). For example, for SMTP:
ferencd@0 264 if (!url.getUsername().empty() || !url.getPassword().empty())
ferencd@0 265 tr->setProperty("options.need-authentication", true);
ferencd@0 266
ferencd@0 267 // Trace communication between client and server
ferencd@0 268 vmime::shared_ptr <std::ostringstream> traceStream = vmime::make_shared <std::ostringstream>();
ferencd@0 269 tr->setTracerFactory(vmime::make_shared <myTracerFactory>(traceStream));
ferencd@0 270
ferencd@0 271 // Information about the mail
ferencd@0 272 std::cout << "Enter email of the expeditor (eg. me@somewhere.com): ";
ferencd@0 273 std::cout.flush();
ferencd@0 274
ferencd@0 275 vmime::string fromString;
ferencd@0 276 std::getline(std::cin, fromString);
ferencd@0 277
ferencd@0 278 vmime::mailbox from(fromString);
ferencd@0 279 vmime::mailboxList to;
ferencd@0 280
ferencd@0 281 for (bool cont = true ; cont ; )
ferencd@0 282 {
ferencd@0 283 std::cout << "Enter email of the recipient (empty to stop): ";
ferencd@0 284 std::cout.flush();
ferencd@0 285
ferencd@0 286 vmime::string toString;
ferencd@0 287 std::getline(std::cin, toString);
ferencd@0 288
ferencd@0 289 cont = (toString.size() != 0);
ferencd@0 290
ferencd@0 291 if (cont)
ferencd@0 292 to.appendMailbox(vmime::make_shared <vmime::mailbox>(toString));
ferencd@0 293 }
ferencd@0 294
ferencd@0 295 std::cout << "Enter message data, including headers (end with '.' on a single line):" << std::endl;
ferencd@0 296
ferencd@0 297 std::ostringstream data;
ferencd@0 298
ferencd@0 299 for (bool cont = true ; cont ; )
ferencd@0 300 {
ferencd@0 301 std::string line;
ferencd@0 302 std::getline(std::cin, line);
ferencd@0 303
ferencd@0 304 if (line == ".")
ferencd@0 305 cont = false;
ferencd@0 306 else
ferencd@0 307 data << line << "\r\n";
ferencd@0 308 }
ferencd@0 309
ferencd@0 310 // Connect to server
ferencd@0 311 tr->connect();
ferencd@0 312
ferencd@0 313 // Send the message
ferencd@0 314 vmime::string msgData = data.str();
ferencd@0 315 vmime::utility::inputStreamStringAdapter vis(msgData);
ferencd@0 316
ferencd@0 317 tr->send(from, to, vis, msgData.length());
ferencd@0 318
ferencd@0 319 // Note: you could also write this:
ferencd@0 320 // vmime::message msg;
ferencd@0 321 // ...
ferencd@0 322 // tr->send(&msg);
ferencd@0 323
ferencd@0 324 // Display connection log
ferencd@0 325 std::cout << std::endl;
ferencd@0 326 std::cout << "Connection Trace:" << std::endl;
ferencd@0 327 std::cout << "=================" << std::endl;
ferencd@0 328 std::cout << traceStream->str();
ferencd@0 329
ferencd@0 330 tr->disconnect();
ferencd@0 331 }
ferencd@0 332 catch (vmime::exception& e)
ferencd@0 333 {
ferencd@0 334 std::cerr << std::endl;
ferencd@0 335 std::cerr << e << std::endl;
ferencd@0 336 throw;
ferencd@0 337 }
ferencd@0 338 catch (std::exception& e)
ferencd@0 339 {
ferencd@0 340 std::cerr << std::endl;
ferencd@0 341 std::cerr << "std::exception: " << e.what() << std::endl;
ferencd@0 342 throw;
ferencd@0 343 }
ferencd@0 344 }
ferencd@0 345
ferencd@0 346
ferencd@0 347 /** Connect to a message store interactively.
ferencd@0 348 */
ferencd@0 349 static void connectStore()
ferencd@0 350 {
ferencd@0 351 try
ferencd@0 352 {
ferencd@0 353 // Request user to enter an URL
ferencd@0 354 std::cout << "Enter an URL to connect to store service." << std::endl;
ferencd@0 355 std::cout << "Available protocols: " << findAvailableProtocols(vmime::net::service::TYPE_STORE) << std::endl;
ferencd@0 356 std::cout << "(eg. pop3://user:pass@myserver.com, imap://myserver.com:123)" << std::endl;
ferencd@0 357 std::cout << "> ";
ferencd@0 358 std::cout.flush();
ferencd@0 359
ferencd@0 360 vmime::string urlString;
ferencd@0 361 std::getline(std::cin, urlString);
ferencd@0 362
ferencd@0 363 vmime::utility::url url(urlString);
ferencd@0 364
ferencd@0 365 // If no authenticator is given in argument to getStore(), a default one
ferencd@0 366 // is used. Its behaviour is to get the user credentials from the
ferencd@0 367 // session properties "auth.username" and "auth.password".
ferencd@0 368 vmime::shared_ptr <vmime::net::store> st;
ferencd@0 369
ferencd@0 370 if (url.getUsername().empty() || url.getPassword().empty())
ferencd@0 371 st = g_session->getStore(url, vmime::make_shared <interactiveAuthenticator>());
ferencd@0 372 else
ferencd@0 373 st = g_session->getStore(url);
ferencd@0 374
ferencd@0 375 #if VMIME_HAVE_TLS_SUPPORT
ferencd@0 376
ferencd@0 377 // Enable TLS support if available
ferencd@0 378 st->setProperty("connection.tls", true);
ferencd@0 379
ferencd@0 380 // Set the time out handler
ferencd@0 381 st->setTimeoutHandlerFactory(vmime::make_shared <timeoutHandlerFactory>());
ferencd@0 382
ferencd@0 383 // Set the object responsible for verifying certificates, in the
ferencd@0 384 // case a secured connection is used (TLS/SSL)
ferencd@0 385 st->setCertificateVerifier
ferencd@0 386 (vmime::make_shared <interactiveCertificateVerifier>());
ferencd@0 387
ferencd@0 388 #endif // VMIME_HAVE_TLS_SUPPORT
ferencd@0 389
ferencd@0 390 // Trace communication between client and server
ferencd@0 391 vmime::shared_ptr <std::ostringstream> traceStream = vmime::make_shared <std::ostringstream>();
ferencd@0 392 st->setTracerFactory(vmime::make_shared <myTracerFactory>(traceStream));
ferencd@0 393
ferencd@0 394 // Connect to the mail store
ferencd@0 395 st->connect();
ferencd@0 396
ferencd@0 397 // Display some information about the connection
ferencd@0 398 vmime::shared_ptr <vmime::net::connectionInfos> ci = st->getConnectionInfos();
ferencd@0 399
ferencd@0 400 std::cout << std::endl;
ferencd@0 401 std::cout << "Connected to '" << ci->getHost() << "' (port " << ci->getPort() << ")" << std::endl;
ferencd@0 402 std::cout << "Connection is " << (st->isSecuredConnection() ? "" : "NOT ") << "secured." << std::endl;
ferencd@0 403
ferencd@0 404 // Open the default folder in this store
ferencd@0 405 vmime::shared_ptr <vmime::net::folder> f = st->getDefaultFolder();
ferencd@0 406 // vmime::shared_ptr <vmime::net::folder> f = st->getFolder(vmime::utility::path("a"));
ferencd@0 407
ferencd@0 408 f->open(vmime::net::folder::MODE_READ_WRITE);
ferencd@0 409
ferencd@0 410 int count = f->getMessageCount();
ferencd@0 411
ferencd@0 412 std::cout << std::endl;
ferencd@0 413 std::cout << count << " message(s) in your inbox" << std::endl;
ferencd@0 414
ferencd@0 415 for (bool cont = true ; cont ; )
ferencd@0 416 {
ferencd@0 417 typedef std::map <int, vmime::shared_ptr <vmime::net::message> > MessageList;
ferencd@0 418 MessageList msgList;
ferencd@0 419
ferencd@0 420 try
ferencd@0 421 {
ferencd@0 422 std::vector <std::string> choices;
ferencd@0 423
ferencd@0 424 choices.push_back("Show message flags");
ferencd@0 425 choices.push_back("Show message structure");
ferencd@0 426 choices.push_back("Show message header");
ferencd@0 427 choices.push_back("Show message envelope");
ferencd@0 428 choices.push_back("Extract whole message");
ferencd@0 429 choices.push_back("Extract attachments");
ferencd@0 430 choices.push_back("Status");
ferencd@0 431 choices.push_back("List folders");
ferencd@0 432 choices.push_back("Change folder");
ferencd@0 433 choices.push_back("Add message (to the current folder)");
ferencd@0 434 choices.push_back("Copy message (into the current folder)");
ferencd@0 435 choices.push_back("Display trace output");
ferencd@0 436 choices.push_back("Return to main menu");
ferencd@0 437
ferencd@0 438 const int choice = printMenu(choices);
ferencd@0 439
ferencd@0 440 // Request message number
ferencd@0 441 vmime::shared_ptr <vmime::net::message> msg;
ferencd@0 442
ferencd@0 443 if (choice == 1 || choice == 2 || choice == 3 || choice == 4 ||
ferencd@0 444 choice == 5 || choice == 6 || choice == 11)
ferencd@0 445 {
ferencd@0 446 std::cout << "Enter message number: ";
ferencd@0 447 std::cout.flush();
ferencd@0 448
ferencd@0 449 std::string line;
ferencd@0 450 std::getline(std::cin, line);
ferencd@0 451
ferencd@0 452 std::istringstream iss(line);
ferencd@0 453
ferencd@0 454 int num = 0;
ferencd@0 455 iss >> num;
ferencd@0 456
ferencd@0 457 if (num < 1 || num > f->getMessageCount())
ferencd@0 458 {
ferencd@0 459 std::cerr << "Invalid message number." << std::endl;
ferencd@0 460 continue;
ferencd@0 461 }
ferencd@0 462
ferencd@0 463 MessageList::iterator it = msgList.find(num);
ferencd@0 464
ferencd@0 465 if (it != msgList.end())
ferencd@0 466 {
ferencd@0 467 msg = (*it).second;
ferencd@0 468 }
ferencd@0 469 else
ferencd@0 470 {
ferencd@0 471 msg = f->getMessage(num);
ferencd@0 472 msgList.insert(MessageList::value_type(num, msg));
ferencd@0 473 }
ferencd@0 474
ferencd@0 475 std::cout << std::endl;
ferencd@0 476 }
ferencd@0 477
ferencd@0 478 switch (choice)
ferencd@0 479 {
ferencd@0 480 // Show message flags
ferencd@0 481 case 1:
ferencd@0 482
ferencd@0 483 f->fetchMessage(msg, vmime::net::fetchAttributes::FLAGS);
ferencd@0 484
ferencd@0 485 if (msg->getFlags() & vmime::net::message::FLAG_SEEN)
ferencd@0 486 std::cout << "FLAG_SEEN" << std::endl;
ferencd@0 487 if (msg->getFlags() & vmime::net::message::FLAG_RECENT)
ferencd@0 488 std::cout << "FLAG_RECENT" << std::endl;
ferencd@0 489 if (msg->getFlags() & vmime::net::message::FLAG_REPLIED)
ferencd@0 490 std::cout << "FLAG_REPLIED" << std::endl;
ferencd@0 491 if (msg->getFlags() & vmime::net::message::FLAG_DELETED)
ferencd@0 492 std::cout << "FLAG_DELETED" << std::endl;
ferencd@0 493 if (msg->getFlags() & vmime::net::message::FLAG_MARKED)
ferencd@0 494 std::cout << "FLAG_MARKED" << std::endl;
ferencd@0 495 if (msg->getFlags() & vmime::net::message::FLAG_PASSED)
ferencd@0 496 std::cout << "FLAG_PASSED" << std::endl;
ferencd@0 497
ferencd@0 498 break;
ferencd@0 499
ferencd@0 500 // Show message structure
ferencd@0 501 case 2:
ferencd@0 502
ferencd@0 503 f->fetchMessage(msg, vmime::net::fetchAttributes::STRUCTURE);
ferencd@0 504 printStructure(msg->getStructure());
ferencd@0 505 break;
ferencd@0 506
ferencd@0 507 // Show message header
ferencd@0 508 case 3:
ferencd@0 509
ferencd@0 510 f->fetchMessage(msg, vmime::net::fetchAttributes::FULL_HEADER);
ferencd@0 511 std::cout << msg->getHeader()->generate() << std::endl;
ferencd@0 512 break;
ferencd@0 513
ferencd@0 514 // Show message envelope
ferencd@0 515 case 4:
ferencd@0 516
ferencd@0 517 f->fetchMessage(msg, vmime::net::fetchAttributes::ENVELOPE);
ferencd@0 518
ferencd@0 519 #define ENV_HELPER(x) \
ferencd@0 520 try { std::cout << msg->getHeader()->x()->generate() << std::endl; } \
ferencd@0 521 catch (vmime::exception) { /* In case the header field does not exist. */ }
ferencd@0 522
ferencd@0 523 ENV_HELPER(From)
ferencd@0 524 ENV_HELPER(To)
ferencd@0 525 ENV_HELPER(Date)
ferencd@0 526 ENV_HELPER(Subject)
ferencd@0 527
ferencd@0 528 #undef ENV_HELPER
ferencd@0 529
ferencd@0 530 break;
ferencd@0 531
ferencd@0 532 // Extract whole message
ferencd@0 533 case 5:
ferencd@0 534 {
ferencd@0 535 vmime::utility::outputStreamAdapter out(std::cout);
ferencd@0 536 msg->extract(out);
ferencd@0 537
ferencd@0 538 break;
ferencd@0 539 }
ferencd@0 540 // Extract attachments
ferencd@0 541 case 6:
ferencd@0 542 {
ferencd@0 543 vmime::shared_ptr <vmime::message> parsedMsg = msg->getParsedMessage();
ferencd@0 544
ferencd@0 545 std::vector <vmime::shared_ptr <const vmime::attachment> > attchs =
ferencd@0 546 vmime::attachmentHelper::findAttachmentsInMessage(parsedMsg);
ferencd@0 547
ferencd@0 548 if (attchs.size() > 0)
ferencd@0 549 {
ferencd@0 550 std::cout << attchs.size() << " attachments found." << std::endl;
ferencd@0 551
ferencd@0 552 for (std::vector <vmime::shared_ptr <const vmime::attachment> >::iterator
ferencd@0 553 it = attchs.begin() ; it != attchs.end() ; ++it)
ferencd@0 554 {
ferencd@0 555 vmime::shared_ptr <const vmime::attachment> att = *it;
ferencd@0 556
ferencd@0 557 // Get attachment size
ferencd@0 558 vmime::size_t size = 0;
ferencd@0 559
ferencd@0 560 if (att->getData()->isEncoded())
ferencd@0 561 size = att->getData()->getEncoding().getEncoder()->getDecodedSize(att->getData()->getLength());
ferencd@0 562 else
ferencd@0 563 size = att->getData()->getLength();
ferencd@0 564
ferencd@0 565 std::cout << "Found attachment '" << att->getName().getBuffer() << "'"
ferencd@0 566 << ", size is " << size << " bytes:" << std::endl;
ferencd@0 567
ferencd@0 568 // Get attachment data
ferencd@0 569 std::cout << std::endl;
ferencd@0 570 std::cout << "========== BEGIN CONTENT ==========" << std::endl;
ferencd@0 571
ferencd@0 572 vmime::utility::outputStreamAdapter osa(std::cout);
ferencd@0 573 att->getData()->extract(osa);
ferencd@0 574
ferencd@0 575 std::cout << std::endl;
ferencd@0 576 std::cout << "========== END CONTENT ==========" << std::endl;
ferencd@0 577
ferencd@0 578 // Or write it to a file
ferencd@0 579 /*
ferencd@0 580 vmime::shared_ptr <vmime::utility::fileSystemFactory> fsf
ferencd@0 581 = vmime::platform::getHandler()->getFileSystemFactory();
ferencd@0 582
ferencd@0 583 vmime::shared_ptr <vmime::utility::file> file
ferencd@0 584 = fsf->create(vmime::utility::path::fromString
ferencd@0 585 ("/path/to/attachment-file", "/", vmime::charsets::UTF_8));
ferencd@0 586 // -or- ("C:\\Temp\\attachment-file", "\\", vmime::charsets::UTF_8));
ferencd@0 587
ferencd@0 588 file->createFile();
ferencd@0 589
ferencd@0 590 vmime::shared_ptr <vmime::utility::outputStream> output =
ferencd@0 591 file->getFileWriter()->getOutputStream();
ferencd@0 592
ferencd@0 593 att->getData()->extract(*output.get());
ferencd@0 594 */
ferencd@0 595 }
ferencd@0 596 }
ferencd@0 597 else
ferencd@0 598 {
ferencd@0 599 std::cout << "No attachments found." << std::endl;
ferencd@0 600 }
ferencd@0 601
ferencd@0 602 break;
ferencd@0 603 }
ferencd@0 604 // Status
ferencd@0 605 case 7:
ferencd@0 606 {
ferencd@0 607 int count, unseen;
ferencd@0 608 f->status(count, unseen);
ferencd@0 609
ferencd@0 610 std::cout << "Status: count=" << count << ", unseen=" << unseen << std::endl;
ferencd@0 611 break;
ferencd@0 612 }
ferencd@0 613 // List folders
ferencd@0 614 case 8:
ferencd@0 615 {
ferencd@0 616 vmime::shared_ptr <vmime::net::folder>
ferencd@0 617 root = st->getRootFolder();
ferencd@0 618
ferencd@0 619 printFolders(root);
ferencd@0 620 break;
ferencd@0 621 }
ferencd@0 622 // Change folder
ferencd@0 623 case 9:
ferencd@0 624 {
ferencd@0 625 std::cout << "Enter folder path (eg. /root/subfolder):" << std::endl;
ferencd@0 626 std::cout.flush();
ferencd@0 627
ferencd@0 628 std::string path;
ferencd@0 629 std::getline(std::cin, path);
ferencd@0 630
ferencd@0 631 vmime::shared_ptr <vmime::net::folder> newFolder = st->getRootFolder();
ferencd@0 632
ferencd@0 633 for (std::string::size_type s = 0, p = 0 ; ; s = p + 1)
ferencd@0 634 {
ferencd@0 635 p = path.find_first_of('/', s);
ferencd@0 636
ferencd@0 637 const std::string x = (p == std::string::npos)
ferencd@0 638 ? std::string(path.begin() + s, path.end())
ferencd@0 639 : std::string(path.begin() + s, path.begin() + p);
ferencd@0 640
ferencd@0 641 if (!x.empty())
ferencd@0 642 newFolder = newFolder->getFolder(x);
ferencd@0 643
ferencd@0 644 if (p == std::string::npos)
ferencd@0 645 break;
ferencd@0 646 }
ferencd@0 647
ferencd@0 648 newFolder->open(vmime::net::folder::MODE_READ_WRITE);
ferencd@0 649
ferencd@0 650 count = newFolder->getMessageCount();
ferencd@0 651
ferencd@0 652 std::cout << std::endl;
ferencd@0 653 std::cout << count << " message(s) in this folder" << std::endl;
ferencd@0 654
ferencd@0 655 f->close(true); // 'true' to expunge deleted messages
ferencd@0 656 f = newFolder;
ferencd@0 657
ferencd@0 658 break;
ferencd@0 659 }
ferencd@0 660 // Add message
ferencd@0 661 case 10:
ferencd@0 662 {
ferencd@0 663 vmime::messageBuilder mb;
ferencd@0 664
ferencd@0 665 mb.setExpeditor(vmime::mailbox("me@somewhere.com"));
ferencd@0 666
ferencd@0 667 vmime::addressList to;
ferencd@0 668 to.appendAddress(vmime::make_shared <vmime::mailbox>("you@elsewhere.com"));
ferencd@0 669 mb.setRecipients(to);
ferencd@0 670
ferencd@0 671 mb.setSubject(vmime::text("Test message from VMime example6"));
ferencd@0 672 mb.getTextPart()->setText(vmime::make_shared <vmime::stringContentHandler>(
ferencd@0 673 "Body of test message from VMime example6."));
ferencd@0 674
ferencd@0 675 vmime::shared_ptr <vmime::message> msg = mb.construct();
ferencd@0 676
ferencd@0 677 vmime::net::messageSet set = f->addMessage(msg);
ferencd@0 678
ferencd@0 679 if (set.isEmpty())
ferencd@0 680 {
ferencd@0 681 std::cout << "Message has successfully been added, "
ferencd@0 682 << "but its UID/number is not known." << std::endl;
ferencd@0 683 }
ferencd@0 684 else
ferencd@0 685 {
ferencd@0 686 const vmime::net::messageRange& range = set.getRangeAt(0);
ferencd@0 687
ferencd@0 688 if (set.isUIDSet())
ferencd@0 689 {
ferencd@0 690 const vmime::net::message::uid uid =
ferencd@0 691 dynamic_cast <const vmime::net::UIDMessageRange&>(range).getFirst();
ferencd@0 692
ferencd@0 693 std::cout << "Message has successfully been added, "
ferencd@0 694 << "its UID is '" << uid << "'." << std::endl;
ferencd@0 695 }
ferencd@0 696 else
ferencd@0 697 {
ferencd@0 698 const int number =
ferencd@0 699 dynamic_cast <const vmime::net::numberMessageRange&>(range).getFirst();
ferencd@0 700
ferencd@0 701 std::cout << "Message has successfully been added, "
ferencd@0 702 << "its number is '" << number << "'." << std::endl;
ferencd@0 703 }
ferencd@0 704 }
ferencd@0 705
ferencd@0 706 break;
ferencd@0 707 }
ferencd@0 708 // Copy message
ferencd@0 709 case 11:
ferencd@0 710 {
ferencd@0 711 vmime::net::messageSet set = f->copyMessages(f->getFullPath(),
ferencd@0 712 vmime::net::messageSet::byNumber(msg->getNumber()));
ferencd@0 713
ferencd@0 714 if (set.isEmpty())
ferencd@0 715 {
ferencd@0 716 std::cout << "Message has successfully been copied, "
ferencd@0 717 << "but its UID/number is not known." << std::endl;
ferencd@0 718 }
ferencd@0 719 else
ferencd@0 720 {
ferencd@0 721 const vmime::net::messageRange& range = set.getRangeAt(0);
ferencd@0 722
ferencd@0 723 if (set.isUIDSet())
ferencd@0 724 {
ferencd@0 725 const vmime::net::message::uid uid =
ferencd@0 726 dynamic_cast <const vmime::net::UIDMessageRange&>(range).getFirst();
ferencd@0 727
ferencd@0 728 std::cout << "Message has successfully been copied, "
ferencd@0 729 << "its UID is '" << uid << "'." << std::endl;
ferencd@0 730 }
ferencd@0 731 else
ferencd@0 732 {
ferencd@0 733 const int number =
ferencd@0 734 dynamic_cast <const vmime::net::numberMessageRange&>(range).getFirst();
ferencd@0 735
ferencd@0 736 std::cout << "Message has successfully been copied, "
ferencd@0 737 << "its number is '" << number << "'." << std::endl;
ferencd@0 738 }
ferencd@0 739 }
ferencd@0 740
ferencd@0 741 break;
ferencd@0 742 }
ferencd@0 743 // Display trace output
ferencd@0 744 case 12:
ferencd@0 745
ferencd@0 746 std::cout << std::endl;
ferencd@0 747 std::cout << "Connection Trace:" << std::endl;
ferencd@0 748 std::cout << "=================" << std::endl;
ferencd@0 749 std::cout << traceStream->str();
ferencd@0 750 break;
ferencd@0 751
ferencd@0 752 // Main menu
ferencd@0 753 case 13:
ferencd@0 754
ferencd@0 755 f->close(true); // 'true' to expunge deleted messages
ferencd@0 756 cont = false;
ferencd@0 757 break;
ferencd@0 758 }
ferencd@0 759
ferencd@0 760 /*
ferencd@0 761 // Append message
ferencd@0 762 std::istringstream iss(
ferencd@0 763 "From: me@localhost\r\n"
ferencd@0 764 "To: you@localhost\r\n"
ferencd@0 765 "Subject: Message Text\r\n"
ferencd@0 766 "\r\n"
ferencd@0 767 "This is a test message...\r\n"
ferencd@0 768 "Bye bye!\r\n"
ferencd@0 769 );
ferencd@0 770
ferencd@0 771 f->addMessage(iss, iss.str().size());
ferencd@0 772
ferencd@0 773 // Folder renaming
ferencd@0 774 {
ferencd@0 775 vmime::shared_ptr <vmime::net::folder> f = st->getFolder(vmime::net::folder::path("c"));
ferencd@0 776 f->rename(vmime::net::folder::path("c2"));
ferencd@0 777
ferencd@0 778 vmime::shared_ptr <vmime::net::folder> g = st->getFolder(vmime::net::folder::path("c2"));
ferencd@0 779 g->rename(vmime::net::folder::path("c"));
ferencd@0 780 }
ferencd@0 781
ferencd@0 782 // Message copy: copy all messages from 'f' to 'g'
ferencd@0 783 {
ferencd@0 784 vmime::shared_ptr <vmime::net::folder> g = st->getFolder(vmime::net::folder::path("TEMP"));
ferencd@0 785
ferencd@0 786 if (!g->exists())
ferencd@0 787 g->create(vmime::net::folder::TYPE_CONTAINS_MESSAGES);
ferencd@0 788
ferencd@0 789 f->copyMessages(g->getFullPath());
ferencd@0 790 }
ferencd@0 791 */
ferencd@0 792 }
ferencd@0 793 catch (vmime::exception& e)
ferencd@0 794 {
ferencd@0 795 std::cerr << std::endl;
ferencd@0 796 std::cerr << e << std::endl;
ferencd@0 797 }
ferencd@0 798 catch (std::exception& e)
ferencd@0 799 {
ferencd@0 800 std::cerr << std::endl;
ferencd@0 801 std::cerr << "std::exception: " << e.what() << std::endl;
ferencd@0 802 }
ferencd@0 803 } // for(cont)
ferencd@0 804
ferencd@0 805 st->disconnect();
ferencd@0 806 }
ferencd@0 807 catch (vmime::exception& e)
ferencd@0 808 {
ferencd@0 809 std::cerr << std::endl;
ferencd@0 810 std::cerr << e << std::endl;
ferencd@0 811 throw;
ferencd@0 812 }
ferencd@0 813 catch (std::exception& e)
ferencd@0 814 {
ferencd@0 815 std::cerr << std::endl;
ferencd@0 816 std::cerr << "std::exception: " << e.what() << std::endl;
ferencd@0 817 throw;
ferencd@0 818 }
ferencd@0 819 }
ferencd@0 820
ferencd@0 821
ferencd@0 822 /* Show the main menu.
ferencd@0 823 *
ferencd@0 824 * @return true to quit the program, false to continue
ferencd@0 825 */
ferencd@0 826 static bool menu()
ferencd@0 827 {
ferencd@0 828 std::vector <std::string> items;
ferencd@0 829
ferencd@0 830 items.push_back("Connect to a message store");
ferencd@0 831 items.push_back("Send a message");
ferencd@0 832 items.push_back("Quit");
ferencd@0 833
ferencd@0 834 switch (printMenu(items))
ferencd@0 835 {
ferencd@0 836 // Connect to store
ferencd@0 837 case 1:
ferencd@0 838
ferencd@0 839 connectStore();
ferencd@0 840 return false;
ferencd@0 841
ferencd@0 842 // Send a message
ferencd@0 843 case 2:
ferencd@0 844
ferencd@0 845 sendMessage();
ferencd@0 846 return false;
ferencd@0 847
ferencd@0 848 // Quit
ferencd@0 849 case 3:
ferencd@0 850
ferencd@0 851 return true;
ferencd@0 852
ferencd@0 853 // Other choice
ferencd@0 854 default:
ferencd@0 855
ferencd@0 856 return false;
ferencd@0 857 }
ferencd@0 858 }
ferencd@0 859
ferencd@0 860
ferencd@0 861 int main()
ferencd@0 862 {
ferencd@0 863 // Set the global C and C++ locale to the user-configured locale.
ferencd@0 864 // The locale should use UTF-8 encoding for these tests to run successfully.
ferencd@0 865 try
ferencd@0 866 {
ferencd@0 867 std::locale::global(std::locale(""));
ferencd@0 868 }
ferencd@0 869 catch (std::exception &)
ferencd@0 870 {
ferencd@0 871 std::setlocale(LC_ALL, "");
ferencd@0 872 }
ferencd@0 873
ferencd@0 874 for (bool quit = false ; !quit ; )
ferencd@0 875 {
ferencd@0 876 // Loop on main menu
ferencd@0 877 quit = menu();
ferencd@0 878 }
ferencd@0 879
ferencd@0 880 return 0;
ferencd@0 881 }
ferencd@0 882