diff options
Diffstat (limited to 'tests/net/smtp')
-rw-r--r-- | tests/net/smtp/SMTPCommandSetTest.cpp | 34 | ||||
-rw-r--r-- | tests/net/smtp/SMTPCommandTest.cpp | 119 | ||||
-rw-r--r-- | tests/net/smtp/SMTPResponseTest.cpp | 84 | ||||
-rw-r--r-- | tests/net/smtp/SMTPTransportTest.cpp | 224 | ||||
-rw-r--r-- | tests/net/smtp/SMTPTransportTestUtils.hpp | 569 |
5 files changed, 688 insertions, 342 deletions
diff --git a/tests/net/smtp/SMTPCommandSetTest.cpp b/tests/net/smtp/SMTPCommandSetTest.cpp index f419eb40..7ea3578b 100644 --- a/tests/net/smtp/SMTPCommandSetTest.cpp +++ b/tests/net/smtp/SMTPCommandSetTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 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 @@ -44,24 +44,24 @@ VMIME_TEST_SUITE_BEGIN(SMTPCommandSetTest) VMIME_TEST_LIST_END - void testCreate() - { + void testCreate() { + vmime::shared_ptr <SMTPCommandSet> cset = SMTPCommandSet::create(/* pipelining */ false); VASSERT_NOT_NULL("Not null", cset); VASSERT_FALSE("Finished", cset->isFinished()); } - void testCreatePipeline() - { + void testCreatePipeline() { + vmime::shared_ptr <SMTPCommandSet> cset = SMTPCommandSet::create(/* pipelining */ true); VASSERT_NOT_NULL("Not null", cset); VASSERT_FALSE("Finished", cset->isFinished()); } - void testAddCommand() - { + void testAddCommand() { + vmime::shared_ptr <SMTPCommandSet> cset = SMTPCommandSet::create(/* pipelining */ false); VASSERT_NO_THROW("No throw 1", cset->addCommand(SMTPCommand::createCommand("MY_COMMAND1"))); @@ -82,8 +82,8 @@ VMIME_TEST_SUITE_BEGIN(SMTPCommandSetTest) VASSERT_TRUE("Finished", cset->isFinished()); } - void testAddCommandPipeline() - { + void testAddCommandPipeline() { + vmime::shared_ptr <SMTPCommandSet> cset = SMTPCommandSet::create(/* pipelining */ true); VASSERT_NO_THROW("No throw 1", cset->addCommand(SMTPCommand::createCommand("MY_COMMAND1"))); @@ -105,8 +105,8 @@ VMIME_TEST_SUITE_BEGIN(SMTPCommandSetTest) VASSERT_THROW("Throw", cset->addCommand(SMTPCommand::createCommand("MY_COMMAND3")), std::runtime_error); } - void testWriteToSocket() - { + void testWriteToSocket() { + vmime::shared_ptr <SMTPCommandSet> cset = SMTPCommandSet::create(/* pipelining */ false); cset->addCommand(SMTPCommand::createCommand("MY_COMMAND1")); @@ -127,8 +127,8 @@ VMIME_TEST_SUITE_BEGIN(SMTPCommandSetTest) VASSERT_EQ("Receive cmd 2", "MY_COMMAND2\r\n", response); } - void testWriteToSocketPipeline() - { + void testWriteToSocketPipeline() { + vmime::shared_ptr <SMTPCommandSet> cset = SMTPCommandSet::create(/* pipelining */ true); cset->addCommand(SMTPCommand::createCommand("MY_COMMAND1")); @@ -144,8 +144,8 @@ VMIME_TEST_SUITE_BEGIN(SMTPCommandSetTest) VASSERT_EQ("Receive cmds", "MY_COMMAND1\r\nMY_COMMAND2\r\n", response); } - void testGetLastCommandSent() - { + void testGetLastCommandSent() { + vmime::shared_ptr <SMTPCommandSet> cset = SMTPCommandSet::create(/* pipelining */ false); cset->addCommand(SMTPCommand::createCommand("MY_COMMAND1")); @@ -161,8 +161,8 @@ VMIME_TEST_SUITE_BEGIN(SMTPCommandSetTest) VASSERT_EQ("Cmd 2", "MY_COMMAND2", cset->getLastCommandSent()->getText()); } - void testGetLastCommandSentPipeline() - { + void testGetLastCommandSentPipeline() { + vmime::shared_ptr <SMTPCommandSet> cset = SMTPCommandSet::create(/* pipelining */ true); cset->addCommand(SMTPCommand::createCommand("MY_COMMAND1")); diff --git a/tests/net/smtp/SMTPCommandTest.cpp b/tests/net/smtp/SMTPCommandTest.cpp index 9b3daa73..a0f03bb6 100644 --- a/tests/net/smtp/SMTPCommandTest.cpp +++ b/tests/net/smtp/SMTPCommandTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 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 @@ -56,150 +56,157 @@ VMIME_TEST_SUITE_BEGIN(SMTPCommandTest) VMIME_TEST_LIST_END - void testCreateCommand() - { + void testCreateCommand() { + vmime::shared_ptr <SMTPCommand> cmd = SMTPCommand::createCommand("MY_COMMAND"); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "MY_COMMAND", cmd->getText()); } - void testCreateCommandParams() - { + void testCreateCommandParams() { + vmime::shared_ptr <SMTPCommand> cmd = SMTPCommand::createCommand("MY_COMMAND param1 param2"); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "MY_COMMAND param1 param2", cmd->getText()); } - void testHELO() - { + void testHELO() { + vmime::shared_ptr <SMTPCommand> cmd = SMTPCommand::HELO("hostname"); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "HELO hostname", cmd->getText()); } - void testEHLO() - { + void testEHLO() { + vmime::shared_ptr <SMTPCommand> cmd = SMTPCommand::EHLO("hostname"); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "EHLO hostname", cmd->getText()); } - void testAUTH() - { + void testAUTH() { + vmime::shared_ptr <SMTPCommand> cmd = SMTPCommand::AUTH("saslmechanism"); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "AUTH saslmechanism", cmd->getText()); } - void testAUTH_InitialResponse() - { + void testAUTH_InitialResponse() { + vmime::shared_ptr <SMTPCommand> cmd = SMTPCommand::AUTH("saslmechanism", "initial-response"); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "AUTH saslmechanism initial-response", cmd->getText()); } - void testSTARTTLS() - { + void testSTARTTLS() { + vmime::shared_ptr <SMTPCommand> cmd = SMTPCommand::STARTTLS(); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "STARTTLS", cmd->getText()); } - void testMAIL() - { + void testMAIL() { + vmime::shared_ptr <SMTPCommand> cmd = SMTPCommand::MAIL(vmime::mailbox("[email protected]"), false); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "MAIL FROM:<[email protected]>", cmd->getText()); } - void testMAIL_Encoded() - { - vmime::shared_ptr <SMTPCommand> cmd = SMTPCommand::MAIL - (vmime::mailbox(vmime::emailAddress("mailtest", "例え.テスト")), false); + void testMAIL_Encoded() { + + vmime::shared_ptr <SMTPCommand> cmd = SMTPCommand::MAIL( + vmime::mailbox(vmime::emailAddress("mailtest", "例え.テスト")), false + ); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "MAIL FROM:<[email protected]>", cmd->getText()); } - void testMAIL_UTF8() - { - vmime::shared_ptr <SMTPCommand> cmd = SMTPCommand::MAIL - (vmime::mailbox(vmime::emailAddress("mailtest", "例え.テスト")), true); + void testMAIL_UTF8() { + + vmime::shared_ptr <SMTPCommand> cmd = SMTPCommand::MAIL( + vmime::mailbox(vmime::emailAddress("mailtest", "例え.テスト")), true + ); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "MAIL FROM:<mailtest@例え.テスト> SMTPUTF8", cmd->getText()); } - void testMAIL_SIZE() - { - vmime::shared_ptr <SMTPCommand> cmd = SMTPCommand::MAIL - (vmime::mailbox("[email protected]"), false, 123456789); + void testMAIL_SIZE() { + + vmime::shared_ptr <SMTPCommand> cmd = SMTPCommand::MAIL( + vmime::mailbox("[email protected]"), false, 123456789 + ); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "MAIL FROM:<[email protected]> SIZE=123456789", cmd->getText()); } - void testMAIL_SIZE_UTF8() - { - vmime::shared_ptr <SMTPCommand> cmd = SMTPCommand::MAIL - (vmime::mailbox(vmime::emailAddress("mailtest", "例え.テスト")), true, 123456789); + void testMAIL_SIZE_UTF8() { + + vmime::shared_ptr <SMTPCommand> cmd = SMTPCommand::MAIL( + vmime::mailbox(vmime::emailAddress("mailtest", "例え.テスト")), true, 123456789 + ); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "MAIL FROM:<mailtest@例え.テスト> SMTPUTF8 SIZE=123456789", cmd->getText()); } - void testRCPT() - { - vmime::shared_ptr <SMTPCommand> cmd = SMTPCommand::RCPT(vmime::mailbox("[email protected]"), false); + void testRCPT() { + + vmime::shared_ptr <SMTPCommand> cmd = + SMTPCommand::RCPT(vmime::mailbox("[email protected]"), false); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "RCPT TO:<[email protected]>", cmd->getText()); } - void testRCPT_Encoded() - { - vmime::shared_ptr <SMTPCommand> cmd = SMTPCommand::RCPT - (vmime::mailbox(vmime::emailAddress("mailtest", "例え.テスト")), false); + void testRCPT_Encoded() { + + vmime::shared_ptr <SMTPCommand> cmd = SMTPCommand::RCPT( + vmime::mailbox(vmime::emailAddress("mailtest", "例え.テスト")), false + ); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "RCPT TO:<[email protected]>", cmd->getText()); } - void testRCPT_UTF8() - { - vmime::shared_ptr <SMTPCommand> cmd = SMTPCommand::RCPT - (vmime::mailbox(vmime::emailAddress("mailtest", "例え.テスト")), true); + void testRCPT_UTF8() { + + vmime::shared_ptr <SMTPCommand> cmd = SMTPCommand::RCPT( + vmime::mailbox(vmime::emailAddress("mailtest", "例え.テスト")), true + ); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "RCPT TO:<mailtest@例え.テスト>", cmd->getText()); } - void testRSET() - { + void testRSET() { + vmime::shared_ptr <SMTPCommand> cmd = SMTPCommand::RSET(); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "RSET", cmd->getText()); } - void testDATA() - { + void testDATA() { + vmime::shared_ptr <SMTPCommand> cmd = SMTPCommand::DATA(); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "DATA", cmd->getText()); } - void testBDAT() - { + void testBDAT() { + vmime::shared_ptr <SMTPCommand> cmd1 = SMTPCommand::BDAT(12345, false); VASSERT_NOT_NULL("Not null", cmd1); @@ -211,24 +218,24 @@ VMIME_TEST_SUITE_BEGIN(SMTPCommandTest) VASSERT_EQ("Text", "BDAT 67890 LAST", cmd2->getText()); } - void testNOOP() - { + void testNOOP() { + vmime::shared_ptr <SMTPCommand> cmd = SMTPCommand::NOOP(); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "NOOP", cmd->getText()); } - void testQUIT() - { + void testQUIT() { + vmime::shared_ptr <SMTPCommand> cmd = SMTPCommand::QUIT(); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "QUIT", cmd->getText()); } - void testWriteToSocket() - { + void testWriteToSocket() { + vmime::shared_ptr <SMTPCommand> cmd = SMTPCommand::createCommand("MY_COMMAND param1 param2"); vmime::shared_ptr <vmime::net::tracer> tracer; diff --git a/tests/net/smtp/SMTPResponseTest.cpp b/tests/net/smtp/SMTPResponseTest.cpp index d47e31e9..f899a828 100644 --- a/tests/net/smtp/SMTPResponseTest.cpp +++ b/tests/net/smtp/SMTPResponseTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 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 @@ -41,12 +41,11 @@ VMIME_TEST_SUITE_BEGIN(SMTPResponseTest) VMIME_TEST_LIST_END - void testSingleLineResponse() - { + void testSingleLineResponse() { + vmime::shared_ptr <vmime::net::tracer> tracer; vmime::shared_ptr <testSocket> socket = vmime::make_shared <testSocket>(); - vmime::shared_ptr <vmime::net::timeoutHandler> toh = - vmime::make_shared <testTimeoutHandler>(); + vmime::shared_ptr <vmime::net::timeoutHandler> toh = vmime::make_shared <testTimeoutHandler>(); socket->localSend("123 Response Text\r\n"); @@ -60,12 +59,11 @@ VMIME_TEST_SUITE_BEGIN(SMTPResponseTest) VASSERT_EQ("Text", "Response Text", resp->getText()); } - void testSingleLineResponseLF() - { + void testSingleLineResponseLF() { + vmime::shared_ptr <vmime::net::tracer> tracer; vmime::shared_ptr <testSocket> socket = vmime::make_shared <testSocket>(); - vmime::shared_ptr <vmime::net::timeoutHandler> toh = - vmime::make_shared <testTimeoutHandler>(); + vmime::shared_ptr <vmime::net::timeoutHandler> toh = vmime::make_shared <testTimeoutHandler>(); socket->localSend("123 Response Text\n"); @@ -79,15 +77,13 @@ VMIME_TEST_SUITE_BEGIN(SMTPResponseTest) VASSERT_EQ("Text", "Response Text", resp->getText()); } - void testMultiLineResponse() - { + void testMultiLineResponse() { + vmime::shared_ptr <vmime::net::tracer> tracer; vmime::shared_ptr <testSocket> socket = vmime::make_shared <testSocket>(); - vmime::shared_ptr <vmime::net::timeoutHandler> toh = - vmime::make_shared <testTimeoutHandler>(); + vmime::shared_ptr <vmime::net::timeoutHandler> toh = vmime::make_shared <testTimeoutHandler>(); - socket->localSend - ( + socket->localSend( "123-Response\r\n" "123 Text\r\n" ); @@ -108,15 +104,13 @@ VMIME_TEST_SUITE_BEGIN(SMTPResponseTest) VASSERT_EQ("Text", "Text", resp->getLineAt(1).getText()); } - void testMultiLineResponseDifferentCode() - { + void testMultiLineResponseDifferentCode() { + vmime::shared_ptr <vmime::net::tracer> tracer; vmime::shared_ptr <testSocket> socket = vmime::make_shared <testSocket>(); - vmime::shared_ptr <vmime::net::timeoutHandler> toh = - vmime::make_shared <testTimeoutHandler>(); + vmime::shared_ptr <vmime::net::timeoutHandler> toh = vmime::make_shared <testTimeoutHandler>(); - socket->localSend - ( + socket->localSend( "123-Response\r\n" "456 Text\r\n" ); @@ -137,15 +131,13 @@ VMIME_TEST_SUITE_BEGIN(SMTPResponseTest) VASSERT_EQ("Text", "Text", resp->getLineAt(1).getText()); } - void testIncompleteMultiLineResponse() - { + void testIncompleteMultiLineResponse() { + vmime::shared_ptr <vmime::net::tracer> tracer; vmime::shared_ptr <testSocket> socket = vmime::make_shared <testSocket>(); - vmime::shared_ptr <vmime::net::timeoutHandler> toh = - vmime::make_shared <testTimeoutHandler>(1); + vmime::shared_ptr <vmime::net::timeoutHandler> toh = vmime::make_shared <testTimeoutHandler>(1); - socket->localSend - ( + socket->localSend( "123-Response\r\n" "123-Text\r\n" // Missing data @@ -153,20 +145,20 @@ VMIME_TEST_SUITE_BEGIN(SMTPResponseTest) vmime::net::smtp::SMTPResponse::state responseState; - VASSERT_THROW("Incomplete response", + VASSERT_THROW( + "Incomplete response", vmime::net::smtp::SMTPResponse::readResponse(tracer, socket, toh, responseState), - vmime::exceptions::operation_timed_out); + vmime::exceptions::operation_timed_out + ); } - void testNoResponseText() - { + void testNoResponseText() { + vmime::shared_ptr <vmime::net::tracer> tracer; vmime::shared_ptr <testSocket> socket = vmime::make_shared <testSocket>(); - vmime::shared_ptr <vmime::net::timeoutHandler> toh = - vmime::make_shared <testTimeoutHandler>(1); + vmime::shared_ptr <vmime::net::timeoutHandler> toh = vmime::make_shared <testTimeoutHandler>(1); - socket->localSend - ( + socket->localSend( "250\r\n" ); @@ -180,12 +172,11 @@ VMIME_TEST_SUITE_BEGIN(SMTPResponseTest) VASSERT_EQ("Text", "", resp->getText()); } - void testEnhancedStatusCode() - { + void testEnhancedStatusCode() { + vmime::shared_ptr <vmime::net::tracer> tracer; vmime::shared_ptr <testSocket> socket = vmime::make_shared <testSocket>(); - vmime::shared_ptr <vmime::net::timeoutHandler> toh = - vmime::make_shared <testTimeoutHandler>(); + vmime::shared_ptr <vmime::net::timeoutHandler> toh = vmime::make_shared <testTimeoutHandler>(); socket->localSend("250 2.1.5 OK fu13sm4720601wic.7 - gsmtp\r\n"); @@ -202,12 +193,11 @@ VMIME_TEST_SUITE_BEGIN(SMTPResponseTest) VASSERT_EQ("Enh.detail", 5, resp->getEnhancedCode().detail); } - void testNoEnhancedStatusCode() - { + void testNoEnhancedStatusCode() { + vmime::shared_ptr <vmime::net::tracer> tracer; vmime::shared_ptr <testSocket> socket = vmime::make_shared <testSocket>(); - vmime::shared_ptr <vmime::net::timeoutHandler> toh = - vmime::make_shared <testTimeoutHandler>(); + vmime::shared_ptr <vmime::net::timeoutHandler> toh = vmime::make_shared <testTimeoutHandler>(); socket->localSend("354 Go ahead fu13sm4720601wic.7 - gsmtp\r\n"); @@ -224,12 +214,11 @@ VMIME_TEST_SUITE_BEGIN(SMTPResponseTest) VASSERT_EQ("Enh.detail", 0, resp->getEnhancedCode().detail); } - void testInvalidEnhancedStatusCode() - { + void testInvalidEnhancedStatusCode() { + vmime::shared_ptr <vmime::net::tracer> tracer; vmime::shared_ptr <testSocket> socket = vmime::make_shared <testSocket>(); - vmime::shared_ptr <vmime::net::timeoutHandler> toh = - vmime::make_shared <testTimeoutHandler>(); + vmime::shared_ptr <vmime::net::timeoutHandler> toh = vmime::make_shared <testTimeoutHandler>(); socket->localSend("250 4.2 xxx\r\n"); @@ -247,4 +236,3 @@ VMIME_TEST_SUITE_BEGIN(SMTPResponseTest) } VMIME_TEST_SUITE_END - diff --git a/tests/net/smtp/SMTPTransportTest.cpp b/tests/net/smtp/SMTPTransportTest.cpp index dd5546cc..8ea4ba75 100644 --- a/tests/net/smtp/SMTPTransportTest.cpp +++ b/tests/net/smtp/SMTPTransportTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 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 @@ -39,11 +39,13 @@ VMIME_TEST_SUITE_BEGIN(SMTPTransportTest) VMIME_TEST(testChunking) VMIME_TEST(testSize_Chunking) VMIME_TEST(testSize_NoChunking) + VMIME_TEST(testSMTPUTF8_available) + VMIME_TEST(testSMTPUTF8_notAvailable) VMIME_TEST_LIST_END - void testConnectToInvalidServer() - { + void testConnectToInvalidServer() { + vmime::shared_ptr <vmime::net::session> sess = vmime::net::session::create(); vmime::utility::url url("smtp://invalid-smtp-server"); @@ -52,26 +54,29 @@ VMIME_TEST_SUITE_BEGIN(SMTPTransportTest) VASSERT_THROW("connect", store->connect(), vmime::exceptions::connection_error); } - void testGreetingError() - { + void testGreetingError() { + vmime::shared_ptr <vmime::net::session> session = vmime::net::session::create(); - vmime::shared_ptr <vmime::net::transport> tr = session->getTransport - (vmime::utility::url("smtp://localhost")); + vmime::shared_ptr <vmime::net::transport> tr = + session->getTransport(vmime::utility::url("smtp://localhost")); tr->setSocketFactory(vmime::make_shared <testSocketFactory <greetingErrorSMTPTestSocket> >()); tr->setTimeoutHandlerFactory(vmime::make_shared <testTimeoutHandlerFactory>()); - VASSERT_THROW("Connection", tr->connect(), - vmime::exceptions::connection_greeting_error); + VASSERT_THROW( + "Connection", + tr->connect(), + vmime::exceptions::connection_greeting_error + ); } - void testMAILandRCPT() - { + void testMAILandRCPT() { + vmime::shared_ptr <vmime::net::session> session = vmime::net::session::create(); - vmime::shared_ptr <vmime::net::transport> tr = session->getTransport - (vmime::utility::url("smtp://localhost")); + vmime::shared_ptr <vmime::net::transport> tr = + session->getTransport(vmime::utility::url("smtp://localhost")); tr->setSocketFactory(vmime::make_shared <testSocketFactory <MAILandRCPTSMTPTestSocket> >()); tr->setTimeoutHandlerFactory(vmime::make_shared <testTimeoutHandlerFactory>()); @@ -91,20 +96,22 @@ VMIME_TEST_SUITE_BEGIN(SMTPTransportTest) tr->send(exp, recips, is, 0); } - void testChunking() - { + void testChunking() { + vmime::shared_ptr <vmime::net::session> session = vmime::net::session::create(); - vmime::shared_ptr <vmime::net::transport> tr = session->getTransport - (vmime::utility::url("smtp://localhost")); + vmime::shared_ptr <vmime::net::transport> tr = + session->getTransport(vmime::utility::url("smtp://localhost")); tr->setSocketFactory(vmime::make_shared <testSocketFactory <chunkingSMTPTestSocket> >()); tr->setTimeoutHandlerFactory(vmime::make_shared <testTimeoutHandlerFactory>()); tr->connect(); - VASSERT("Test server should report it supports the CHUNKING extension!", - vmime::dynamicCast <vmime::net::smtp::SMTPTransport>(tr)->getConnection()->hasExtension("CHUNKING")); + VASSERT( + "Test server should report it supports the CHUNKING extension!", + vmime::dynamicCast <vmime::net::smtp::SMTPTransport>(tr)->getConnection()->hasExtension("CHUNKING") + ); vmime::mailbox exp("[email protected]"); @@ -116,20 +123,22 @@ VMIME_TEST_SUITE_BEGIN(SMTPTransportTest) tr->send(msg, exp, recips); } - void testSize_Chunking() - { + void testSize_Chunking() { + vmime::shared_ptr <vmime::net::session> session = vmime::net::session::create(); - vmime::shared_ptr <vmime::net::transport> tr = session->getTransport - (vmime::utility::url("smtp://localhost")); + vmime::shared_ptr <vmime::net::transport> tr = + session->getTransport(vmime::utility::url("smtp://localhost")); tr->setSocketFactory(vmime::make_shared <testSocketFactory <bigMessageSMTPTestSocket <true> > >()); tr->setTimeoutHandlerFactory(vmime::make_shared <testTimeoutHandlerFactory>()); tr->connect(); - VASSERT("Test server should report it supports the SIZE extension!", - vmime::dynamicCast <vmime::net::smtp::SMTPTransport>(tr)->getConnection()->hasExtension("SIZE")); + VASSERT( + "Test server should report it supports the SIZE extension!", + vmime::dynamicCast <vmime::net::smtp::SMTPTransport>(tr)->getConnection()->hasExtension("SIZE") + ); vmime::mailbox exp("[email protected]"); @@ -138,24 +147,29 @@ VMIME_TEST_SUITE_BEGIN(SMTPTransportTest) vmime::shared_ptr <vmime::message> msg = vmime::make_shared <SMTPBigTestMessage4MB>(); - VASSERT_THROW("Connection", tr->send(msg, exp, recips), - vmime::net::smtp::SMTPMessageSizeExceedsMaxLimitsException); + VASSERT_THROW( + "Max size limit exception", + tr->send(msg, exp, recips), + vmime::net::smtp::SMTPMessageSizeExceedsMaxLimitsException + ); } - void testSize_NoChunking() - { + void testSize_NoChunking() { + vmime::shared_ptr <vmime::net::session> session = vmime::net::session::create(); - vmime::shared_ptr <vmime::net::transport> tr = session->getTransport - (vmime::utility::url("smtp://localhost")); + vmime::shared_ptr <vmime::net::transport> tr = + session->getTransport(vmime::utility::url("smtp://localhost")); tr->setSocketFactory(vmime::make_shared <testSocketFactory <bigMessageSMTPTestSocket <false> > >()); tr->setTimeoutHandlerFactory(vmime::make_shared <testTimeoutHandlerFactory>()); tr->connect(); - VASSERT("Test server should report it supports the SIZE extension!", - vmime::dynamicCast <vmime::net::smtp::SMTPTransport>(tr)->getConnection()->hasExtension("SIZE")); + VASSERT( + "Test server should report it supports the SIZE extension!", + vmime::dynamicCast <vmime::net::smtp::SMTPTransport>(tr)->getConnection()->hasExtension("SIZE") + ); vmime::mailbox exp("[email protected]"); @@ -164,9 +178,147 @@ VMIME_TEST_SUITE_BEGIN(SMTPTransportTest) vmime::shared_ptr <vmime::message> msg = vmime::make_shared <SMTPBigTestMessage4MB>(); - VASSERT_THROW("Connection", tr->send(msg, exp, recips), - vmime::net::smtp::SMTPMessageSizeExceedsMaxLimitsException); + VASSERT_THROW( + "Max size limit exception", + tr->send(msg, exp, recips), + vmime::net::smtp::SMTPMessageSizeExceedsMaxLimitsException + ); } -VMIME_TEST_SUITE_END + void testSMTPUTF8_available() { + + // Test with UTF8 sender + { + vmime::shared_ptr <vmime::net::session> session = vmime::net::session::create(); + + vmime::shared_ptr <vmime::net::transport> tr = + session->getTransport(vmime::utility::url("smtp://localhost")); + + tr->setSocketFactory(vmime::make_shared <testSocketFactory <UTF8SMTPTestSocket <true> > >()); + tr->setTimeoutHandlerFactory(vmime::make_shared <testTimeoutHandlerFactory>()); + + VASSERT_NO_THROW("Connection", tr->connect()); + + vmime::mailbox exp( + vmime::emailAddress( + vmime::word("expéditeur", vmime::charsets::UTF_8), + vmime::word("test.vmime.org") + ) + ); + + vmime::mailboxList recips; + recips.appendMailbox(vmime::make_shared <vmime::mailbox>("[email protected]")); + recips.appendMailbox(vmime::make_shared <vmime::mailbox>("[email protected]")); + recips.appendMailbox(vmime::make_shared <vmime::mailbox>( + vmime::emailAddress( + vmime::word("récepteur", vmime::charsets::UTF_8), + vmime::word("test.vmime.org") + ) + )); + + vmime::string data("Message data"); + vmime::utility::inputStreamStringAdapter is(data); + + tr->send(exp, recips, is, 0); + } + + // Test with UTF8 recipient only + { + vmime::shared_ptr <vmime::net::session> session = vmime::net::session::create(); + + vmime::shared_ptr <vmime::net::transport> tr = + session->getTransport(vmime::utility::url("smtp://localhost")); + + tr->setSocketFactory(vmime::make_shared <testSocketFactory <UTF8SMTPTestSocket <true> > >()); + tr->setTimeoutHandlerFactory(vmime::make_shared <testTimeoutHandlerFactory>()); + + VASSERT_NO_THROW("Connection", tr->connect()); + + vmime::mailbox exp("[email protected]"); + + vmime::mailboxList recips; + recips.appendMailbox(vmime::make_shared <vmime::mailbox>("[email protected]")); + recips.appendMailbox(vmime::make_shared <vmime::mailbox>("[email protected]")); + recips.appendMailbox(vmime::make_shared <vmime::mailbox>( + vmime::emailAddress( + vmime::word("récepteur", vmime::charsets::UTF_8), + vmime::word("test.vmime.org") + ) + )); + + vmime::string data("Message data"); + vmime::utility::inputStreamStringAdapter is(data); + tr->send(exp, recips, is, 0); + } + } + + void testSMTPUTF8_notAvailable() { + + // Test with UTF8 sender + { + vmime::shared_ptr <vmime::net::session> session = vmime::net::session::create(); + + vmime::shared_ptr <vmime::net::transport> tr = + session->getTransport(vmime::utility::url("smtp://localhost")); + + tr->setSocketFactory(vmime::make_shared <testSocketFactory <UTF8SMTPTestSocket <false> > >()); + tr->setTimeoutHandlerFactory(vmime::make_shared <testTimeoutHandlerFactory>()); + + VASSERT_NO_THROW("Connection", tr->connect()); + + vmime::mailbox exp( + vmime::emailAddress( + vmime::word("expéditeur", vmime::charsets::UTF_8), + vmime::word("test.vmime.org") + ) + ); + + vmime::mailboxList recips; + recips.appendMailbox(vmime::make_shared <vmime::mailbox>("[email protected]")); + recips.appendMailbox(vmime::make_shared <vmime::mailbox>("[email protected]")); + recips.appendMailbox(vmime::make_shared <vmime::mailbox>( + vmime::emailAddress( + vmime::word("récepteur", vmime::charsets::UTF_8), + vmime::word("test.vmime.org") + ) + )); + + vmime::string data("Message data"); + vmime::utility::inputStreamStringAdapter is(data); + + tr->send(exp, recips, is, 0); + } + + // Test with UTF8 recipient only + { + vmime::shared_ptr <vmime::net::session> session = vmime::net::session::create(); + + vmime::shared_ptr <vmime::net::transport> tr = + session->getTransport(vmime::utility::url("smtp://localhost")); + + tr->setSocketFactory(vmime::make_shared <testSocketFactory <UTF8SMTPTestSocket <false> > >()); + tr->setTimeoutHandlerFactory(vmime::make_shared <testTimeoutHandlerFactory>()); + + VASSERT_NO_THROW("Connection", tr->connect()); + + vmime::mailbox exp("[email protected]"); + + vmime::mailboxList recips; + recips.appendMailbox(vmime::make_shared <vmime::mailbox>("[email protected]")); + recips.appendMailbox(vmime::make_shared <vmime::mailbox>("[email protected]")); + recips.appendMailbox(vmime::make_shared <vmime::mailbox>( + vmime::emailAddress( + vmime::word("récepteur", vmime::charsets::UTF_8), + vmime::word("test.vmime.org") + ) + )); + + vmime::string data("Message data"); + vmime::utility::inputStreamStringAdapter is(data); + + tr->send(exp, recips, is, 0); + } + } + +VMIME_TEST_SUITE_END diff --git a/tests/net/smtp/SMTPTransportTestUtils.hpp b/tests/net/smtp/SMTPTransportTestUtils.hpp index c1224216..8710639f 100644 --- a/tests/net/smtp/SMTPTransportTestUtils.hpp +++ b/tests/net/smtp/SMTPTransportTestUtils.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 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 @@ -24,20 +24,21 @@ /** Accepts connection and fails on greeting. */ -class greetingErrorSMTPTestSocket : public lineBasedTestSocket -{ +class greetingErrorSMTPTestSocket : public lineBasedTestSocket { + public: - void onConnected() - { + void onConnected() { + localSend("421 test.vmime.org Service not available, closing transmission channel\r\n"); disconnect(); } - void processCommand() - { - if (!haveMoreLines()) + void processCommand() { + + if (!haveMoreLines()) { return; + } getNextLine(); @@ -52,12 +53,12 @@ public: * Test send(). * Ensure MAIL and RCPT commands are sent correctly. */ -class MAILandRCPTSMTPTestSocket : public lineBasedTestSocket -{ +class MAILandRCPTSMTPTestSocket : public lineBasedTestSocket { + public: - MAILandRCPTSMTPTestSocket() - { + MAILandRCPTSMTPTestSocket() { + m_recipients.insert("[email protected]"); m_recipients.insert("[email protected]"); m_recipients.insert("[email protected]"); @@ -66,60 +67,61 @@ public: m_ehloSent = m_heloSent = m_mailSent = m_rcptSent = m_dataSent = m_quitSent = false; } - ~MAILandRCPTSMTPTestSocket() - { + ~MAILandRCPTSMTPTestSocket() { + VASSERT("Client must send the DATA command", m_dataSent); VASSERT("Client must send the QUIT command", m_quitSent); } - void onConnected() - { + void onConnected() { + localSend("220 test.vmime.org Service ready\r\n"); processCommand(); m_state = STATE_COMMAND; } - void processCommand() - { - if (!haveMoreLines()) + void processCommand() { + + if (!haveMoreLines()) { return; + } vmime::string line = getNextLine(); std::istringstream iss(line); - switch (m_state) - { + switch (m_state) { + case STATE_NOT_CONNECTED: localSend("451 Requested action aborted: invalid state\r\n"); break; - case STATE_COMMAND: - { + case STATE_COMMAND: { + std::string cmd; iss >> cmd; - if (cmd.empty()) - { + if (cmd.empty()) { + localSend("500 Syntax error, command unrecognized\r\n"); - } - else if (cmd == "EHLO") - { + + } else if (cmd == "EHLO") { + localSend("502 Command not implemented\r\n"); m_ehloSent = true; - } - else if (cmd == "HELO") - { + + } else if (cmd == "HELO") { + VASSERT("Client must send the EHLO command before HELO", m_ehloSent); localSend("250 OK\r\n"); m_heloSent = true; - } - else if (cmd == "MAIL") - { + + } else if (cmd == "MAIL") { + VASSERT("Client must send the HELO command", m_heloSent); VASSERT("The MAIL command must be sent only one time", !m_mailSent); @@ -128,9 +130,9 @@ public: localSend("250 OK\r\n"); m_mailSent = true; - } - else if (cmd == "RCPT") - { + + } else if (cmd == "RCPT") { + const vmime::size_t lt = line.find('<'); const vmime::size_t gt = line.find('>'); @@ -138,23 +140,25 @@ public: VASSERT("RCPT >", gt != vmime::string::npos); VASSERT("RCPT ><", gt >= lt); - const vmime::string recip = vmime::string - (line.begin() + lt + 1, line.begin() + gt); + 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()); + VASSERT( + std::string("Recipient not found: '") + recip + "'", + it != m_recipients.end() + ); m_recipients.erase(it); localSend("250 OK, recipient accepted\r\n"); m_rcptSent = true; - } - else if (cmd == "DATA") - { + + } else if (cmd == "DATA") { + VASSERT("Client must send the MAIL command", m_mailSent); VASSERT("Client must send the RCPT command", m_rcptSent); VASSERT("All recipients", m_recipients.empty()); @@ -165,35 +169,35 @@ public: m_msgData.clear(); m_dataSent = true; - } - else if (cmd == "NOOP") - { + + } else if (cmd == "NOOP") { + localSend("250 Completed\r\n"); - } - else if (cmd == "QUIT") - { + + } else if (cmd == "QUIT") { + m_quitSent = true; localSend("221 test.vmime.org Service closing transmission channel\r\n"); - } - else - { + + } else { + localSend("502 Command not implemented\r\n"); } break; } - case STATE_DATA: - { - if (line == ".") - { + 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 - { + + } else { + m_msgData += line + "\r\n"; } @@ -207,8 +211,7 @@ public: private: - enum State - { + enum State { STATE_NOT_CONNECTED, STATE_COMMAND, STATE_DATA @@ -230,45 +233,45 @@ private: * * Test CHUNKING extension/BDAT command. */ -class chunkingSMTPTestSocket : public testSocket -{ +class chunkingSMTPTestSocket : public testSocket { + public: - chunkingSMTPTestSocket() - { + chunkingSMTPTestSocket() { + m_state = STATE_NOT_CONNECTED; m_bdatChunkCount = 0; m_ehloSent = m_mailSent = m_rcptSent = m_quitSent = false; } - ~chunkingSMTPTestSocket() - { + ~chunkingSMTPTestSocket() { + VASSERT_EQ("BDAT chunk count", 3, m_bdatChunkCount); VASSERT("Client must send the QUIT command", m_quitSent); } - void onConnected() - { + void onConnected() { + localSend("220 test.vmime.org Service ready\r\n"); processCommand(); m_state = STATE_COMMAND; } - void onDataReceived() - { - if (m_state == STATE_DATA) - { - if (m_bdatChunkReceived != m_bdatChunkSize) - { + void onDataReceived() { + + if (m_state == STATE_DATA) { + + if (m_bdatChunkReceived != m_bdatChunkSize) { + const size_t remaining = m_bdatChunkSize - m_bdatChunkReceived; const size_t received = localReceiveRaw(NULL, remaining); m_bdatChunkReceived += received; } - if (m_bdatChunkReceived == m_bdatChunkSize) - { + if (m_bdatChunkReceived == m_bdatChunkSize) { + m_state = STATE_COMMAND; } } @@ -276,58 +279,59 @@ public: processCommand(); } - void processCommand() - { + void processCommand() { + vmime::string line; - if (!localReceiveLine(line)) + if (!localReceiveLine(line)) { return; + } std::istringstream iss(line); - switch (m_state) - { + switch (m_state) { + case STATE_NOT_CONNECTED: localSend("451 Requested action aborted: invalid state\r\n"); break; - case STATE_COMMAND: - { + case STATE_COMMAND: { + std::string cmd; iss >> cmd; - if (cmd == "EHLO") - { + if (cmd == "EHLO") { + localSend("250-test.vmime.org says hello\r\n"); localSend("250 CHUNKING\r\n"); m_ehloSent = true; - } - else if (cmd == "HELO") - { + + } else if (cmd == "HELO") { + VASSERT("Client must not send the HELO command, as EHLO succeeded", false); - } - else if (cmd == "MAIL") - { + + } else if (cmd == "MAIL") { + VASSERT("The MAIL command must be sent only one time", !m_mailSent); localSend("250 OK\r\n"); m_mailSent = true; - } - else if (cmd == "RCPT") - { + + } else if (cmd == "RCPT") { + localSend("250 OK, recipient accepted\r\n"); m_rcptSent = true; - } - else if (cmd == "DATA") - { + + } else if (cmd == "DATA") { + VASSERT("BDAT must be used here!", false); - } - else if (cmd == "BDAT") - { + + } else if (cmd == "BDAT") { + VASSERT("Client must send the MAIL command", m_mailSent); VASSERT("Client must send the RCPT command", m_rcptSent); @@ -337,23 +341,23 @@ public: std::string last; iss >> last; - if (m_bdatChunkCount == 0) - { + if (m_bdatChunkCount == 0) { + VASSERT_EQ("BDAT chunk1 size", 262144, chunkSize); VASSERT_EQ("BDAT chunk1 last", "", last); - } - else if (m_bdatChunkCount == 1) - { + + } else if (m_bdatChunkCount == 1) { + VASSERT_EQ("BDAT chunk2 size", 262144, chunkSize); VASSERT_EQ("BDAT chunk2 last", "", last); - } - else if (m_bdatChunkCount == 2) - { + + } else if (m_bdatChunkCount == 2) { + VASSERT_EQ("BDAT chunk3 size", 4712, chunkSize); VASSERT_EQ("BDAT chunk3 last", "LAST", last); - } - else - { + + } else { + VASSERT("No more BDAT command should be issued!", false); } @@ -363,19 +367,19 @@ public: m_state = STATE_DATA; localSend("250 chunk received\r\n"); - } - else if (cmd == "NOOP") - { + + } else if (cmd == "NOOP") { + localSend("250 Completed\r\n"); - } - else if (cmd == "QUIT") - { + + } else if (cmd == "QUIT") { + localSend("221 test.vmime.org Service closing transmission channel\r\n"); m_quitSent = true; - } - else - { + + } else { + localSend("502 Command not implemented\r\n"); } @@ -389,8 +393,7 @@ public: private: - enum State - { + enum State { STATE_NOT_CONNECTED, STATE_COMMAND, STATE_DATA @@ -404,22 +407,21 @@ private: }; -class SMTPTestMessage : public vmime::message -{ +class SMTPTestMessage : public vmime::message { + public: - vmime::size_t getChunkBufferSize() const - { + vmime::size_t getChunkBufferSize() const { + static vmime::net::smtp::SMTPChunkingOutputStreamAdapter chunkStream(vmime::null, 0, NULL); return chunkStream.getBlockSize(); } - const std::vector <vmime::string>& getChunks() const - { + const std::vector <vmime::string>& getChunks() const { + static std::vector <vmime::string> chunks; - if (chunks.size() == 0) - { + if (chunks.size() == 0) { chunks.push_back(vmime::string(1000, 'A')); chunks.push_back(vmime::string(3000, 'B')); chunks.push_back(vmime::string(500000, 'C')); @@ -429,12 +431,15 @@ public: return chunks; } - void generateImpl - (const vmime::generationContext& /* ctx */, vmime::utility::outputStream& outputStream, - const size_t /* curLinePos */ = 0, size_t* /* newLinePos */ = NULL) const - { - for (size_t i = 0, n = getChunks().size() ; i < n ; ++i) - { + void generateImpl( + const vmime::generationContext& /* ctx */, + vmime::utility::outputStream& outputStream, + const size_t /* curLinePos */ = 0, + size_t* /* newLinePos */ = NULL + ) const { + + for (size_t i = 0, n = getChunks().size() ; i < n ; ++i) { + const vmime::string& chunk = getChunks()[i]; outputStream.write(chunk.data(), chunk.size()); } @@ -448,72 +453,74 @@ public: * Test SIZE extension. */ template <bool WITH_CHUNKING> -class bigMessageSMTPTestSocket : public testSocket -{ +class bigMessageSMTPTestSocket : public testSocket { + public: - bigMessageSMTPTestSocket() - { + bigMessageSMTPTestSocket() { + m_state = STATE_NOT_CONNECTED; m_ehloSent = m_mailSent = m_rcptSent = m_quitSent = false; } - ~bigMessageSMTPTestSocket() - { + ~bigMessageSMTPTestSocket() { + VASSERT("Client must send the QUIT command", m_quitSent); } - void onConnected() - { + void onConnected() { + localSend("220 test.vmime.org Service ready\r\n"); processCommand(); m_state = STATE_COMMAND; } - void onDataReceived() - { + void onDataReceived() { + processCommand(); } - void processCommand() - { + void processCommand() { + vmime::string line; - if (!localReceiveLine(line)) + if (!localReceiveLine(line)) { return; + } std::istringstream iss(line); - switch (m_state) - { + switch (m_state) { + case STATE_NOT_CONNECTED: localSend("451 Requested action aborted: invalid state\r\n"); break; - case STATE_COMMAND: - { + case STATE_COMMAND: { + std::string cmd; iss >> cmd; - if (cmd == "EHLO") - { + if (cmd == "EHLO") { + localSend("250-test.vmime.org says hello\r\n"); - if (WITH_CHUNKING) + if (WITH_CHUNKING) { localSend("250-CHUNKING\r\n"); + } localSend("250 SIZE 1000000\r\n"); m_ehloSent = true; - } - else if (cmd == "HELO") - { + + } else if (cmd == "HELO") { + VASSERT("Client must not send the HELO command, as EHLO succeeded", false); - } - else if (cmd == "MAIL") - { + + } else if (cmd == "MAIL") { + VASSERT("The MAIL command must be sent only one time", !m_mailSent); std::string address; @@ -529,19 +536,19 @@ public: localSend("552 Channel size limit exceeded\r\n"); m_mailSent = true; - } - else if (cmd == "NOOP") - { + + } else if (cmd == "NOOP") { + localSend("250 Completed\r\n"); - } - else if (cmd == "QUIT") - { + + } else if (cmd == "QUIT") { + localSend("221 test.vmime.org Service closing transmission channel\r\n"); m_quitSent = true; - } - else - { + + } else { + VASSERT("No other command should be sent", false); localSend("502 Command not implemented\r\n"); @@ -557,8 +564,7 @@ public: private: - enum State - { + enum State { STATE_NOT_CONNECTED, STATE_COMMAND, STATE_DATA @@ -571,23 +577,216 @@ private: template <unsigned long SIZE> -class SMTPBigTestMessage : public vmime::message -{ +class SMTPBigTestMessage : public vmime::message { + public: - size_t getGeneratedSize(const vmime::generationContext& /* ctx */) - { + size_t getGeneratedSize(const vmime::generationContext& /* ctx */) { + return SIZE; } - void generateImpl(const vmime::generationContext& /* ctx */, - vmime::utility::outputStream& outputStream, - const vmime::size_t /* curLinePos */ = 0, - vmime::size_t* /* newLinePos */ = NULL) const - { - for (unsigned int i = 0, n = SIZE ; i < n ; ++i) + void generateImpl( + const vmime::generationContext& /* ctx */, + vmime::utility::outputStream& outputStream, + const vmime::size_t /* curLinePos */ = 0, + vmime::size_t* /* newLinePos */ = NULL + ) const { + + for (unsigned int i = 0, n = SIZE ; i < n ; ++i) { outputStream.write("X", 1); + } } }; typedef SMTPBigTestMessage <4194304> SMTPBigTestMessage4MB; + + + +/** SMTP test server for SMTPUTF8 extension. + */ +template <bool SUPPORTS_UTF8> +class UTF8SMTPTestSocket : public lineBasedTestSocket { + +public: + + UTF8SMTPTestSocket() { + + if (SUPPORTS_UTF8) { + + m_rcptLines.insert("RCPT TO:<[email protected]>"); + m_rcptLines.insert("RCPT TO:<[email protected]>"); + m_rcptLines.insert("RCPT TO:<ré[email protected]>"); + + } else { + + m_rcptLines.insert("RCPT TO:<[email protected]>"); + m_rcptLines.insert("RCPT TO:<[email protected]>"); + m_rcptLines.insert("RCPT TO:<[email protected]>"); + } + + m_state = STATE_NOT_CONNECTED; + m_ehloSent = m_mailSent = m_rcptSent = m_dataSent = m_quitSent = false; + } + + ~UTF8SMTPTestSocket() { + + } + + 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 == "EHLO") { + + if (SUPPORTS_UTF8) { + + localSend("250-test.vmime.org\r\n"); + localSend("250 SMTPUTF8\r\n"); + + } else { + + localSend("250 test.vmime.org\r\n"); + } + + m_ehloSent = true; + + } else if (cmd == "HELO") { + + VASSERT("Client must not send the HELO command, as EHLO succeeded", false); + + } else if (cmd == "MAIL") { + + VASSERT("Client must send the EHLO command", m_ehloSent); + VASSERT("The MAIL command must be sent only one time", !m_mailSent); + + if (SUPPORTS_UTF8) { + + VASSERT( + "MAIL", + std::string("MAIL FROM:<[email protected]> SMTPUTF8") == line + || std::string("MAIL FROM:<expé[email protected]> SMTPUTF8") == line + ); + + } else { + + VASSERT( + "MAIL", + std::string("MAIL FROM:<[email protected]>") == line + || std::string("MAIL FROM:<[email protected]>") == line + ); + } + + localSend("250 OK\r\n"); + + m_mailSent = true; + + } else if (cmd == "RCPT") { + + std::set <vmime::string>::iterator it = m_rcptLines.find(line); + + VASSERT(std::string("RCPT not found: '") + line + "'", it != m_rcptLines.end()); + + m_rcptLines.erase(it); + + localSend("250 OK, recipient accepted\r\n"); + + m_rcptSent = true; + + } else if (cmd == "DATA") { + + VASSERT("Client must send the MAIL command", m_mailSent); + VASSERT("Client must send the RCPT command", m_rcptSent); + VASSERT("All recipients", m_rcptLines.empty()); + + localSend("354 Ready to accept data; end with <CRLF>.<CRLF>\r\n"); + + m_state = STATE_DATA; + m_msgData.clear(); + + m_dataSent = true; + + } else if (cmd == "NOOP") { + + localSend("250 Completed\r\n"); + + } else if (cmd == "QUIT") { + + m_quitSent = true; + + 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_rcptLines; + + std::string m_msgData; + + bool m_ehloSent, m_mailSent, m_rcptSent, m_dataSent, m_quitSent; +}; |