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