diff 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
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/3rdparty/vmime/examples/example6.cpp	Tue Aug 17 11:19:54 2021 +0200
@@ -0,0 +1,882 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2013 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::make_shared <vmime::net::session>();
+
+
+/** 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;
+	int count = 0;
+
+	for (int 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() != NULL)
+		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 (int 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 << " ";
+
+	std::cout << getFolderPathString(folder) << 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);
+
+		int 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 <int, 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);
+
+					int 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:
+
+					f->fetchMessage(msg, vmime::net::fetchAttributes::ENVELOPE);
+
+#define ENV_HELPER(x) \
+	try { std::cout << msg->getHeader()->x()->generate() << std::endl; } \
+	catch (vmime::exception) { /* In case the header field does not exist. */ }
+
+					ENV_HELPER(From)
+					ENV_HELPER(To)
+					ENV_HELPER(Date)
+					ENV_HELPER(Subject)
+
+#undef ENV_HELPER
+
+					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:
+				{
+					int 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(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 int 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 int 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;
+}
+