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