diff options
author | Vincent Richard <[email protected]> | 2006-05-05 20:50:26 +0000 |
---|---|---|
committer | Vincent Richard <[email protected]> | 2006-05-05 20:50:26 +0000 |
commit | 2791e5d41e96982ec3a80c2725ab4f3b9f3bfffc (patch) | |
tree | 9a938e05b1207dfe95f331ce3f4ef7d9067d0a71 /tests/net/smtp/SMTPTransportTest.cpp | |
parent | Fixed CRLF response parsing + intermediate replies. (diff) | |
download | vmime-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.cpp | 256 |
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; +}; + + |