diff options
author | Vincent Richard <[email protected]> | 2013-02-12 15:58:27 +0000 |
---|---|---|
committer | Vincent Richard <[email protected]> | 2013-02-12 15:58:27 +0000 |
commit | 83c5ba96b9e1ae8fc1d4d413aff57d6522b9c184 (patch) | |
tree | c76b03893e920ed7d9745e136cc383ccf53188d3 /src/net/smtp/SMTPTransport.cpp | |
parent | Fixed invalid use of freed memory. (diff) | |
download | vmime-83c5ba96b9e1ae8fc1d4d413aff57d6522b9c184.tar.gz vmime-83c5ba96b9e1ae8fc1d4d413aff57d6522b9c184.zip |
Rewrote SMTP command sending. Better code for pipelining. Report full command text on MAIL/RCPT errors.
Diffstat (limited to 'src/net/smtp/SMTPTransport.cpp')
-rw-r--r-- | src/net/smtp/SMTPTransport.cpp | 154 |
1 files changed, 45 insertions, 109 deletions
diff --git a/src/net/smtp/SMTPTransport.cpp b/src/net/smtp/SMTPTransport.cpp index c17b4a05..8a3362e2 100644 --- a/src/net/smtp/SMTPTransport.cpp +++ b/src/net/smtp/SMTPTransport.cpp @@ -29,6 +29,8 @@ #include "vmime/net/smtp/SMTPTransport.hpp" #include "vmime/net/smtp/SMTPResponse.hpp" +#include "vmime/net/smtp/SMTPCommand.hpp" +#include "vmime/net/smtp/SMTPCommandSet.hpp" #include "vmime/exception.hpp" #include "vmime/platform.hpp" @@ -68,7 +70,7 @@ namespace smtp { SMTPTransport::SMTPTransport(ref <session> sess, ref <security::authenticator> 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_pipelineStarted(false) + m_isSMTPS(secured), m_secured(false) { } @@ -202,7 +204,7 @@ void SMTPTransport::helo() // S: 250-PIPELINING // S: 250 SIZE 2555555555 - sendRequest("EHLO " + platform::getHandler()->getHostName()); + sendRequest(SMTPCommand::EHLO(platform::getHandler()->getHostName())); ref <SMTPResponse> resp; @@ -213,7 +215,7 @@ void SMTPTransport::helo() // eg: C: HELO thismachine.ourdomain.com // S: 250 OK - sendRequest("HELO " + platform::getHandler()->getHostName()); + sendRequest(SMTPCommand::HELO(platform::getHandler()->getHostName())); if ((resp = readResponse())->getCode() != 250) { @@ -365,7 +367,7 @@ void SMTPTransport::authenticateSASL() saslSession->init(); - sendRequest("AUTH " + mech->getName()); + sendRequest(SMTPCommand::AUTH(mech->getName())); for (bool cont = true ; cont ; ) { @@ -396,7 +398,7 @@ void SMTPTransport::authenticateSASL() (challenge, challengeLen, &resp, &respLen); // Send response - sendRequest(saslContext->encodeB64(resp, respLen)); + m_socket->send(saslContext->encodeB64(resp, respLen) + "\r\n"); } catch (exceptions::sasl_exception& e) { @@ -413,7 +415,7 @@ void SMTPTransport::authenticateSASL() } // Cancel SASL exchange - sendRequest("*"); + m_socket->sendRaw("*\r\n", 3); } catch (...) { @@ -455,7 +457,7 @@ void SMTPTransport::startTLS() { try { - sendRequest("STARTTLS"); + sendRequest(SMTPCommand::STARTTLS()); ref <SMTPResponse> resp = readResponse(); @@ -523,7 +525,7 @@ void SMTPTransport::internalDisconnect() { try { - sendRequest("QUIT"); + sendRequest(SMTPCommand::QUIT()); readResponse(); } catch (exception&) @@ -549,7 +551,7 @@ void SMTPTransport::noop() if (!isConnected()) throw exceptions::not_connected(); - sendRequest("NOOP"); + sendRequest(SMTPCommand::NOOP()); ref <SMTPResponse> resp = readResponse(); @@ -572,87 +574,53 @@ void SMTPTransport::send(const mailbox& expeditor, const mailboxList& recipients throw exceptions::no_expeditor(); - ref <SMTPResponse> resp; - - if (m_extensions.find("PIPELINING") != m_extensions.end()) - { - beginCommandPipeline(); - - // Emit the "MAIL" command - sendRequest("MAIL FROM:<" + expeditor.getEmail() + ">"); - - // Emit a "RCPT TO" command for each recipient - for (size_t i = 0 ; i < recipients.getMailboxCount() ; ++i) - { - const mailbox& mbox = *recipients.getMailboxAt(i); - - sendRequest("RCPT TO:<" + mbox.getEmail() + ">"); - } + const bool hasPipelining = + m_extensions.find("PIPELINING") != m_extensions.end(); - // Prepare sending of message data - sendRequest("DATA"); + ref <SMTPResponse> resp; + ref <SMTPCommandSet> commands = SMTPCommandSet::create(hasPipelining); - endCommandPipeline(); + // Emit the "MAIL" command + commands->addCommand(SMTPCommand::MAIL(expeditor)); - // Read response for "MAIL" command - if ((resp = readResponse())->getCode() != 250) - { - internalDisconnect(); - throw exceptions::command_error("MAIL", resp->getText()); - } + // Emit a "RCPT TO" command for each recipient + for (size_t i = 0 ; i < recipients.getMailboxCount() ; ++i) + { + const mailbox& mbox = *recipients.getMailboxAt(i); + commands->addCommand(SMTPCommand::RCPT(mbox)); + } - // Read responses for "RCPT TO" commands - for (size_t i = 0 ; i < recipients.getMailboxCount() ; ++i) - { - const mailbox& mbox = *recipients.getMailboxAt(i); + // Prepare sending of message data + commands->addCommand(SMTPCommand::DATA()); - if ((resp = readResponse())->getCode() != 250) - { - internalDisconnect(); - throw exceptions::command_error("RCPT TO", resp->getText(), mbox.getEmail()); - } - } + // Read response for "MAIL" command + commands->writeToSocket(m_socket); - // Read response for "DATA" command - if ((resp = readResponse())->getCode() != 354) - { - internalDisconnect(); - throw exceptions::command_error("DATA", resp->getText()); - } + if ((resp = readResponse())->getCode() != 250) + { + internalDisconnect(); + throw exceptions::command_error(commands->getLastCommandSent()->getText(), resp->getText()); } - else + + // Read responses for "RCPT TO" commands + for (size_t i = 0 ; i < recipients.getMailboxCount() ; ++i) { - // Emit the "MAIL" command - sendRequest("MAIL FROM:<" + expeditor.getEmail() + ">"); + commands->writeToSocket(m_socket); if ((resp = readResponse())->getCode() != 250) { internalDisconnect(); - throw exceptions::command_error("MAIL", resp->getText()); - } - - // Emit a "RCPT TO" command for each recipient - for (size_t i = 0 ; i < recipients.getMailboxCount() ; ++i) - { - const mailbox& mbox = *recipients.getMailboxAt(i); - - sendRequest("RCPT TO:<" + mbox.getEmail() + ">"); - - if ((resp = readResponse())->getCode() != 250) - { - internalDisconnect(); - throw exceptions::command_error("RCPT TO", resp->getText(), mbox.getEmail()); - } + throw exceptions::command_error(commands->getLastCommandSent()->getText(), resp->getText()); } + } - // Prepare sending of message data - sendRequest("DATA"); + // Read response for "DATA" command + commands->writeToSocket(m_socket); - if ((resp = readResponse())->getCode() != 354) - { - internalDisconnect(); - throw exceptions::command_error("DATA", resp->getText()); - } + if ((resp = readResponse())->getCode() != 354) + { + internalDisconnect(); + throw exceptions::command_error(commands->getLastCommandSent()->getText(), resp->getText()); } // Send the message data @@ -675,41 +643,9 @@ void SMTPTransport::send(const mailbox& expeditor, const mailboxList& recipients } -void SMTPTransport::beginCommandPipeline() +void SMTPTransport::sendRequest(ref <SMTPCommand> cmd) { - m_pipeline.clear(); - m_pipelineStarted = true; -} - - -void SMTPTransport::endCommandPipeline() -{ - if (m_pipelineStarted) - { - m_socket->send(m_pipeline.str()); - - m_pipeline.clear(); - m_pipelineStarted = false; - } -} - - -void SMTPTransport::sendRequest(const string& buffer, const bool end) -{ - if (m_pipelineStarted) - { - m_pipeline << buffer; - - if (end) - m_pipeline << "\r\n"; - } - else - { - if (end) - m_socket->send(buffer + "\r\n"); - else - m_socket->send(buffer); - } + cmd->writeToSocket(m_socket); } |