aboutsummaryrefslogtreecommitdiffstats
path: root/tests/net/smtp/SMTPTransportTest.cpp
diff options
context:
space:
mode:
authorVincent Richard <[email protected]>2006-05-05 20:50:26 +0000
committerVincent Richard <[email protected]>2006-05-05 20:50:26 +0000
commit2791e5d41e96982ec3a80c2725ab4f3b9f3bfffc (patch)
tree9a938e05b1207dfe95f331ce3f4ef7d9067d0a71 /tests/net/smtp/SMTPTransportTest.cpp
parentFixed CRLF response parsing + intermediate replies. (diff)
downloadvmime-2791e5d41e96982ec3a80c2725ab4f3b9f3bfffc.tar.gz
vmime-2791e5d41e96982ec3a80c2725ab4f3b9f3bfffc.zip
Unit tests for SMTP.
Diffstat (limited to 'tests/net/smtp/SMTPTransportTest.cpp')
-rw-r--r--tests/net/smtp/SMTPTransportTest.cpp256
1 files changed, 256 insertions, 0 deletions
diff --git a/tests/net/smtp/SMTPTransportTest.cpp b/tests/net/smtp/SMTPTransportTest.cpp
new file mode 100644
index 00000000..a69c2144
--- /dev/null
+++ b/tests/net/smtp/SMTPTransportTest.cpp
@@ -0,0 +1,256 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2006 Vincent Richard <[email protected]>
+//
+// 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 2 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 "tests/testUtils.hpp"
+
+
+#define VMIME_TEST_SUITE SMTPTransportTest
+#define VMIME_TEST_SUITE_MODULE "Net/SMTP"
+
+
+class greetingErrorSMTPTestSocket;
+class MAILandRCPTSMTPTestSocket;
+
+
+VMIME_TEST_SUITE_BEGIN
+
+ VMIME_TEST_LIST_BEGIN
+ VMIME_TEST(testGreetingError)
+ VMIME_TEST(testMAILandRCPT)
+ VMIME_TEST_LIST_END
+
+
+ void testGreetingError()
+ {
+ vmime::ref <vmime::net::session> session =
+ vmime::create <vmime::net::session>();
+
+ vmime::ref <vmime::net::transport> tr = session->getTransport
+ (vmime::utility::url("smtp://localhost"));
+
+ tr->setSocketFactory(vmime::create <testSocketFactory <greetingErrorSMTPTestSocket> >());
+ tr->setTimeoutHandlerFactory(vmime::create <testTimeoutHandlerFactory>());
+
+ VASSERT_THROW("Connection", tr->connect(),
+ vmime::exceptions::connection_greeting_error);
+ }
+
+ void testMAILandRCPT()
+ {
+ vmime::ref <vmime::net::session> session =
+ vmime::create <vmime::net::session>();
+
+ vmime::ref <vmime::net::transport> tr = session->getTransport
+ (vmime::utility::url("smtp://localhost"));
+
+ tr->setSocketFactory(vmime::create <testSocketFactory <MAILandRCPTSMTPTestSocket> >());
+ tr->setTimeoutHandlerFactory(vmime::create <testTimeoutHandlerFactory>());
+
+ VASSERT_NO_THROW("Connection", tr->connect());
+
+ vmime::mailbox exp("[email protected]");
+
+ vmime::mailboxList recips;
+ recips.appendMailbox(vmime::create <vmime::mailbox>("[email protected]"));
+ recips.appendMailbox(vmime::create <vmime::mailbox>("[email protected]"));
+ recips.appendMailbox(vmime::create <vmime::mailbox>("[email protected]"));
+
+ vmime::string data("Message data");
+ vmime::utility::inputStreamStringAdapter is(data);
+
+ tr->send(exp, recips, is, 0);
+ }
+
+VMIME_TEST_SUITE_END
+
+
+/** Accepts connection and fails on greeting.
+ */
+class greetingErrorSMTPTestSocket : public lineBasedTestSocket
+{
+public:
+
+ void onConnected()
+ {
+ localSend("421 test.vmime.org Service not available, closing transmission channel\r\n");
+ disconnect();
+ }
+
+ void processCommand()
+ {
+ if (!haveMoreLines())
+ return;
+
+ getNextLine();
+
+ localSend("502 Command not implemented\r\n");
+ processCommand();
+ }
+};
+
+
+/** SMTP test server 1.
+ *
+ * Test send().
+ * Ensure MAIL and RCPT commands are sent correctly.
+ */
+class MAILandRCPTSMTPTestSocket : public lineBasedTestSocket
+{
+public:
+
+ MAILandRCPTSMTPTestSocket()
+ {
+ m_recipients.insert("[email protected]");
+ m_recipients.insert("[email protected]");
+ m_recipients.insert("[email protected]");
+
+ m_state = STATE_NOT_CONNECTED;
+ }
+
+ void onConnected()
+ {
+ localSend("220 test.vmime.org Service ready\r\n");
+ processCommand();
+
+ m_state = STATE_COMMAND;
+ }
+
+ void processCommand()
+ {
+ if (!haveMoreLines())
+ return;
+
+ vmime::string line = getNextLine();
+ std::istringstream iss(line);
+
+ switch (m_state)
+ {
+ case STATE_NOT_CONNECTED:
+
+ localSend("451 Requested action aborted: invalid state\r\n");
+ break;
+
+ case STATE_COMMAND:
+ {
+ std::string cmd;
+ iss >> cmd;
+
+ if (cmd.empty())
+ {
+ localSend("500 Syntax error, command unrecognized\r\n");
+ }
+ else if (cmd == "HELO")
+ {
+ localSend("250 OK\r\n");
+ }
+ else if (cmd == "MAIL")
+ {
+ VASSERT_EQ("MAIL", std::string("MAIL FROM: <[email protected]>"), line);
+
+ localSend("250 OK\r\n");
+ }
+ else if (cmd == "RCPT")
+ {
+ const vmime::string::size_type lt = line.find('<');
+ const vmime::string::size_type gt = line.find('>');
+
+ VASSERT("RCPT <", lt != vmime::string::npos);
+ VASSERT("RCPT >", gt != vmime::string::npos);
+ VASSERT("RCPT ><", gt >= lt);
+
+ const vmime::string recip = vmime::string
+ (line.begin() + lt + 1, line.begin() + gt);
+
+ std::set <vmime::string>::iterator it =
+ m_recipients.find(recip);
+
+ VASSERT(std::string("Recipient not found: '") + recip + "'",
+ it != m_recipients.end());
+
+ m_recipients.erase(it);
+
+ localSend("250 OK, recipient accepted\r\n");
+ }
+ else if (cmd == "DATA")
+ {
+ VASSERT("All recipients", m_recipients.empty());
+
+ localSend("354 Ready to accept data; end with <CRLF>.<CRLF>\r\n");
+
+ m_state = STATE_DATA;
+ m_msgData.clear();
+ }
+ else if (cmd == "NOOP")
+ {
+ localSend("250 Completed\r\n");
+ }
+ else if (cmd == "QUIT")
+ {
+ localSend("221 test.vmime.org Service closing transmission channel\r\n");
+ }
+ else
+ {
+ localSend("502 Command not implemented\r\n");
+ }
+
+ break;
+ }
+ case STATE_DATA:
+ {
+ if (line == ".")
+ {
+ VASSERT_EQ("Data", "Message data\r\n", m_msgData);
+
+ localSend("250 Message accepted for delivery\r\n");
+ m_state = STATE_COMMAND;
+ }
+ else
+ {
+ m_msgData += line + "\r\n";
+ }
+
+ break;
+ }
+
+ }
+
+ processCommand();
+ }
+
+private:
+
+ enum State
+ {
+ STATE_NOT_CONNECTED,
+ STATE_COMMAND,
+ STATE_DATA
+ };
+
+ int m_state;
+
+ std::set <vmime::string> m_recipients;
+
+ std::string m_msgData;
+};
+
+