From 0757efad0d0669766236eefbedad98ee8541a5f5 Mon Sep 17 00:00:00 2001 From: Vincent Richard Date: Sun, 17 Feb 2013 18:07:23 +0100 Subject: [PATCH] Reset SMTP session state (using RSET command) if transport is being reused. --- src/net/smtp/SMTPCommand.cpp | 7 +++++++ src/net/smtp/SMTPTransport.cpp | 22 +++++++++++++++++++++- tests/net/smtp/SMTPCommandTest.cpp | 9 +++++++++ vmime/net/smtp/SMTPCommand.hpp | 1 + vmime/net/smtp/SMTPTransport.hpp | 2 ++ 5 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/net/smtp/SMTPCommand.cpp b/src/net/smtp/SMTPCommand.cpp index 13b1dc5d..f338e248 100644 --- a/src/net/smtp/SMTPCommand.cpp +++ b/src/net/smtp/SMTPCommand.cpp @@ -107,6 +107,13 @@ ref SMTPCommand::RCPT(const mailbox& mbox) } +// static +ref SMTPCommand::RSET() +{ + return createCommand("RSET"); +} + + // static ref SMTPCommand::DATA() { diff --git a/src/net/smtp/SMTPTransport.cpp b/src/net/smtp/SMTPTransport.cpp index 8a3362e2..f1fa76aa 100644 --- a/src/net/smtp/SMTPTransport.cpp +++ b/src/net/smtp/SMTPTransport.cpp @@ -70,7 +70,7 @@ namespace smtp { SMTPTransport::SMTPTransport(ref sess, ref auth, const bool secured) : transport(sess, getInfosInstance(), auth), m_socket(NULL), m_authentified(false), m_extendedSMTP(false), m_timeoutHandler(NULL), - m_isSMTPS(secured), m_secured(false) + m_isSMTPS(secured), m_secured(false), m_needReset(false) { } @@ -574,15 +574,23 @@ void SMTPTransport::send(const mailbox& expeditor, const mailboxList& recipients throw exceptions::no_expeditor(); + const bool needReset = m_needReset; const bool hasPipelining = m_extensions.find("PIPELINING") != m_extensions.end(); ref resp; ref commands = SMTPCommandSet::create(hasPipelining); + // Emit a "RSET" command if we previously sent a message on this connection + if (needReset) + commands->addCommand(SMTPCommand::RSET()); + // Emit the "MAIL" command commands->addCommand(SMTPCommand::MAIL(expeditor)); + // Now, we will need to reset next time + m_needReset = true; + // Emit a "RCPT TO" command for each recipient for (size_t i = 0 ; i < recipients.getMailboxCount() ; ++i) { @@ -593,6 +601,18 @@ void SMTPTransport::send(const mailbox& expeditor, const mailboxList& recipients // Prepare sending of message data commands->addCommand(SMTPCommand::DATA()); + // Read response for "RSET" command + if (needReset) + { + commands->writeToSocket(m_socket); + + if ((resp = readResponse())->getCode() != 250) + { + internalDisconnect(); + throw exceptions::command_error(commands->getLastCommandSent()->getText(), resp->getText()); + } + } + // Read response for "MAIL" command commands->writeToSocket(m_socket); diff --git a/tests/net/smtp/SMTPCommandTest.cpp b/tests/net/smtp/SMTPCommandTest.cpp index 93cdf7ae..0ff52741 100644 --- a/tests/net/smtp/SMTPCommandTest.cpp +++ b/tests/net/smtp/SMTPCommandTest.cpp @@ -44,6 +44,7 @@ VMIME_TEST_SUITE_BEGIN VMIME_TEST(testSTARTTLS) VMIME_TEST(testMAIL) VMIME_TEST(testRCPT) + VMIME_TEST(testRSET) VMIME_TEST(testDATA) VMIME_TEST(testNOOP) VMIME_TEST(testQUIT) @@ -115,6 +116,14 @@ VMIME_TEST_SUITE_BEGIN VASSERT_EQ("Text", "RCPT TO:", cmd->getText()); } + void testRSET() + { + vmime::ref cmd = SMTPCommand::RSET(); + + VASSERT_NOT_NULL("Not null", cmd); + VASSERT_EQ("Text", "RSET", cmd->getText()); + } + void testDATA() { vmime::ref cmd = SMTPCommand::DATA(); diff --git a/vmime/net/smtp/SMTPCommand.hpp b/vmime/net/smtp/SMTPCommand.hpp index ccf445e5..3a28445f 100644 --- a/vmime/net/smtp/SMTPCommand.hpp +++ b/vmime/net/smtp/SMTPCommand.hpp @@ -65,6 +65,7 @@ public: static ref STARTTLS(); static ref MAIL(const mailbox& mbox); static ref RCPT(const mailbox& mbox); + static ref RSET(); static ref DATA(); static ref NOOP(); static ref QUIT(); diff --git a/vmime/net/smtp/SMTPTransport.hpp b/vmime/net/smtp/SMTPTransport.hpp index 50885203..20f4bc52 100644 --- a/vmime/net/smtp/SMTPTransport.hpp +++ b/vmime/net/smtp/SMTPTransport.hpp @@ -105,6 +105,8 @@ private: SMTPResponse::state m_responseState; + bool m_needReset; + // Service infos static SMTPServiceInfos sm_infos; };