First working version of the state machine implementation.
This commit is contained in:
parent
618d583551
commit
297f2f8178
@ -178,73 +178,15 @@ bool SmtpClient::login(const QString &user, const QString &password, AuthMethod
|
|||||||
|
|
||||||
bool SmtpClient::sendMail(MimeMessage& email)
|
bool SmtpClient::sendMail(MimeMessage& email)
|
||||||
{
|
{
|
||||||
try
|
this->email = &email;
|
||||||
{
|
changeState(MailSendingState);
|
||||||
// Send the MAIL command with the sender
|
|
||||||
sendMessage("MAIL FROM: <" + email.getSender().getAddress() + ">");
|
|
||||||
|
|
||||||
waitForResponse();
|
|
||||||
|
|
||||||
if (responseCode != 250) return false;
|
|
||||||
|
|
||||||
// Send RCPT command for each recipient
|
|
||||||
QList<EmailAddress*>::const_iterator it, itEnd;
|
|
||||||
// To (primary recipients)
|
|
||||||
for (it = email.getRecipients().begin(), itEnd = email.getRecipients().end();
|
|
||||||
it != itEnd; ++it)
|
|
||||||
{
|
|
||||||
sendMessage("RCPT TO: <" + (*it)->getAddress() + ">");
|
|
||||||
waitForResponse();
|
|
||||||
|
|
||||||
if (responseCode != 250) return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cc (carbon copy)
|
|
||||||
for (it = email.getRecipients(MimeMessage::Cc).begin(), itEnd = email.getRecipients(MimeMessage::Cc).end();
|
|
||||||
it != itEnd; ++it)
|
|
||||||
{
|
|
||||||
sendMessage("RCPT TO: <" + (*it)->getAddress() + ">");
|
|
||||||
waitForResponse();
|
|
||||||
|
|
||||||
if (responseCode != 250) return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bcc (blind carbon copy)
|
|
||||||
for (it = email.getRecipients(MimeMessage::Bcc).begin(), itEnd = email.getRecipients(MimeMessage::Bcc).end();
|
|
||||||
it != itEnd; ++it)
|
|
||||||
{
|
|
||||||
sendMessage("RCPT TO: <" + (*it)->getAddress() + ">");
|
|
||||||
waitForResponse();
|
|
||||||
|
|
||||||
if (responseCode != 250) return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send DATA command
|
|
||||||
sendMessage("DATA");
|
|
||||||
waitForResponse();
|
|
||||||
|
|
||||||
if (responseCode != 354) return false;
|
|
||||||
|
|
||||||
sendMessage(email.toString());
|
|
||||||
|
|
||||||
// Send \r\n.\r\n to end the mail data
|
|
||||||
sendMessage(".");
|
|
||||||
|
|
||||||
waitForResponse();
|
|
||||||
|
|
||||||
if (responseCode != 250) return false;
|
|
||||||
}
|
|
||||||
catch (ResponseTimeoutException)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SmtpClient::quit()
|
void SmtpClient::quit()
|
||||||
{
|
{
|
||||||
sendMessage("QUIT");
|
changeState(DisconnectingState);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* [3] --- */
|
/* [3] --- */
|
||||||
@ -291,6 +233,19 @@ void SmtpClient::changeState(ClientState state) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case AuthenticatingState:
|
||||||
|
changeState(authMethod == AuthPlain ? _AUTH_PLAIN_0 : _AUTH_LOGIN_0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MailSendingState:
|
||||||
|
changeState(_MAIL_0_FROM);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DisconnectingState:
|
||||||
|
sendMessage("QUIT");
|
||||||
|
socket->disconnectFromHost();
|
||||||
|
break;
|
||||||
|
|
||||||
case _EHLO_State:
|
case _EHLO_State:
|
||||||
// Service ready. Send EHLO message and chage the state
|
// Service ready. Send EHLO message and chage the state
|
||||||
sendMessage("EHLO " + name);
|
sendMessage("EHLO " + name);
|
||||||
@ -325,10 +280,6 @@ void SmtpClient::changeState(ClientState state) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
/* --- AUTH --- */
|
/* --- AUTH --- */
|
||||||
case AuthenticatingState:
|
|
||||||
changeState(authMethod == AuthPlain ? _AUTH_PLAIN_0 : _AUTH_LOGIN_0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case _AUTH_PLAIN_0:
|
case _AUTH_PLAIN_0:
|
||||||
// Sending command: AUTH PLAIN base64('\0' + username + '\0' + password)
|
// Sending command: AUTH PLAIN base64('\0' + username + '\0' + password)
|
||||||
sendMessage("AUTH PLAIN " + QByteArray().append((char) 0).append(user)
|
sendMessage("AUTH PLAIN " + QByteArray().append((char) 0).append(user)
|
||||||
@ -354,11 +305,58 @@ void SmtpClient::changeState(ClientState state) {
|
|||||||
emit authenticated();
|
emit authenticated();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
/* --- MAIL --- */
|
||||||
|
case _MAIL_0_FROM:
|
||||||
|
sendMessage("MAIL FROM: <" + email->getSender().getAddress() + ">");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case _MAIL_1_RCPT_INIT:
|
||||||
|
rcptType++;
|
||||||
|
switch (rcptType)
|
||||||
|
{
|
||||||
|
case _TO:
|
||||||
|
addressList = &email->getRecipients(MimeMessage::To);
|
||||||
|
break;
|
||||||
|
case _CC:
|
||||||
|
addressList = &email->getRecipients(MimeMessage::Cc);
|
||||||
|
break;
|
||||||
|
case _BCC:
|
||||||
|
addressList = &email->getRecipients(MimeMessage::Bcc);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
changeState(_MAIL_3_DATA);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
addressIt = addressList->constBegin();
|
||||||
|
changeState(_MAIL_2_RCPT);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case _MAIL_2_RCPT:
|
||||||
|
if (addressIt != addressList->end()) {
|
||||||
|
sendMessage("RCPT TO: <" + (*addressIt)->getAddress() + ">");
|
||||||
|
addressIt++;
|
||||||
|
} else {
|
||||||
|
changeState(_MAIL_1_RCPT_INIT);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case _MAIL_3_DATA:
|
||||||
|
sendMessage("DATA");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case _MAIL_4_SEND_DATA:
|
||||||
|
sendMessage(email->toString());
|
||||||
|
sendMessage(".");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case _READY_MailSended:
|
||||||
|
changeState(ReadyState);
|
||||||
|
emit mailSended();
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SmtpClient::processResponse() {
|
void SmtpClient::processResponse() {
|
||||||
@ -405,7 +403,7 @@ void SmtpClient::processResponse() {
|
|||||||
case _AUTH_PLAIN_0:
|
case _AUTH_PLAIN_0:
|
||||||
// If the response is not 235 then the authentication was failed
|
// If the response is not 235 then the authentication was failed
|
||||||
if (responseCode != 235) {
|
if (responseCode != 235) {
|
||||||
emit smtpError(AuthenticationFailedError);
|
emit smtpError(AuthenticationError);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
changeState(_READY_Authenticated);
|
changeState(_READY_Authenticated);
|
||||||
@ -413,7 +411,7 @@ void SmtpClient::processResponse() {
|
|||||||
|
|
||||||
case _AUTH_LOGIN_0:
|
case _AUTH_LOGIN_0:
|
||||||
if (responseCode != 334) {
|
if (responseCode != 334) {
|
||||||
emit smtpError(AuthenticationFailedError);
|
emit smtpError(AuthenticationError);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
changeState(_AUTH_LOGIN_1_USER);
|
changeState(_AUTH_LOGIN_1_USER);
|
||||||
@ -421,7 +419,7 @@ void SmtpClient::processResponse() {
|
|||||||
|
|
||||||
case _AUTH_LOGIN_1_USER:
|
case _AUTH_LOGIN_1_USER:
|
||||||
if (responseCode != 334) {
|
if (responseCode != 334) {
|
||||||
emit smtpError(AuthenticationFailedError);
|
emit smtpError(AuthenticationError);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
changeState(_AUTH_LOGIN_2_PASS);
|
changeState(_AUTH_LOGIN_2_PASS);
|
||||||
@ -429,12 +427,46 @@ void SmtpClient::processResponse() {
|
|||||||
|
|
||||||
case _AUTH_LOGIN_2_PASS:
|
case _AUTH_LOGIN_2_PASS:
|
||||||
if (responseCode != 235) {
|
if (responseCode != 235) {
|
||||||
emit smtpError(AuthenticationFailedError);
|
emit smtpError(AuthenticationError);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
changeState(_READY_Authenticated);
|
changeState(_READY_Authenticated);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
/* --- MAIL --- */
|
||||||
|
case _MAIL_0_FROM:
|
||||||
|
if (responseCode != 250) {
|
||||||
|
emit smtpError(MailSendingError);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
changeState(_MAIL_1_RCPT_INIT);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case _MAIL_2_RCPT:
|
||||||
|
if (responseCode != 250) {
|
||||||
|
emit smtpError(MailSendingError);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
changeState(_MAIL_2_RCPT);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case _MAIL_3_DATA:
|
||||||
|
if (responseCode != 354) {
|
||||||
|
emit smtpError(MailSendingError);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
changeState(_MAIL_4_SEND_DATA);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case _MAIL_4_SEND_DATA:
|
||||||
|
if (responseCode != 250) {
|
||||||
|
emit smtpError(MailSendingError);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
changeState(_READY_MailSended);
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
@ -40,12 +40,13 @@ public:
|
|||||||
|
|
||||||
enum SmtpError
|
enum SmtpError
|
||||||
{
|
{
|
||||||
ConnectionTimeoutError,
|
ConnectionTimeoutError = 0,
|
||||||
ResponseTimeoutError,
|
ResponseTimeoutError = 1,
|
||||||
AuthenticationFailedError,
|
AuthenticationError = 2,
|
||||||
ServerError, // 4xx smtp error
|
MailSendingError = 3,
|
||||||
ClientError, // 5xx smtp error
|
ServerError = 4, // 4xx smtp error
|
||||||
SocketError
|
ClientError = 5, // 5xx smtp error
|
||||||
|
SocketError = 6
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ConnectionType
|
enum ConnectionType
|
||||||
@ -81,12 +82,17 @@ public:
|
|||||||
_TLS_2_EHLO = 62,
|
_TLS_2_EHLO = 62,
|
||||||
|
|
||||||
// AUTH
|
// AUTH
|
||||||
_AUTH_PLAIN_0 = 63,
|
_AUTH_PLAIN_0 = 70,
|
||||||
_AUTH_LOGIN_0 = 64,
|
_AUTH_LOGIN_0 = 71,
|
||||||
_AUTH_LOGIN_1_USER = 65,
|
_AUTH_LOGIN_1_USER = 72,
|
||||||
_AUTH_LOGIN_2_PASS = 66
|
_AUTH_LOGIN_2_PASS = 73,
|
||||||
|
|
||||||
|
|
||||||
|
// MAIL
|
||||||
|
_MAIL_0_FROM = 81,
|
||||||
|
_MAIL_1_RCPT_INIT = 82,
|
||||||
|
_MAIL_2_RCPT = 83,
|
||||||
|
_MAIL_3_DATA = 84,
|
||||||
|
_MAIL_4_SEND_DATA = 85
|
||||||
};
|
};
|
||||||
|
|
||||||
/* [0] --- */
|
/* [0] --- */
|
||||||
@ -172,6 +178,12 @@ protected:
|
|||||||
QString tempResponse;
|
QString tempResponse;
|
||||||
int responseCode;
|
int responseCode;
|
||||||
|
|
||||||
|
MimeMessage *email;
|
||||||
|
QList<EmailAddress*>::const_iterator addressIt;
|
||||||
|
const QList<EmailAddress*> *addressList;
|
||||||
|
|
||||||
|
int rcptType;
|
||||||
|
enum _RcptType { _TO = 1, _CC = 2, _BCC = 3};
|
||||||
|
|
||||||
class ResponseTimeoutException {};
|
class ResponseTimeoutException {};
|
||||||
|
|
||||||
@ -205,7 +217,7 @@ signals:
|
|||||||
|
|
||||||
/* [7] Signals */
|
/* [7] Signals */
|
||||||
|
|
||||||
void smtpError(SmtpError e);
|
void smtpError(SmtpClient::SmtpError e);
|
||||||
void stateChanged(SmtpClient::ClientState s);
|
void stateChanged(SmtpClient::ClientState s);
|
||||||
void connected();
|
void connected();
|
||||||
void readyConnected();
|
void readyConnected();
|
||||||
|
Loading…
Reference in New Issue
Block a user