Rewrote SMTP command sending. Better code for pipelining. Report full command text on MAIL/RCPT errors.
This commit is contained in:
parent
f0e12cbadc
commit
83c5ba96b9
@ -243,6 +243,8 @@ libvmime_messaging_proto_sources = [
|
||||
[
|
||||
'smtp',
|
||||
[
|
||||
'net/smtp/SMTPCommand.cpp', 'net/smtp/SMTPCommand.hpp',
|
||||
'net/smtp/SMTPCommandSet.cpp', 'net/smtp/SMTPCommandSet.hpp',
|
||||
'net/smtp/SMTPResponse.cpp', 'net/smtp/SMTPResponse.hpp',
|
||||
'net/smtp/SMTPServiceInfos.cpp', 'net/smtp/SMTPServiceInfos.hpp',
|
||||
'net/smtp/SMTPTransport.cpp', 'net/smtp/SMTPTransport.hpp',
|
||||
|
155
src/net/smtp/SMTPCommand.cpp
Normal file
155
src/net/smtp/SMTPCommand.cpp
Normal file
@ -0,0 +1,155 @@
|
||||
//
|
||||
// VMime library (http://www.vmime.org)
|
||||
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org>
|
||||
//
|
||||
// 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 3 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 "vmime/config.hpp"
|
||||
|
||||
|
||||
#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP
|
||||
|
||||
|
||||
#include "vmime/net/smtp/SMTPCommand.hpp"
|
||||
|
||||
#include "vmime/net/socket.hpp"
|
||||
|
||||
#include "vmime/mailbox.hpp"
|
||||
|
||||
|
||||
namespace vmime {
|
||||
namespace net {
|
||||
namespace smtp {
|
||||
|
||||
|
||||
SMTPCommand::SMTPCommand(const std::string& text)
|
||||
: m_text(text)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
ref <SMTPCommand> SMTPCommand::EHLO(const std::string& hostname)
|
||||
{
|
||||
std::ostringstream cmd;
|
||||
cmd.imbue(std::locale::classic());
|
||||
cmd << "EHLO " << hostname;
|
||||
|
||||
return createCommand(cmd.str());
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
ref <SMTPCommand> SMTPCommand::HELO(const std::string& hostname)
|
||||
{
|
||||
std::ostringstream cmd;
|
||||
cmd.imbue(std::locale::classic());
|
||||
cmd << "HELO " << hostname;
|
||||
|
||||
return createCommand(cmd.str());
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
ref <SMTPCommand> SMTPCommand::AUTH(const std::string& mechName)
|
||||
{
|
||||
std::ostringstream cmd;
|
||||
cmd.imbue(std::locale::classic());
|
||||
cmd << "AUTH " << mechName;
|
||||
|
||||
return createCommand(cmd.str());
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
ref <SMTPCommand> SMTPCommand::STARTTLS()
|
||||
{
|
||||
return createCommand("STARTTLS");
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
ref <SMTPCommand> SMTPCommand::MAIL(const mailbox& mbox)
|
||||
{
|
||||
std::ostringstream cmd;
|
||||
cmd.imbue(std::locale::classic());
|
||||
cmd << "MAIL FROM:<" << mbox.getEmail() << ">";
|
||||
|
||||
return createCommand(cmd.str());
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
ref <SMTPCommand> SMTPCommand::RCPT(const mailbox& mbox)
|
||||
{
|
||||
std::ostringstream cmd;
|
||||
cmd.imbue(std::locale::classic());
|
||||
cmd << "RCPT TO:<" << mbox.getEmail() << ">";
|
||||
|
||||
return createCommand(cmd.str());
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
ref <SMTPCommand> SMTPCommand::DATA()
|
||||
{
|
||||
return createCommand("DATA");
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
ref <SMTPCommand> SMTPCommand::NOOP()
|
||||
{
|
||||
return createCommand("NOOP");
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
ref <SMTPCommand> SMTPCommand::QUIT()
|
||||
{
|
||||
return createCommand("QUIT");
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
ref <SMTPCommand> SMTPCommand::createCommand(const std::string& text)
|
||||
{
|
||||
return vmime::create <SMTPCommand>(text);
|
||||
}
|
||||
|
||||
|
||||
const string SMTPCommand::getText() const
|
||||
{
|
||||
return m_text;
|
||||
}
|
||||
|
||||
|
||||
void SMTPCommand::writeToSocket(ref <socket> sok)
|
||||
{
|
||||
sok->send(m_text + "\r\n");
|
||||
}
|
||||
|
||||
|
||||
} // smtp
|
||||
} // net
|
||||
} // vmime
|
||||
|
||||
|
||||
#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP
|
144
src/net/smtp/SMTPCommandSet.cpp
Normal file
144
src/net/smtp/SMTPCommandSet.cpp
Normal file
@ -0,0 +1,144 @@
|
||||
//
|
||||
// VMime library (http://www.vmime.org)
|
||||
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org>
|
||||
//
|
||||
// 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 3 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 "vmime/config.hpp"
|
||||
|
||||
|
||||
#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP
|
||||
|
||||
|
||||
#include "vmime/net/smtp/SMTPCommandSet.hpp"
|
||||
|
||||
#include "vmime/net/socket.hpp"
|
||||
|
||||
#include "vmime/mailbox.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
|
||||
namespace vmime {
|
||||
namespace net {
|
||||
namespace smtp {
|
||||
|
||||
|
||||
SMTPCommandSet::SMTPCommandSet(const bool pipeline)
|
||||
: SMTPCommand(""), m_pipeline(pipeline),
|
||||
m_started(false), m_lastCommandSent()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
ref <SMTPCommandSet> SMTPCommandSet::create(const bool pipeline)
|
||||
{
|
||||
return vmime::create <SMTPCommandSet>(pipeline);
|
||||
}
|
||||
|
||||
|
||||
void SMTPCommandSet::addCommand(ref <SMTPCommand> cmd)
|
||||
{
|
||||
if (m_started)
|
||||
{
|
||||
throw std::runtime_error("Could not add command to pipeline: "
|
||||
"one or more commands have already been sent to the server.");
|
||||
}
|
||||
|
||||
m_commands.push_back(cmd);
|
||||
}
|
||||
|
||||
|
||||
void SMTPCommandSet::writeToSocket(ref <socket> sok)
|
||||
{
|
||||
if (m_pipeline)
|
||||
{
|
||||
if (!m_started)
|
||||
{
|
||||
// Send all commands at once
|
||||
for (std::list <ref <SMTPCommand> >::const_iterator it = m_commands.begin() ;
|
||||
it != m_commands.end() ; ++it)
|
||||
{
|
||||
ref <SMTPCommand> cmd = *it;
|
||||
cmd->writeToSocket(sok);
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_commands.empty())
|
||||
{
|
||||
// Advance the pointer to last command sent
|
||||
ref <SMTPCommand> cmd = m_commands.front();
|
||||
m_commands.pop_front();
|
||||
|
||||
m_lastCommandSent = cmd;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!m_commands.empty())
|
||||
{
|
||||
// Send only one command
|
||||
ref <SMTPCommand> cmd = m_commands.front();
|
||||
m_commands.pop_front();
|
||||
|
||||
cmd->writeToSocket(sok);
|
||||
|
||||
m_lastCommandSent = cmd;
|
||||
}
|
||||
}
|
||||
|
||||
m_started = true;
|
||||
}
|
||||
|
||||
|
||||
const string SMTPCommandSet::getText() const
|
||||
{
|
||||
std::ostringstream cmd;
|
||||
cmd.imbue(std::locale::classic());
|
||||
|
||||
for (std::list <ref <SMTPCommand> >::const_iterator it = m_commands.begin() ;
|
||||
it != m_commands.end() ; ++it)
|
||||
{
|
||||
cmd << (*it)->getText() << "\r\n";
|
||||
}
|
||||
|
||||
return cmd.str();
|
||||
}
|
||||
|
||||
|
||||
const bool SMTPCommandSet::isFinished() const
|
||||
{
|
||||
return (m_pipeline && m_started) || (m_commands.size() == 0);
|
||||
}
|
||||
|
||||
|
||||
ref <SMTPCommand> SMTPCommandSet::getLastCommandSent() const
|
||||
{
|
||||
return m_lastCommandSent;
|
||||
}
|
||||
|
||||
|
||||
} // smtp
|
||||
} // net
|
||||
} // vmime
|
||||
|
||||
|
||||
#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP
|
@ -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();
|
||||
|
||||
|
||||
const bool hasPipelining =
|
||||
m_extensions.find("PIPELINING") != m_extensions.end();
|
||||
|
||||
ref <SMTPResponse> resp;
|
||||
ref <SMTPCommandSet> commands = SMTPCommandSet::create(hasPipelining);
|
||||
|
||||
if (m_extensions.find("PIPELINING") != m_extensions.end())
|
||||
// Emit the "MAIL" command
|
||||
commands->addCommand(SMTPCommand::MAIL(expeditor));
|
||||
|
||||
// Emit a "RCPT TO" command for each recipient
|
||||
for (size_t i = 0 ; i < recipients.getMailboxCount() ; ++i)
|
||||
{
|
||||
beginCommandPipeline();
|
||||
const mailbox& mbox = *recipients.getMailboxAt(i);
|
||||
commands->addCommand(SMTPCommand::RCPT(mbox));
|
||||
}
|
||||
|
||||
// Emit the "MAIL" command
|
||||
sendRequest("MAIL FROM:<" + expeditor.getEmail() + ">");
|
||||
// Prepare sending of message data
|
||||
commands->addCommand(SMTPCommand::DATA());
|
||||
|
||||
// Emit a "RCPT TO" command for each recipient
|
||||
for (size_t i = 0 ; i < recipients.getMailboxCount() ; ++i)
|
||||
{
|
||||
const mailbox& mbox = *recipients.getMailboxAt(i);
|
||||
// Read response for "MAIL" command
|
||||
commands->writeToSocket(m_socket);
|
||||
|
||||
sendRequest("RCPT TO:<" + mbox.getEmail() + ">");
|
||||
}
|
||||
if ((resp = readResponse())->getCode() != 250)
|
||||
{
|
||||
internalDisconnect();
|
||||
throw exceptions::command_error(commands->getLastCommandSent()->getText(), resp->getText());
|
||||
}
|
||||
|
||||
// Prepare sending of message data
|
||||
sendRequest("DATA");
|
||||
// Read responses for "RCPT TO" commands
|
||||
for (size_t i = 0 ; i < recipients.getMailboxCount() ; ++i)
|
||||
{
|
||||
commands->writeToSocket(m_socket);
|
||||
|
||||
endCommandPipeline();
|
||||
|
||||
// Read response for "MAIL" command
|
||||
if ((resp = readResponse())->getCode() != 250)
|
||||
{
|
||||
internalDisconnect();
|
||||
throw exceptions::command_error("MAIL", resp->getText());
|
||||
}
|
||||
|
||||
// Read responses for "RCPT TO" commands
|
||||
for (size_t i = 0 ; i < recipients.getMailboxCount() ; ++i)
|
||||
{
|
||||
const mailbox& mbox = *recipients.getMailboxAt(i);
|
||||
|
||||
if ((resp = readResponse())->getCode() != 250)
|
||||
{
|
||||
internalDisconnect();
|
||||
throw exceptions::command_error("RCPT TO", resp->getText(), mbox.getEmail());
|
||||
}
|
||||
}
|
||||
|
||||
// Read response for "DATA" command
|
||||
if ((resp = readResponse())->getCode() != 354)
|
||||
{
|
||||
internalDisconnect();
|
||||
throw exceptions::command_error("DATA", resp->getText());
|
||||
throw exceptions::command_error(commands->getLastCommandSent()->getText(), resp->getText());
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
// Read response for "DATA" command
|
||||
commands->writeToSocket(m_socket);
|
||||
|
||||
if ((resp = readResponse())->getCode() != 354)
|
||||
{
|
||||
// Emit the "MAIL" command
|
||||
sendRequest("MAIL FROM:<" + expeditor.getEmail() + ">");
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare sending of message data
|
||||
sendRequest("DATA");
|
||||
|
||||
if ((resp = readResponse())->getCode() != 354)
|
||||
{
|
||||
internalDisconnect();
|
||||
throw exceptions::command_error("DATA", resp->getText());
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
110
vmime/net/smtp/SMTPCommand.hpp
Normal file
110
vmime/net/smtp/SMTPCommand.hpp
Normal file
@ -0,0 +1,110 @@
|
||||
//
|
||||
// VMime library (http://www.vmime.org)
|
||||
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org>
|
||||
//
|
||||
// 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 3 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.
|
||||
//
|
||||
|
||||
#ifndef VMIME_NET_SMTP_SMTPCOMMAND_HPP_INCLUDED
|
||||
#define VMIME_NET_SMTP_SMTPCOMMAND_HPP_INCLUDED
|
||||
|
||||
|
||||
#include "vmime/config.hpp"
|
||||
|
||||
|
||||
#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP
|
||||
|
||||
|
||||
#include "vmime/object.hpp"
|
||||
#include "vmime/base.hpp"
|
||||
|
||||
|
||||
namespace vmime {
|
||||
|
||||
|
||||
class mailbox;
|
||||
|
||||
|
||||
namespace net {
|
||||
|
||||
|
||||
class socket;
|
||||
class timeoutHandler;
|
||||
|
||||
|
||||
namespace smtp {
|
||||
|
||||
|
||||
/** A SMTP command, as sent to server.
|
||||
*/
|
||||
class SMTPCommand : public object
|
||||
{
|
||||
friend class vmime::creator;
|
||||
|
||||
public:
|
||||
|
||||
static ref <SMTPCommand> HELO(const std::string& hostname);
|
||||
static ref <SMTPCommand> EHLO(const std::string& hostname);
|
||||
static ref <SMTPCommand> AUTH(const std::string& mechName);
|
||||
static ref <SMTPCommand> STARTTLS();
|
||||
static ref <SMTPCommand> MAIL(const mailbox& mbox);
|
||||
static ref <SMTPCommand> RCPT(const mailbox& mbox);
|
||||
static ref <SMTPCommand> DATA();
|
||||
static ref <SMTPCommand> NOOP();
|
||||
static ref <SMTPCommand> QUIT();
|
||||
|
||||
/** Creates a new SMTP command with the specified text.
|
||||
*
|
||||
* @param text command text
|
||||
* @return a new SMTPCommand object
|
||||
*/
|
||||
static ref <SMTPCommand> createCommand(const std::string& text);
|
||||
|
||||
/** Sends this command to the specified socket.
|
||||
*
|
||||
* @param sok socket to which the command will be written
|
||||
*/
|
||||
virtual void writeToSocket(ref <socket> sok);
|
||||
|
||||
/** Returns the full text of the command, including command name
|
||||
* and parameters (if any).
|
||||
*
|
||||
* @return command text (eg. "RCPT TO:<vincent@kisli.com>")
|
||||
*/
|
||||
virtual const string getText() const;
|
||||
|
||||
protected:
|
||||
|
||||
SMTPCommand(const std::string& text);
|
||||
SMTPCommand(const SMTPCommand&);
|
||||
|
||||
private:
|
||||
|
||||
std::string m_text;
|
||||
};
|
||||
|
||||
|
||||
} // smtp
|
||||
} // net
|
||||
} // vmime
|
||||
|
||||
|
||||
#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP
|
||||
|
||||
#endif // VMIME_NET_SMTP_SMTPCOMMAND_HPP_INCLUDED
|
107
vmime/net/smtp/SMTPCommandSet.hpp
Normal file
107
vmime/net/smtp/SMTPCommandSet.hpp
Normal file
@ -0,0 +1,107 @@
|
||||
//
|
||||
// VMime library (http://www.vmime.org)
|
||||
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org>
|
||||
//
|
||||
// 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 3 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.
|
||||
//
|
||||
|
||||
#ifndef VMIME_NET_SMTP_SMTPCOMMANDSET_HPP_INCLUDED
|
||||
#define VMIME_NET_SMTP_SMTPCOMMANDSET_HPP_INCLUDED
|
||||
|
||||
|
||||
#include "vmime/config.hpp"
|
||||
|
||||
|
||||
#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP
|
||||
|
||||
|
||||
#include <list>
|
||||
|
||||
#include "vmime/net/smtp/SMTPCommand.hpp"
|
||||
|
||||
|
||||
namespace vmime {
|
||||
namespace net {
|
||||
namespace smtp {
|
||||
|
||||
|
||||
/** A set of SMTP commands, which may be sent all at once
|
||||
* to the server if pipelining is supported.
|
||||
*/
|
||||
class SMTPCommandSet : public SMTPCommand
|
||||
{
|
||||
friend class vmime::creator;
|
||||
|
||||
public:
|
||||
|
||||
/** Creates a new set of SMTP commands.
|
||||
*
|
||||
* @param pipeline set to true if the server supports pipelining
|
||||
* @return a new SMTPCommandSet object
|
||||
*/
|
||||
static ref <SMTPCommandSet> create(const bool pipeline);
|
||||
|
||||
/** Adds a new command to this set.
|
||||
* If one or more comments have already been sent to the server,
|
||||
* an exception will be thrown.
|
||||
*
|
||||
* @param cmd command to add
|
||||
*/
|
||||
void addCommand(ref <SMTPCommand> cmd);
|
||||
|
||||
/** Tests whether all commands have been sent.
|
||||
*
|
||||
* @return true if all commands have been sent,
|
||||
* or false otherwise
|
||||
*/
|
||||
const bool isFinished() const;
|
||||
|
||||
/** Returns the last command which has been sent.
|
||||
*
|
||||
* @return a pointer to a SMTPCommand, of NULL if no command
|
||||
* has been sent yet
|
||||
*/
|
||||
ref <SMTPCommand> getLastCommandSent() const;
|
||||
|
||||
|
||||
void writeToSocket(ref <socket> sok);
|
||||
|
||||
const string getText() const;
|
||||
|
||||
private:
|
||||
|
||||
SMTPCommandSet(const bool pipeline);
|
||||
SMTPCommandSet(const SMTPCommandSet&);
|
||||
|
||||
|
||||
bool m_pipeline;
|
||||
bool m_started;
|
||||
std::list <ref <SMTPCommand> > m_commands;
|
||||
ref <SMTPCommand> m_lastCommandSent;
|
||||
};
|
||||
|
||||
|
||||
} // smtp
|
||||
} // net
|
||||
} // vmime
|
||||
|
||||
|
||||
#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP
|
||||
|
||||
#endif // VMIME_NET_SMTP_SMTPCOMMANDSET_HPP_INCLUDED
|
@ -44,6 +44,9 @@ namespace net {
|
||||
namespace smtp {
|
||||
|
||||
|
||||
class SMTPCommand;
|
||||
|
||||
|
||||
/** SMTP transport service.
|
||||
*/
|
||||
|
||||
@ -72,7 +75,7 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
void sendRequest(const string& buffer, const bool end = true);
|
||||
void sendRequest(ref <SMTPCommand> cmd);
|
||||
ref <SMTPResponse> readResponse();
|
||||
|
||||
void internalDisconnect();
|
||||
@ -102,14 +105,6 @@ private:
|
||||
|
||||
SMTPResponse::state m_responseState;
|
||||
|
||||
// Pipelining
|
||||
std::ostringstream m_pipeline;
|
||||
bool m_pipelineStarted;
|
||||
|
||||
void beginCommandPipeline();
|
||||
void endCommandPipeline();
|
||||
|
||||
|
||||
// Service infos
|
||||
static SMTPServiceInfos sm_infos;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user