diff --git a/src/smtpclient.cpp b/src/smtpclient.cpp index e03e480..e3a9bbf 100644 --- a/src/smtpclient.cpp +++ b/src/smtpclient.cpp @@ -178,73 +178,15 @@ bool SmtpClient::login(const QString &user, const QString &password, AuthMethod bool SmtpClient::sendMail(MimeMessage& email) { - try - { - // 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::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; - } + this->email = &email; + changeState(MailSendingState); return true; } void SmtpClient::quit() { - sendMessage("QUIT"); + changeState(DisconnectingState); } /* [3] --- */ @@ -291,6 +233,19 @@ void SmtpClient::changeState(ClientState state) { } 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: // Service ready. Send EHLO message and chage the state sendMessage("EHLO " + name); @@ -325,10 +280,6 @@ void SmtpClient::changeState(ClientState state) { break; /* --- AUTH --- */ - case AuthenticatingState: - changeState(authMethod == AuthPlain ? _AUTH_PLAIN_0 : _AUTH_LOGIN_0); - break; - case _AUTH_PLAIN_0: // Sending command: AUTH PLAIN base64('\0' + username + '\0' + password) sendMessage("AUTH PLAIN " + QByteArray().append((char) 0).append(user) @@ -354,11 +305,58 @@ void SmtpClient::changeState(ClientState state) { emit authenticated(); 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: ; } - - } void SmtpClient::processResponse() { @@ -405,7 +403,7 @@ void SmtpClient::processResponse() { case _AUTH_PLAIN_0: // If the response is not 235 then the authentication was failed if (responseCode != 235) { - emit smtpError(AuthenticationFailedError); + emit smtpError(AuthenticationError); return; } changeState(_READY_Authenticated); @@ -413,7 +411,7 @@ void SmtpClient::processResponse() { case _AUTH_LOGIN_0: if (responseCode != 334) { - emit smtpError(AuthenticationFailedError); + emit smtpError(AuthenticationError); return; } changeState(_AUTH_LOGIN_1_USER); @@ -421,7 +419,7 @@ void SmtpClient::processResponse() { case _AUTH_LOGIN_1_USER: if (responseCode != 334) { - emit smtpError(AuthenticationFailedError); + emit smtpError(AuthenticationError); return; } changeState(_AUTH_LOGIN_2_PASS); @@ -429,12 +427,46 @@ void SmtpClient::processResponse() { case _AUTH_LOGIN_2_PASS: if (responseCode != 235) { - emit smtpError(AuthenticationFailedError); + emit smtpError(AuthenticationError); return; } changeState(_READY_Authenticated); 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: ; } diff --git a/src/smtpclient.h b/src/smtpclient.h index 5de7eee..0c4aa45 100644 --- a/src/smtpclient.h +++ b/src/smtpclient.h @@ -40,12 +40,13 @@ public: enum SmtpError { - ConnectionTimeoutError, - ResponseTimeoutError, - AuthenticationFailedError, - ServerError, // 4xx smtp error - ClientError, // 5xx smtp error - SocketError + ConnectionTimeoutError = 0, + ResponseTimeoutError = 1, + AuthenticationError = 2, + MailSendingError = 3, + ServerError = 4, // 4xx smtp error + ClientError = 5, // 5xx smtp error + SocketError = 6 }; enum ConnectionType @@ -81,12 +82,17 @@ public: _TLS_2_EHLO = 62, // AUTH - _AUTH_PLAIN_0 = 63, - _AUTH_LOGIN_0 = 64, - _AUTH_LOGIN_1_USER = 65, - _AUTH_LOGIN_2_PASS = 66 - + _AUTH_PLAIN_0 = 70, + _AUTH_LOGIN_0 = 71, + _AUTH_LOGIN_1_USER = 72, + _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] --- */ @@ -172,6 +178,12 @@ protected: QString tempResponse; int responseCode; + MimeMessage *email; + QList::const_iterator addressIt; + const QList *addressList; + + int rcptType; + enum _RcptType { _TO = 1, _CC = 2, _BCC = 3}; class ResponseTimeoutException {}; @@ -205,7 +217,7 @@ signals: /* [7] Signals */ - void smtpError(SmtpError e); + void smtpError(SmtpClient::SmtpError e); void stateChanged(SmtpClient::ClientState s); void connected(); void readyConnected();