aboutsummaryrefslogtreecommitdiffstats
path: root/examples/example6.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'examples/example6.cpp')
-rw-r--r--examples/example6.cpp580
1 files changed, 429 insertions, 151 deletions
diff --git a/examples/example6.cpp b/examples/example6.cpp
index 304990d7..0cb493ce 100644
--- a/examples/example6.cpp
+++ b/examples/example6.cpp
@@ -18,36 +18,97 @@
//
#include <iostream>
+#include <sstream>
+#include <vector>
#include "vmime/vmime.hpp"
#include "vmime/platforms/posix/posixHandler.hpp"
-//
-// Authentification handler
-//
+// Global session object
+static vmime::utility::auto_ptr <vmime::messaging::session> g_session
+ = new vmime::messaging::session();
-class my_auth : public vmime::messaging::authenticator
+
+// Authentification handler
+class interactiveAuthenticator : public vmime::messaging::authenticator
{
const vmime::messaging::authenticationInfos requestAuthInfos() const
{
vmime::string username, password;
- std::cout << "Username: "; std::cout.flush();
- std::cin >> username;
+ std::cout << std::endl;
+ std::cout << "Please authenticate yourself:" << std::endl;
+
+ std::cout << " Username: ";
+ std::cout.flush();
+
+ std::getline(std::cin, username);
+
+ std::cout << " Password: ";
+ std::cout.flush();
- std::cout << "Password: "; std::cout.flush();
- std::cin >> password;
+ std::getline(std::cin, password);
return (vmime::messaging::authenticationInfos(username, password));
}
};
+// 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::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::platformDependant::getHandler()->
+ getFileSystemFactory()->pathToString(fse.path()) << std::endl;
+ }
+
+ if (e.other() != NULL)
+ os << *e.other();
+ return os;
+}
-void printStructure(const vmime::messaging::structure& s, int level = 0)
+/** Print the MIME structure of a message on the standard output.
+ *
+ * @param s structure object
+ * @param level current depth
+ */
+static void printStructure(const vmime::messaging::structure& s, const int level = 0)
{
for (int i = 1 ; i <= s.getCount() ; ++i)
{
@@ -66,172 +127,346 @@ void printStructure(const vmime::messaging::structure& s, int level = 0)
}
+static const vmime::string getFolderPathString(vmime::messaging::folder* f)
+{
+ const vmime::string n = f->getName().getBuffer();
-int main()
+ if (n.empty()) // root folder
+ {
+ return "/";
+ }
+ else
+ {
+ vmime::utility::auto_ptr <vmime::messaging::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::messaging::folder* folder, const int level = 0)
{
- // VMime initialization
- vmime::platformDependant::setHandler<vmime::platforms::posix::posixHandler>();
+ for (int j = 0 ; j < level * 2 ; ++j)
+ std::cout << " ";
- vmime::messaging::session sess;
- sess.getProperties()["store.protocol"] = "imap";
- sess.getProperties()["transport.protocol"] = "smtp";
+ std::cout << getFolderPathString(folder) << std::endl;
- my_auth auth;
+ std::vector <vmime::messaging::folder*> subFolders = folder->getFolders(false);
- try
+ for (unsigned int i = 0 ; i < subFolders.size() ; ++i)
{
- //
- // Test the sending of a message
- //
+ printFolders(subFolders[i], level + 1);
+ delete subFolders[i];
+ }
+}
-#if 0
- // Transport protocol configuration
- vmime::messaging::transport* tr = sess.getTransport();
- //sess.getProperties()[tr->getInfos().getPropertyPrefix() + "auth.username"] = "username";
- //sess.getProperties()[tr->getInfos().getPropertyPrefix() + "auth.password"] = "password";
+/** Print a menu on the standard output.
+ *
+ * @param choices menu choices
+ */
+static const unsigned int printMenu(const std::vector <std::string>& choices)
+{
+ std::cout << std::endl;
- sess.getProperties()[tr->getInfos().getPropertyPrefix() + "server.address"] = "smtp.mydomain.com";
+ for (unsigned int i = 0 ; i < choices.size() ; ++i)
+ std::cout << " " << (i + 1) << ". " << choices[i] << std::endl;
- //sess.getProperties()[tr->getInfos().getPropertyPrefix() + "options.need-authentification"] = true;
+ std::cout << std::endl;
+ std::cout << " Your choice? [1-" << choices.size() << "] ";
+ std::cout.flush();
- // Connection
- tr->connect();
+ std::string line;
+ std::getline(std::cin, line);
- // Expeditor
- vmime::mailbox from("[email protected]");
+ std::istringstream iss(line);
- // Recipients list
- vmime::mailboxList to;
- to.appendMailbox(new vmime::mailbox("[email protected]"));
- to.appendMailbox(new vmime::mailbox("[email protected]"));
+ unsigned int choice = 0;
+ iss >> choice;
- vmime::string str("[MESSAGE DATA: HEADER + BODY]");
- vmime::utility::inputStreamStringAdapter vis(str);
+ std::cout << std::endl;
- tr->send(from, to, vis, str.length());
+ if (choice < 1 || choice > choices.size())
+ return 0;
+ else
+ return choice;
+}
- // Note: you could also write this:
- // vmime::message msg;
- // ...
- // tr->send(&msg);
- tr->disconnect();
-#endif
+/** 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 << "(eg. smtp://myserver.com, sendmail://localhost)" << std::endl;
+ std::cout << "> ";
+ std::cout.flush();
- //
- // Test the access to a mail store
- //
+ vmime::string urlString;
+ std::getline(std::cin, urlString);
-#if 1
- // 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::messaging::store* st = sess.getStore(&auth);
+ vmime::utility::url url(urlString);
- // Store protocol configuration
- //sess.getProperties()[st->getInfos().getPropertyPrefix() + "auth.username"] = "username";
- //sess.getProperties()[st->getInfos().getPropertyPrefix() + "auth.password"] = "password";
+ interactiveAuthenticator auth;
- sess.getProperties()[st->getInfos().getPropertyPrefix() + "server.address"] = "imap.mydomain.com";
- //sess.getProperties()[st->getInfos().getPropertyPrefix() + "server.port"] = 110;
- //sess.getProperties()[st->getInfos().getPropertyPrefix() + "server.socket-factory"] = "default";
+ vmime::utility::auto_ptr <vmime::messaging::transport> tr =
+ g_session->getTransport(url, &auth);
- //sess.getProperties()[st->getInfos().getPropertyPrefix() + "options.apop"] = false;
- //sess.getProperties()[st->getInfos().getPropertyPrefix() + "options.apop.fallback"] = true;
+ // You can also set some properties (see example7 to know the properties
+ // available for each service). For example, for SMTP:
+// tr->setProperty("options.need-authentication", true);
- // Connection
- st->connect();
+ // Information about the mail
+ std::cout << "Enter email of the expeditor (eg. [email protected]): ";
+ std::cout.flush();
- // Open the default folder in this store
- vmime::messaging::folder* f = st->getDefaultFolder();
+ vmime::string fromString;
+ std::getline(std::cin, fromString);
- f->open(vmime::messaging::folder::MODE_READ_WRITE);
+ vmime::mailbox from(fromString);
+ vmime::mailboxList to;
- std::cout << f->getMessageCount() << " message(s) in your inbox" << std::endl;
+ for (bool cont = true ; cont ; )
+ {
+ std::cout << "Enter email of the recipient (empty to stop): ";
+ std::cout.flush();
- // Get a pointer to the first message
- vmime::messaging::message* m = f->getMessage(1);
+ vmime::string toString;
+ std::getline(std::cin, toString);
- // To fetch the header
- f->fetchMessage(m, vmime::messaging::folder::FETCH_ENVELOPE |
- vmime::messaging::folder::FETCH_CONTENT_INFO);
+ cont = (toString.size() != 0);
- // To retrieve the whole message
- std::ostringstream oss;
- vmime::utility::outputStreamAdapter out(oss);
+ if (cont)
+ to.appendMailbox(new vmime::mailbox(toString));
+ }
- m->extract(out);
+ std::cout << "Enter message data (end with '.' on a single line):" << std::endl;
- // To fetch the header
- f->fetchMessage(m, vmime::messaging::folder::FETCH_ENVELOPE |
- vmime::messaging::folder::FETCH_CONTENT_INFO |
- vmime::messaging::folder::FETCH_STRUCTURE |
- vmime::messaging::folder::FETCH_SIZE |
- //vmime::messaging::folder::FETCH_FULL_HEADER |
- vmime::messaging::folder::FETCH_SIZE |
- vmime::messaging::folder::FETCH_FLAGS |
- vmime::messaging::folder::FETCH_UID);
+ std::ostringstream data;
- // Print structure
- std::cout << "STRUCTURE:" << std::endl;
- std::cout << "==========" << std::endl;
+ for (bool cont = true ; cont ; )
+ {
+ std::string line;
+ std::getline(std::cin, line);
- printStructure(m->getStructure());
+ if (line == ".")
+ cont = false;
+ else
+ data << line << "\r\n";
+ }
- std::cout << std::endl;
+ // Connect to server
+ tr->connect();
- std::cout << "Size = " << m->getSize() << " byte(s)" << std::endl;
- std::cout << "UID = " << m->getUniqueId() << std::endl;
- std::cout << std::endl;
+ // Send the message
+ vmime::string msgData = data.str();
+ vmime::utility::inputStreamStringAdapter vis(msgData);
- std::cout << "ENVELOPE:" << std::endl;
- std::cout << "=========" << std::endl;
- try { std::cout << m->getHeader().From().generate() << std::endl; } catch (...) { }
- try { std::cout << m->getHeader().To().generate() << std::endl; } catch (...) { }
- try { std::cout << m->getHeader().Date().generate() << std::endl; } catch (...) { }
- try { std::cout << m->getHeader().Subject().generate() << std::endl; } catch (...) { }
+ tr->send(from, to, vis, msgData.length());
- std::cout << std::endl;
+ // Note: you could also write this:
+ // vmime::message msg;
+ // ...
+ // tr->send(&msg);
- std::cout << "FULL HEADER:" << std::endl;
- std::cout << "============" << std::endl;
- std::cout << m->getHeader().generate() << std::endl;
+ 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;
+ }
+}
- std::cout << std::endl;
- std::cout << "=========================================================" << std::endl;
- vmime::utility::outputStreamAdapter out2(std::cout);
- m->extractPart(m->getStructure()[1][2][1], out2, NULL); //, 0, 10);
+/** 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 << "(eg. pop3://user:[email protected], imap://myserver.com:123)" << std::endl;
+ std::cout << "> ";
+ std::cout.flush();
- std::cout << "=========================================================" << std::endl;
+ vmime::string urlString;
+ std::getline(std::cin, urlString);
- std::cout << std::endl;
- std::cout << "=========================================================" << std::endl;
+ vmime::utility::url url(urlString);
- m->fetchPartHeader(m->getStructure()[1][2][1]);
+ // 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".
+ interactiveAuthenticator auth;
- std::cout << m->getStructure()[1][2][1].getHeader().generate() << std::endl;
+ vmime::utility::auto_ptr <vmime::messaging::store> st =
+ g_session->getStore(url, &auth);
- std::cout << "=========================================================" << std::endl;
+ // Connect to the mail store
+ st->connect();
- // Flags manipulation
- std::cout << "Flags = " << m->getFlags() << std::endl;
- m->setFlags(vmime::messaging::message::FLAG_REPLIED, vmime::messaging::message::FLAG_MODE_ADD);
- std::cout << "Flags = " << m->getFlags() << std::endl;
- m->setFlags(vmime::messaging::message::FLAG_REPLIED, vmime::messaging::message::FLAG_MODE_REMOVE);
- std::cout << "Flags = " << m->getFlags() << std::endl;
+ // Open the default folder in this store
+ vmime::utility::auto_ptr <vmime::messaging::folder> f = st->getDefaultFolder();
+// vmime::utility::auto_ptr <vmime::messaging::folder> f = st->getFolder(vmime::utility::path("a"));
- f->setMessageFlags(m->getNumber(), m->getNumber(), vmime::messaging::message::FLAG_REPLIED, vmime::messaging::message::FLAG_MODE_ADD);
- std::cout << "Flags = " << m->getFlags() << std::endl;
- f->setMessageFlags(m->getNumber(), m->getNumber(), vmime::messaging::message::FLAG_REPLIED, vmime::messaging::message::FLAG_MODE_REMOVE);
- std::cout << "Flags = " << m->getFlags() << std::endl;
+ f->open(vmime::messaging::folder::MODE_READ_WRITE);
+ int count = f->getMessageCount();
- std::cout << "=========================================================" << std::endl;
+ std::cout << std::endl;
+ std::cout << count << " message(s) in your inbox" << std::endl;
+
+ for (bool cont = true ; cont ; )
+ {
+ typedef std::map <int, vmime::utility::smart_ptr <vmime::messaging::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("List folders");
+ choices.push_back("Return to main menu");
+
+ const int choice = printMenu(choices);
+
+ // Request message number
+ vmime::utility::smart_ptr <vmime::messaging::message> msg;
+
+ if (choice != 6 && choice != 7)
+ {
+ 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 > count)
+ {
+ 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::messaging::folder::FETCH_FLAGS);
+
+ if (msg->getFlags() & vmime::messaging::message::FLAG_SEEN)
+ std::cout << "FLAG_SEEN" << std::endl;
+ if (msg->getFlags() & vmime::messaging::message::FLAG_RECENT)
+ std::cout << "FLAG_RECENT" << std::endl;
+ if (msg->getFlags() & vmime::messaging::message::FLAG_REPLIED)
+ std::cout << "FLAG_REPLIED" << std::endl;
+ if (msg->getFlags() & vmime::messaging::message::FLAG_DELETED)
+ std::cout << "FLAG_DELETED" << std::endl;
+ if (msg->getFlags() & vmime::messaging::message::FLAG_MARKED)
+ std::cout << "FLAG_MARKED" << std::endl;
+ if (msg->getFlags() & vmime::messaging::message::FLAG_PASSED)
+ std::cout << "FLAG_PASSED" << std::endl;
+
+ break;
+
+ // Show message structure
+ case 2:
+
+ f->fetchMessage(msg, vmime::messaging::folder::FETCH_STRUCTURE);
+ printStructure(msg->getStructure());
+ break;
+
+ // Show message header
+ case 3:
+
+ f->fetchMessage(msg, vmime::messaging::folder::FETCH_FULL_HEADER);
+ std::cout << msg->getHeader().generate() << std::endl;
+ break;
+
+ // Show message envelope
+ case 4:
+
+ f->fetchMessage(msg, vmime::messaging::folder::FETCH_ENVELOPE);
+
+#define ENV_HELPER(x, y) \
+ try { std::cout << x << msg->getHeader().y().generate() << std::endl; } \
+ catch (vmime::exception) { /* In case the header field does not exist. */ }
+
+ ENV_HELPER("From: ", From)
+ ENV_HELPER("To: ", To)
+ ENV_HELPER("Date: ", Date)
+ ENV_HELPER("Subject: ", Subject)
+
+#undef ENV_HELPER
+
+ break;
+
+ // Extract whole message
+ case 5:
+ {
+ vmime::utility::outputStreamAdapter out(std::cout);
+ msg->extract(out);
+
+ break;
+ }
+ // List folders
+ case 6:
+ {
+ vmime::utility::auto_ptr <vmime::messaging::folder>
+ root = st->getRootFolder();
+
+ printFolders(root);
+ break;
+ }
+ // Main menu
+ case 7:
+
+ cont = false;
+ break;
+ }
- // Append message
/*
+ // Append message
std::istringstream iss(
"From: me@localhost\r\n"
"To: you@localhost\r\n"
@@ -242,10 +477,7 @@ int main()
);
f->addMessage(iss, iss.str().size());
-*/
-
-/*
// Folder renaming
{
vmime::messaging::folder* f = st->getFolder(vmime::messaging::folder::path("c"));
@@ -256,10 +488,8 @@ int main()
g->rename(vmime::messaging::folder::path("c"));
delete (g);
}
-*/
-/*
- // Message copy
+ // Message copy: copy all messages from 'f' to 'g'
{
vmime::messaging::folder* g = st->getFolder(vmime::messaging::folder::path("TEMP"));
@@ -271,36 +501,84 @@ int main()
delete (g);
}
*/
-
- delete (m);
-
- f->close(true);
- delete (f);
-
- st->disconnect();
- delete (st);
-#endif
+ }
+ 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;
+ }
+ }
}
- catch (vmime::exceptions::authentication_error& e)
+ catch (vmime::exception& e)
{
- std::cout << "vmime::authentication_error: " << e.what() << std::endl
- << "Response is: '" << e.response() << "'." << std::endl;
+ std::cerr << std::endl;
+ std::cerr << e << std::endl;
throw;
}
- catch (vmime::exceptions::command_error& e)
+ catch (std::exception& e)
{
- std::cout << "vmime::command_error: " << e.what() << std::endl
- << "Response is: '" << e.response() << "'." << std::endl;
+ std::cerr << std::endl;
+ std::cerr << "std::exception: " << e.what() << std::endl;
throw;
}
- catch (vmime::exception& e)
+}
+
+
+/* Show the main menu.
+ *
+ * @return true to quit the program, false to continue
+ */
+static const 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))
{
- std::cout << "vmime::exception: " << e.what() << std::endl;
- throw;
+ // 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;
}
- catch (std::exception& e)
+}
+
+
+int main()
+{
+ // VMime initialization
+ vmime::platformDependant::setHandler<vmime::platforms::posix::posixHandler>();
+
+ for (bool quit = false ; !quit ; )
{
- std::cout << "std::exception: " << e.what() << std::endl;
- throw;
+ // Loop on main menu
+ quit = menu();
}
+
+ return 0;
}
+