ferencd@0: // ferencd@0: // VMime library (http://www.vmime.org) ferencd@0: // Copyright (C) 2002-2013 Vincent Richard ferencd@0: // ferencd@0: // This program is free software; you can redistribute it and/or ferencd@0: // modify it under the terms of the GNU General Public License as ferencd@0: // published by the Free Software Foundation; either version 3 of ferencd@0: // the License, or (at your option) any later version. ferencd@0: // ferencd@0: // This program is distributed in the hope that it will be useful, ferencd@0: // but WITHOUT ANY WARRANTY; without even the implied warranty of ferencd@0: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ferencd@0: // General Public License for more details. ferencd@0: // ferencd@0: // You should have received a copy of the GNU General Public License along ferencd@0: // with this program; if not, write to the Free Software Foundation, Inc., ferencd@0: // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ferencd@0: // ferencd@0: // Linking this library statically or dynamically with other modules is making ferencd@0: // a combined work based on this library. Thus, the terms and conditions of ferencd@0: // the GNU General Public License cover the whole combination. ferencd@0: // ferencd@0: ferencd@0: #include ferencd@0: #include ferencd@0: #include ferencd@0: #include ferencd@0: #include ferencd@0: #include ferencd@0: ferencd@0: #include "vmime/vmime.hpp" ferencd@0: #include "vmime/platforms/posix/posixHandler.hpp" ferencd@0: ferencd@0: #include "example6_tracer.hpp" ferencd@0: #include "example6_authenticator.hpp" ferencd@0: #include "example6_certificateVerifier.hpp" ferencd@0: #include "example6_timeoutHandler.hpp" ferencd@0: ferencd@0: ferencd@0: // Global session object ferencd@0: static vmime::shared_ptr g_session ferencd@0: = vmime::make_shared (); ferencd@0: ferencd@0: ferencd@0: /** Returns the messaging protocols supported by VMime. ferencd@0: * ferencd@0: * @param type service type (vmime::net::service::TYPE_STORE or ferencd@0: * vmime::net::service::TYPE_TRANSPORT) ferencd@0: */ ferencd@0: static const std::string findAvailableProtocols(const vmime::net::service::Type type) ferencd@0: { ferencd@0: vmime::shared_ptr sf = ferencd@0: vmime::net::serviceFactory::getInstance(); ferencd@0: ferencd@0: std::ostringstream res; ferencd@0: int count = 0; ferencd@0: ferencd@0: for (int i = 0 ; i < sf->getServiceCount() ; ++i) ferencd@0: { ferencd@0: const vmime::net::serviceFactory::registeredService& serv = *sf->getServiceAt(i); ferencd@0: ferencd@0: if (serv.getType() == type) ferencd@0: { ferencd@0: if (count != 0) ferencd@0: res << ", "; ferencd@0: ferencd@0: res << serv.getName(); ferencd@0: ++count; ferencd@0: } ferencd@0: } ferencd@0: ferencd@0: return res.str(); ferencd@0: } ferencd@0: ferencd@0: ferencd@0: // Exception helper ferencd@0: static std::ostream& operator<<(std::ostream& os, const vmime::exception& e) ferencd@0: { ferencd@0: os << "* vmime::exceptions::" << e.name() << std::endl; ferencd@0: os << " what = " << e.what() << std::endl; ferencd@0: ferencd@0: // More information for special exceptions ferencd@0: if (dynamic_cast (&e)) ferencd@0: { ferencd@0: const vmime::exceptions::command_error& cee = ferencd@0: dynamic_cast (e); ferencd@0: ferencd@0: os << " command = " << cee.command() << std::endl; ferencd@0: os << " response = " << cee.response() << std::endl; ferencd@0: } ferencd@0: ferencd@0: if (dynamic_cast (&e)) ferencd@0: { ferencd@0: const vmime::exceptions::invalid_response& ir = ferencd@0: dynamic_cast (e); ferencd@0: ferencd@0: os << " response = " << ir.response() << std::endl; ferencd@0: } ferencd@0: ferencd@0: if (dynamic_cast (&e)) ferencd@0: { ferencd@0: const vmime::exceptions::connection_greeting_error& cgee = ferencd@0: dynamic_cast (e); ferencd@0: ferencd@0: os << " response = " << cgee.response() << std::endl; ferencd@0: } ferencd@0: ferencd@0: if (dynamic_cast (&e)) ferencd@0: { ferencd@0: const vmime::exceptions::authentication_error& aee = ferencd@0: dynamic_cast (e); ferencd@0: ferencd@0: os << " response = " << aee.response() << std::endl; ferencd@0: } ferencd@0: ferencd@0: if (dynamic_cast (&e)) ferencd@0: { ferencd@0: const vmime::exceptions::filesystem_exception& fse = ferencd@0: dynamic_cast (e); ferencd@0: ferencd@0: os << " path = " << vmime::platform::getHandler()-> ferencd@0: getFileSystemFactory()->pathToString(fse.path()) << std::endl; ferencd@0: } ferencd@0: ferencd@0: if (e.other() != NULL) ferencd@0: os << *e.other(); ferencd@0: ferencd@0: return os; ferencd@0: } ferencd@0: ferencd@0: ferencd@0: /** Print the MIME structure of a message on the standard output. ferencd@0: * ferencd@0: * @param s structure object ferencd@0: * @param level current depth ferencd@0: */ ferencd@0: static void printStructure(vmime::shared_ptr s, const int level = 0) ferencd@0: { ferencd@0: for (int i = 0 ; i < s->getPartCount() ; ++i) ferencd@0: { ferencd@0: vmime::shared_ptr part = s->getPartAt(i); ferencd@0: ferencd@0: for (int j = 0 ; j < level * 2 ; ++j) ferencd@0: std::cout << " "; ferencd@0: ferencd@0: std::cout << (part->getNumber() + 1) << ". " ferencd@0: << part->getType().generate() ferencd@0: << " [" << part->getSize() << " byte(s)]" ferencd@0: << std::endl; ferencd@0: ferencd@0: printStructure(part->getStructure(), level + 1); ferencd@0: } ferencd@0: } ferencd@0: ferencd@0: ferencd@0: static const vmime::string getFolderPathString(vmime::shared_ptr f) ferencd@0: { ferencd@0: const vmime::string n = f->getName().getBuffer(); ferencd@0: ferencd@0: if (n.empty()) // root folder ferencd@0: { ferencd@0: return "/"; ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: vmime::shared_ptr p = f->getParent(); ferencd@0: return getFolderPathString(p) + n + "/"; ferencd@0: } ferencd@0: } ferencd@0: ferencd@0: ferencd@0: /** Print folders and sub-folders on the standard output. ferencd@0: * ferencd@0: * @param folder current folder ferencd@0: */ ferencd@0: static void printFolders(vmime::shared_ptr folder, const int level = 0) ferencd@0: { ferencd@0: for (int j = 0 ; j < level * 2 ; ++j) ferencd@0: std::cout << " "; ferencd@0: ferencd@0: std::cout << getFolderPathString(folder) << std::endl; ferencd@0: ferencd@0: std::vector > subFolders = folder->getFolders(false); ferencd@0: ferencd@0: for (unsigned int i = 0 ; i < subFolders.size() ; ++i) ferencd@0: printFolders(subFolders[i], level + 1); ferencd@0: } ferencd@0: ferencd@0: ferencd@0: /** Print a menu on the standard output. ferencd@0: * ferencd@0: * @param choices menu choices ferencd@0: */ ferencd@0: static unsigned int printMenu(const std::vector & choices) ferencd@0: { ferencd@0: std::cout << std::endl; ferencd@0: ferencd@0: for (unsigned int i = 0 ; i < choices.size() ; ++i) ferencd@0: std::cout << " " << (i + 1) << ". " << choices[i] << std::endl; ferencd@0: ferencd@0: std::cout << std::endl; ferencd@0: std::cout << " Your choice? [1-" << choices.size() << "] "; ferencd@0: std::cout.flush(); ferencd@0: ferencd@0: std::string line; ferencd@0: std::getline(std::cin, line); ferencd@0: ferencd@0: std::istringstream iss(line); ferencd@0: ferencd@0: unsigned int choice = 0; ferencd@0: iss >> choice; ferencd@0: ferencd@0: std::cout << std::endl; ferencd@0: ferencd@0: if (choice < 1 || choice > choices.size()) ferencd@0: return 0; ferencd@0: else ferencd@0: return choice; ferencd@0: } ferencd@0: ferencd@0: ferencd@0: /** Send a message interactively. ferencd@0: */ ferencd@0: static void sendMessage() ferencd@0: { ferencd@0: try ferencd@0: { ferencd@0: // Request user to enter an URL ferencd@0: std::cout << "Enter an URL to connect to transport service." << std::endl; ferencd@0: std::cout << "Available protocols: " << findAvailableProtocols(vmime::net::service::TYPE_TRANSPORT) << std::endl; ferencd@0: std::cout << "(eg. smtp://myserver.com, sendmail://localhost)" << std::endl; ferencd@0: std::cout << "> "; ferencd@0: std::cout.flush(); ferencd@0: ferencd@0: vmime::string urlString; ferencd@0: std::getline(std::cin, urlString); ferencd@0: ferencd@0: vmime::utility::url url(urlString); ferencd@0: ferencd@0: vmime::shared_ptr tr; ferencd@0: ferencd@0: if (url.getUsername().empty() || url.getPassword().empty()) ferencd@0: tr = g_session->getTransport(url, vmime::make_shared ()); ferencd@0: else ferencd@0: tr = g_session->getTransport(url); ferencd@0: ferencd@0: #if VMIME_HAVE_TLS_SUPPORT ferencd@0: ferencd@0: // Enable TLS support if available ferencd@0: tr->setProperty("connection.tls", true); ferencd@0: ferencd@0: // Set the time out handler ferencd@0: tr->setTimeoutHandlerFactory(vmime::make_shared ()); ferencd@0: ferencd@0: // Set the object responsible for verifying certificates, in the ferencd@0: // case a secured connection is used (TLS/SSL) ferencd@0: tr->setCertificateVerifier ferencd@0: (vmime::make_shared ()); ferencd@0: ferencd@0: #endif // VMIME_HAVE_TLS_SUPPORT ferencd@0: ferencd@0: // You can also set some properties (see example7 to know the properties ferencd@0: // available for each service). For example, for SMTP: ferencd@0: if (!url.getUsername().empty() || !url.getPassword().empty()) ferencd@0: tr->setProperty("options.need-authentication", true); ferencd@0: ferencd@0: // Trace communication between client and server ferencd@0: vmime::shared_ptr traceStream = vmime::make_shared (); ferencd@0: tr->setTracerFactory(vmime::make_shared (traceStream)); ferencd@0: ferencd@0: // Information about the mail ferencd@0: std::cout << "Enter email of the expeditor (eg. me@somewhere.com): "; ferencd@0: std::cout.flush(); ferencd@0: ferencd@0: vmime::string fromString; ferencd@0: std::getline(std::cin, fromString); ferencd@0: ferencd@0: vmime::mailbox from(fromString); ferencd@0: vmime::mailboxList to; ferencd@0: ferencd@0: for (bool cont = true ; cont ; ) ferencd@0: { ferencd@0: std::cout << "Enter email of the recipient (empty to stop): "; ferencd@0: std::cout.flush(); ferencd@0: ferencd@0: vmime::string toString; ferencd@0: std::getline(std::cin, toString); ferencd@0: ferencd@0: cont = (toString.size() != 0); ferencd@0: ferencd@0: if (cont) ferencd@0: to.appendMailbox(vmime::make_shared (toString)); ferencd@0: } ferencd@0: ferencd@0: std::cout << "Enter message data, including headers (end with '.' on a single line):" << std::endl; ferencd@0: ferencd@0: std::ostringstream data; ferencd@0: ferencd@0: for (bool cont = true ; cont ; ) ferencd@0: { ferencd@0: std::string line; ferencd@0: std::getline(std::cin, line); ferencd@0: ferencd@0: if (line == ".") ferencd@0: cont = false; ferencd@0: else ferencd@0: data << line << "\r\n"; ferencd@0: } ferencd@0: ferencd@0: // Connect to server ferencd@0: tr->connect(); ferencd@0: ferencd@0: // Send the message ferencd@0: vmime::string msgData = data.str(); ferencd@0: vmime::utility::inputStreamStringAdapter vis(msgData); ferencd@0: ferencd@0: tr->send(from, to, vis, msgData.length()); ferencd@0: ferencd@0: // Note: you could also write this: ferencd@0: // vmime::message msg; ferencd@0: // ... ferencd@0: // tr->send(&msg); ferencd@0: ferencd@0: // Display connection log ferencd@0: std::cout << std::endl; ferencd@0: std::cout << "Connection Trace:" << std::endl; ferencd@0: std::cout << "=================" << std::endl; ferencd@0: std::cout << traceStream->str(); ferencd@0: ferencd@0: tr->disconnect(); ferencd@0: } ferencd@0: catch (vmime::exception& e) ferencd@0: { ferencd@0: std::cerr << std::endl; ferencd@0: std::cerr << e << std::endl; ferencd@0: throw; ferencd@0: } ferencd@0: catch (std::exception& e) ferencd@0: { ferencd@0: std::cerr << std::endl; ferencd@0: std::cerr << "std::exception: " << e.what() << std::endl; ferencd@0: throw; ferencd@0: } ferencd@0: } ferencd@0: ferencd@0: ferencd@0: /** Connect to a message store interactively. ferencd@0: */ ferencd@0: static void connectStore() ferencd@0: { ferencd@0: try ferencd@0: { ferencd@0: // Request user to enter an URL ferencd@0: std::cout << "Enter an URL to connect to store service." << std::endl; ferencd@0: std::cout << "Available protocols: " << findAvailableProtocols(vmime::net::service::TYPE_STORE) << std::endl; ferencd@0: std::cout << "(eg. pop3://user:pass@myserver.com, imap://myserver.com:123)" << std::endl; ferencd@0: std::cout << "> "; ferencd@0: std::cout.flush(); ferencd@0: ferencd@0: vmime::string urlString; ferencd@0: std::getline(std::cin, urlString); ferencd@0: ferencd@0: vmime::utility::url url(urlString); ferencd@0: ferencd@0: // If no authenticator is given in argument to getStore(), a default one ferencd@0: // is used. Its behaviour is to get the user credentials from the ferencd@0: // session properties "auth.username" and "auth.password". ferencd@0: vmime::shared_ptr st; ferencd@0: ferencd@0: if (url.getUsername().empty() || url.getPassword().empty()) ferencd@0: st = g_session->getStore(url, vmime::make_shared ()); ferencd@0: else ferencd@0: st = g_session->getStore(url); ferencd@0: ferencd@0: #if VMIME_HAVE_TLS_SUPPORT ferencd@0: ferencd@0: // Enable TLS support if available ferencd@0: st->setProperty("connection.tls", true); ferencd@0: ferencd@0: // Set the time out handler ferencd@0: st->setTimeoutHandlerFactory(vmime::make_shared ()); ferencd@0: ferencd@0: // Set the object responsible for verifying certificates, in the ferencd@0: // case a secured connection is used (TLS/SSL) ferencd@0: st->setCertificateVerifier ferencd@0: (vmime::make_shared ()); ferencd@0: ferencd@0: #endif // VMIME_HAVE_TLS_SUPPORT ferencd@0: ferencd@0: // Trace communication between client and server ferencd@0: vmime::shared_ptr traceStream = vmime::make_shared (); ferencd@0: st->setTracerFactory(vmime::make_shared (traceStream)); ferencd@0: ferencd@0: // Connect to the mail store ferencd@0: st->connect(); ferencd@0: ferencd@0: // Display some information about the connection ferencd@0: vmime::shared_ptr ci = st->getConnectionInfos(); ferencd@0: ferencd@0: std::cout << std::endl; ferencd@0: std::cout << "Connected to '" << ci->getHost() << "' (port " << ci->getPort() << ")" << std::endl; ferencd@0: std::cout << "Connection is " << (st->isSecuredConnection() ? "" : "NOT ") << "secured." << std::endl; ferencd@0: ferencd@0: // Open the default folder in this store ferencd@0: vmime::shared_ptr f = st->getDefaultFolder(); ferencd@0: // vmime::shared_ptr f = st->getFolder(vmime::utility::path("a")); ferencd@0: ferencd@0: f->open(vmime::net::folder::MODE_READ_WRITE); ferencd@0: ferencd@0: int count = f->getMessageCount(); ferencd@0: ferencd@0: std::cout << std::endl; ferencd@0: std::cout << count << " message(s) in your inbox" << std::endl; ferencd@0: ferencd@0: for (bool cont = true ; cont ; ) ferencd@0: { ferencd@0: typedef std::map > MessageList; ferencd@0: MessageList msgList; ferencd@0: ferencd@0: try ferencd@0: { ferencd@0: std::vector choices; ferencd@0: ferencd@0: choices.push_back("Show message flags"); ferencd@0: choices.push_back("Show message structure"); ferencd@0: choices.push_back("Show message header"); ferencd@0: choices.push_back("Show message envelope"); ferencd@0: choices.push_back("Extract whole message"); ferencd@0: choices.push_back("Extract attachments"); ferencd@0: choices.push_back("Status"); ferencd@0: choices.push_back("List folders"); ferencd@0: choices.push_back("Change folder"); ferencd@0: choices.push_back("Add message (to the current folder)"); ferencd@0: choices.push_back("Copy message (into the current folder)"); ferencd@0: choices.push_back("Display trace output"); ferencd@0: choices.push_back("Return to main menu"); ferencd@0: ferencd@0: const int choice = printMenu(choices); ferencd@0: ferencd@0: // Request message number ferencd@0: vmime::shared_ptr msg; ferencd@0: ferencd@0: if (choice == 1 || choice == 2 || choice == 3 || choice == 4 || ferencd@0: choice == 5 || choice == 6 || choice == 11) ferencd@0: { ferencd@0: std::cout << "Enter message number: "; ferencd@0: std::cout.flush(); ferencd@0: ferencd@0: std::string line; ferencd@0: std::getline(std::cin, line); ferencd@0: ferencd@0: std::istringstream iss(line); ferencd@0: ferencd@0: int num = 0; ferencd@0: iss >> num; ferencd@0: ferencd@0: if (num < 1 || num > f->getMessageCount()) ferencd@0: { ferencd@0: std::cerr << "Invalid message number." << std::endl; ferencd@0: continue; ferencd@0: } ferencd@0: ferencd@0: MessageList::iterator it = msgList.find(num); ferencd@0: ferencd@0: if (it != msgList.end()) ferencd@0: { ferencd@0: msg = (*it).second; ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: msg = f->getMessage(num); ferencd@0: msgList.insert(MessageList::value_type(num, msg)); ferencd@0: } ferencd@0: ferencd@0: std::cout << std::endl; ferencd@0: } ferencd@0: ferencd@0: switch (choice) ferencd@0: { ferencd@0: // Show message flags ferencd@0: case 1: ferencd@0: ferencd@0: f->fetchMessage(msg, vmime::net::fetchAttributes::FLAGS); ferencd@0: ferencd@0: if (msg->getFlags() & vmime::net::message::FLAG_SEEN) ferencd@0: std::cout << "FLAG_SEEN" << std::endl; ferencd@0: if (msg->getFlags() & vmime::net::message::FLAG_RECENT) ferencd@0: std::cout << "FLAG_RECENT" << std::endl; ferencd@0: if (msg->getFlags() & vmime::net::message::FLAG_REPLIED) ferencd@0: std::cout << "FLAG_REPLIED" << std::endl; ferencd@0: if (msg->getFlags() & vmime::net::message::FLAG_DELETED) ferencd@0: std::cout << "FLAG_DELETED" << std::endl; ferencd@0: if (msg->getFlags() & vmime::net::message::FLAG_MARKED) ferencd@0: std::cout << "FLAG_MARKED" << std::endl; ferencd@0: if (msg->getFlags() & vmime::net::message::FLAG_PASSED) ferencd@0: std::cout << "FLAG_PASSED" << std::endl; ferencd@0: ferencd@0: break; ferencd@0: ferencd@0: // Show message structure ferencd@0: case 2: ferencd@0: ferencd@0: f->fetchMessage(msg, vmime::net::fetchAttributes::STRUCTURE); ferencd@0: printStructure(msg->getStructure()); ferencd@0: break; ferencd@0: ferencd@0: // Show message header ferencd@0: case 3: ferencd@0: ferencd@0: f->fetchMessage(msg, vmime::net::fetchAttributes::FULL_HEADER); ferencd@0: std::cout << msg->getHeader()->generate() << std::endl; ferencd@0: break; ferencd@0: ferencd@0: // Show message envelope ferencd@0: case 4: ferencd@0: ferencd@0: f->fetchMessage(msg, vmime::net::fetchAttributes::ENVELOPE); ferencd@0: ferencd@0: #define ENV_HELPER(x) \ ferencd@0: try { std::cout << msg->getHeader()->x()->generate() << std::endl; } \ ferencd@0: catch (vmime::exception) { /* In case the header field does not exist. */ } ferencd@0: ferencd@0: ENV_HELPER(From) ferencd@0: ENV_HELPER(To) ferencd@0: ENV_HELPER(Date) ferencd@0: ENV_HELPER(Subject) ferencd@0: ferencd@0: #undef ENV_HELPER ferencd@0: ferencd@0: break; ferencd@0: ferencd@0: // Extract whole message ferencd@0: case 5: ferencd@0: { ferencd@0: vmime::utility::outputStreamAdapter out(std::cout); ferencd@0: msg->extract(out); ferencd@0: ferencd@0: break; ferencd@0: } ferencd@0: // Extract attachments ferencd@0: case 6: ferencd@0: { ferencd@0: vmime::shared_ptr parsedMsg = msg->getParsedMessage(); ferencd@0: ferencd@0: std::vector > attchs = ferencd@0: vmime::attachmentHelper::findAttachmentsInMessage(parsedMsg); ferencd@0: ferencd@0: if (attchs.size() > 0) ferencd@0: { ferencd@0: std::cout << attchs.size() << " attachments found." << std::endl; ferencd@0: ferencd@0: for (std::vector >::iterator ferencd@0: it = attchs.begin() ; it != attchs.end() ; ++it) ferencd@0: { ferencd@0: vmime::shared_ptr att = *it; ferencd@0: ferencd@0: // Get attachment size ferencd@0: vmime::size_t size = 0; ferencd@0: ferencd@0: if (att->getData()->isEncoded()) ferencd@0: size = att->getData()->getEncoding().getEncoder()->getDecodedSize(att->getData()->getLength()); ferencd@0: else ferencd@0: size = att->getData()->getLength(); ferencd@0: ferencd@0: std::cout << "Found attachment '" << att->getName().getBuffer() << "'" ferencd@0: << ", size is " << size << " bytes:" << std::endl; ferencd@0: ferencd@0: // Get attachment data ferencd@0: std::cout << std::endl; ferencd@0: std::cout << "========== BEGIN CONTENT ==========" << std::endl; ferencd@0: ferencd@0: vmime::utility::outputStreamAdapter osa(std::cout); ferencd@0: att->getData()->extract(osa); ferencd@0: ferencd@0: std::cout << std::endl; ferencd@0: std::cout << "========== END CONTENT ==========" << std::endl; ferencd@0: ferencd@0: // Or write it to a file ferencd@0: /* ferencd@0: vmime::shared_ptr fsf ferencd@0: = vmime::platform::getHandler()->getFileSystemFactory(); ferencd@0: ferencd@0: vmime::shared_ptr file ferencd@0: = fsf->create(vmime::utility::path::fromString ferencd@0: ("/path/to/attachment-file", "/", vmime::charsets::UTF_8)); ferencd@0: // -or- ("C:\\Temp\\attachment-file", "\\", vmime::charsets::UTF_8)); ferencd@0: ferencd@0: file->createFile(); ferencd@0: ferencd@0: vmime::shared_ptr output = ferencd@0: file->getFileWriter()->getOutputStream(); ferencd@0: ferencd@0: att->getData()->extract(*output.get()); ferencd@0: */ ferencd@0: } ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: std::cout << "No attachments found." << std::endl; ferencd@0: } ferencd@0: ferencd@0: break; ferencd@0: } ferencd@0: // Status ferencd@0: case 7: ferencd@0: { ferencd@0: int count, unseen; ferencd@0: f->status(count, unseen); ferencd@0: ferencd@0: std::cout << "Status: count=" << count << ", unseen=" << unseen << std::endl; ferencd@0: break; ferencd@0: } ferencd@0: // List folders ferencd@0: case 8: ferencd@0: { ferencd@0: vmime::shared_ptr ferencd@0: root = st->getRootFolder(); ferencd@0: ferencd@0: printFolders(root); ferencd@0: break; ferencd@0: } ferencd@0: // Change folder ferencd@0: case 9: ferencd@0: { ferencd@0: std::cout << "Enter folder path (eg. /root/subfolder):" << std::endl; ferencd@0: std::cout.flush(); ferencd@0: ferencd@0: std::string path; ferencd@0: std::getline(std::cin, path); ferencd@0: ferencd@0: vmime::shared_ptr newFolder = st->getRootFolder(); ferencd@0: ferencd@0: for (std::string::size_type s = 0, p = 0 ; ; s = p + 1) ferencd@0: { ferencd@0: p = path.find_first_of('/', s); ferencd@0: ferencd@0: const std::string x = (p == std::string::npos) ferencd@0: ? std::string(path.begin() + s, path.end()) ferencd@0: : std::string(path.begin() + s, path.begin() + p); ferencd@0: ferencd@0: if (!x.empty()) ferencd@0: newFolder = newFolder->getFolder(x); ferencd@0: ferencd@0: if (p == std::string::npos) ferencd@0: break; ferencd@0: } ferencd@0: ferencd@0: newFolder->open(vmime::net::folder::MODE_READ_WRITE); ferencd@0: ferencd@0: count = newFolder->getMessageCount(); ferencd@0: ferencd@0: std::cout << std::endl; ferencd@0: std::cout << count << " message(s) in this folder" << std::endl; ferencd@0: ferencd@0: f->close(true); // 'true' to expunge deleted messages ferencd@0: f = newFolder; ferencd@0: ferencd@0: break; ferencd@0: } ferencd@0: // Add message ferencd@0: case 10: ferencd@0: { ferencd@0: vmime::messageBuilder mb; ferencd@0: ferencd@0: mb.setExpeditor(vmime::mailbox("me@somewhere.com")); ferencd@0: ferencd@0: vmime::addressList to; ferencd@0: to.appendAddress(vmime::make_shared ("you@elsewhere.com")); ferencd@0: mb.setRecipients(to); ferencd@0: ferencd@0: mb.setSubject(vmime::text("Test message from VMime example6")); ferencd@0: mb.getTextPart()->setText(vmime::make_shared ( ferencd@0: "Body of test message from VMime example6.")); ferencd@0: ferencd@0: vmime::shared_ptr msg = mb.construct(); ferencd@0: ferencd@0: vmime::net::messageSet set = f->addMessage(msg); ferencd@0: ferencd@0: if (set.isEmpty()) ferencd@0: { ferencd@0: std::cout << "Message has successfully been added, " ferencd@0: << "but its UID/number is not known." << std::endl; ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: const vmime::net::messageRange& range = set.getRangeAt(0); ferencd@0: ferencd@0: if (set.isUIDSet()) ferencd@0: { ferencd@0: const vmime::net::message::uid uid = ferencd@0: dynamic_cast (range).getFirst(); ferencd@0: ferencd@0: std::cout << "Message has successfully been added, " ferencd@0: << "its UID is '" << uid << "'." << std::endl; ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: const int number = ferencd@0: dynamic_cast (range).getFirst(); ferencd@0: ferencd@0: std::cout << "Message has successfully been added, " ferencd@0: << "its number is '" << number << "'." << std::endl; ferencd@0: } ferencd@0: } ferencd@0: ferencd@0: break; ferencd@0: } ferencd@0: // Copy message ferencd@0: case 11: ferencd@0: { ferencd@0: vmime::net::messageSet set = f->copyMessages(f->getFullPath(), ferencd@0: vmime::net::messageSet::byNumber(msg->getNumber())); ferencd@0: ferencd@0: if (set.isEmpty()) ferencd@0: { ferencd@0: std::cout << "Message has successfully been copied, " ferencd@0: << "but its UID/number is not known." << std::endl; ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: const vmime::net::messageRange& range = set.getRangeAt(0); ferencd@0: ferencd@0: if (set.isUIDSet()) ferencd@0: { ferencd@0: const vmime::net::message::uid uid = ferencd@0: dynamic_cast (range).getFirst(); ferencd@0: ferencd@0: std::cout << "Message has successfully been copied, " ferencd@0: << "its UID is '" << uid << "'." << std::endl; ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: const int number = ferencd@0: dynamic_cast (range).getFirst(); ferencd@0: ferencd@0: std::cout << "Message has successfully been copied, " ferencd@0: << "its number is '" << number << "'." << std::endl; ferencd@0: } ferencd@0: } ferencd@0: ferencd@0: break; ferencd@0: } ferencd@0: // Display trace output ferencd@0: case 12: ferencd@0: ferencd@0: std::cout << std::endl; ferencd@0: std::cout << "Connection Trace:" << std::endl; ferencd@0: std::cout << "=================" << std::endl; ferencd@0: std::cout << traceStream->str(); ferencd@0: break; ferencd@0: ferencd@0: // Main menu ferencd@0: case 13: ferencd@0: ferencd@0: f->close(true); // 'true' to expunge deleted messages ferencd@0: cont = false; ferencd@0: break; ferencd@0: } ferencd@0: ferencd@0: /* ferencd@0: // Append message ferencd@0: std::istringstream iss( ferencd@0: "From: me@localhost\r\n" ferencd@0: "To: you@localhost\r\n" ferencd@0: "Subject: Message Text\r\n" ferencd@0: "\r\n" ferencd@0: "This is a test message...\r\n" ferencd@0: "Bye bye!\r\n" ferencd@0: ); ferencd@0: ferencd@0: f->addMessage(iss, iss.str().size()); ferencd@0: ferencd@0: // Folder renaming ferencd@0: { ferencd@0: vmime::shared_ptr f = st->getFolder(vmime::net::folder::path("c")); ferencd@0: f->rename(vmime::net::folder::path("c2")); ferencd@0: ferencd@0: vmime::shared_ptr g = st->getFolder(vmime::net::folder::path("c2")); ferencd@0: g->rename(vmime::net::folder::path("c")); ferencd@0: } ferencd@0: ferencd@0: // Message copy: copy all messages from 'f' to 'g' ferencd@0: { ferencd@0: vmime::shared_ptr g = st->getFolder(vmime::net::folder::path("TEMP")); ferencd@0: ferencd@0: if (!g->exists()) ferencd@0: g->create(vmime::net::folder::TYPE_CONTAINS_MESSAGES); ferencd@0: ferencd@0: f->copyMessages(g->getFullPath()); ferencd@0: } ferencd@0: */ ferencd@0: } ferencd@0: catch (vmime::exception& e) ferencd@0: { ferencd@0: std::cerr << std::endl; ferencd@0: std::cerr << e << std::endl; ferencd@0: } ferencd@0: catch (std::exception& e) ferencd@0: { ferencd@0: std::cerr << std::endl; ferencd@0: std::cerr << "std::exception: " << e.what() << std::endl; ferencd@0: } ferencd@0: } // for(cont) ferencd@0: ferencd@0: st->disconnect(); ferencd@0: } ferencd@0: catch (vmime::exception& e) ferencd@0: { ferencd@0: std::cerr << std::endl; ferencd@0: std::cerr << e << std::endl; ferencd@0: throw; ferencd@0: } ferencd@0: catch (std::exception& e) ferencd@0: { ferencd@0: std::cerr << std::endl; ferencd@0: std::cerr << "std::exception: " << e.what() << std::endl; ferencd@0: throw; ferencd@0: } ferencd@0: } ferencd@0: ferencd@0: ferencd@0: /* Show the main menu. ferencd@0: * ferencd@0: * @return true to quit the program, false to continue ferencd@0: */ ferencd@0: static bool menu() ferencd@0: { ferencd@0: std::vector items; ferencd@0: ferencd@0: items.push_back("Connect to a message store"); ferencd@0: items.push_back("Send a message"); ferencd@0: items.push_back("Quit"); ferencd@0: ferencd@0: switch (printMenu(items)) ferencd@0: { ferencd@0: // Connect to store ferencd@0: case 1: ferencd@0: ferencd@0: connectStore(); ferencd@0: return false; ferencd@0: ferencd@0: // Send a message ferencd@0: case 2: ferencd@0: ferencd@0: sendMessage(); ferencd@0: return false; ferencd@0: ferencd@0: // Quit ferencd@0: case 3: ferencd@0: ferencd@0: return true; ferencd@0: ferencd@0: // Other choice ferencd@0: default: ferencd@0: ferencd@0: return false; ferencd@0: } ferencd@0: } ferencd@0: ferencd@0: ferencd@0: int main() ferencd@0: { ferencd@0: // Set the global C and C++ locale to the user-configured locale. ferencd@0: // The locale should use UTF-8 encoding for these tests to run successfully. ferencd@0: try ferencd@0: { ferencd@0: std::locale::global(std::locale("")); ferencd@0: } ferencd@0: catch (std::exception &) ferencd@0: { ferencd@0: std::setlocale(LC_ALL, ""); ferencd@0: } ferencd@0: ferencd@0: for (bool quit = false ; !quit ; ) ferencd@0: { ferencd@0: // Loop on main menu ferencd@0: quit = menu(); ferencd@0: } ferencd@0: ferencd@0: return 0; ferencd@0: } ferencd@0: