SmtpClient-for-Qt/smtpclient.cpp
2011-08-30 21:59:16 +03:00

338 lines
7.3 KiB
C++

/*
Copyright (c) Tőkés Attila (bluetiger9)
Released under LGPL 2.0
*/
#include "smtpclient.h"
#include <QFileInfo>
#include <QByteArray>
/* [1] Constructors and destructors */
SmtpClient::SmtpClient(QString host, int port, ConnectionType ct) :
authMethod(AuthPlain),
connectionTimeout(5000),
responseTimeout(5000)
{
if (ct == TcpConnection)
this->useSsl = false;
else if (ct == SslConnection)
this->useSsl = true;
if (useSsl == false)
socket = new QTcpSocket(this);
else
socket = new QSslSocket(this);
this->host = host;
this->port = port;
connect(socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
this, SLOT(socketStateChanged(QAbstractSocket::SocketState)));
connect(socket, SIGNAL(error(QAbstractSocket::SocketError)),
this, SLOT(socketError(QAbstractSocket::SocketError)));
connect(socket, SIGNAL(readyRead()),
this, SLOT(socketReadyRead()));
}
SmtpClient::~SmtpClient() {}
/* [1] --- */
/* [2] Getters and Setters */
void SmtpClient::setUser(const QString &user)
{
this->user = user;
}
void SmtpClient::setPassword(const QString &password)
{
this->password = password;
}
void SmtpClient::setAuthMethod(AuthMethod method)
{
this->authMethod = method;
}
void SmtpClient::setHost(QString &host)
{
this->host = host;
}
void SmtpClient::setPort(int port)
{
this->port = port;
}
void SmtpClient::setConnectionType(ConnectionType ct)
{
if (ct == TcpConnection)
this->useSsl = false;
else if (ct == SslConnection)
this->useSsl = true;
if (useSsl == false)
socket = new QTcpSocket(this);
else
socket = new QSslSocket(this);
}
const QString& SmtpClient::getHost() const
{
return this->host;
}
const QString& SmtpClient::getUser() const
{
return this->user;
}
const QString& SmtpClient::getPassword() const
{
return this->password;
}
SmtpClient::AuthMethod SmtpClient::getAuthMethod() const
{
return this->authMethod;
}
int SmtpClient::getPort() const
{
return this->port;
}
SmtpClient::ConnectionType SmtpClient::getConnectionType() const
{
if (useSsl)
return SslConnection;
else
return TcpConnection;
}
/* [2] --- */
/* [3] Public methods */
bool SmtpClient::connectToHost()
{
if (useSsl)
((QSslSocket*) socket)->connectToHostEncrypted(host, port);
else
socket->connectToHost(host, port);
// Tries to connect to server
if (!socket->waitForConnected(connectionTimeout))
{
emit smtpError(ConnectionTimeoutError);
return false;
}
try
{
// Wait for the server's response
waitForResponse();
// If the response code is not 220 (Service ready)
// means that is something wrong with the server
if (responseCode != 220)
{
emit smtpError(ServerError);
return false;
}
// Send a EHLO/HELO message to the server
// The client's first command must be EHLO/HELO
sendMessage("EHLO SmtpClient for Qt/C++");
// Wait for the server's response
waitForResponse();
// The response code needs to be 250.
if (responseCode != 250)
{
emit smtpError(ServerError);
return false;
}
}
catch (ResponseTimeoutException)
{
return false;
}
// If no errors occured the function returns true.
return true;
}
bool SmtpClient::login()
{
return login(user, password, authMethod);
}
bool SmtpClient::login(const QString &user, const QString &password, AuthMethod method)
{
try {
if (method == AuthPlain)
{
// Sending command: AUTH PLAIN base64('\0' + username + '\0' + password)
sendMessage("AUTH PLAIN " + QByteArray().append((char) 0).append(user).append((char) 0).append(password).toBase64());
// Wait for the server's response
waitForResponse();
// If the response is not 235 then the authification was faild
if (responseCode != 235)
{
emit smtpError(AuthentificationFailedError);
return false;
}
}
else if (method == AuthLogin)
{
// Sending command: AUTH LOGIN
sendMessage("AUTH LOGIN");
// Wait for 334 response code
waitForResponse();
if (responseCode != 334) { emit smtpError(AuthentificationFailedError); return false; }
// Send the username in base64
sendMessage(QByteArray().append(user).toBase64());
// Wait for 334
waitForResponse();
if (responseCode != 334) { emit smtpError(AuthentificationFailedError); return false; }
// Send the password in base64
sendMessage(QByteArray().append(password).toBase64());
// Wait for the server's responce
waitForResponse();
// If the response is not 235 then the authification was faild
if (responseCode != 235)
{
emit smtpError(AuthentificationFailedError);
return false;
}
}
}
catch (ResponseTimeoutException e)
{
// Responce Timeout exceeded
emit smtpError(AuthentificationFailedError);
return false;
}
return true;
}
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
for (int i = 0; i < email.getRecipients().size(); ++i)
{
sendMessage("RCPT TO: <" + email.getRecipients().at(i)->getAddress() + ">");
waitForResponse();
if (responseCode != 250) return false;
}
// Send DATA command
sendMessage("DATA");
waitForResponse();
if (responseCode != 354) return false;
sendMessage(email.toString());
// Send \n.\n to end the mail data
sendMessage(".");
waitForResponse();
if (responseCode != 250) return false;
}
catch (ResponseTimeoutException)
{
return false;
}
return true;
}
void SmtpClient::quit()
{
sendMessage("QUIT");
}
/* [3] --- */
/* [4] Protected methods */
void SmtpClient::waitForResponse() throw (ResponseTimeoutException)
{
if (!socket->waitForReadyRead(responseTimeout))
{
emit smtpError(ResponseTimeoutError);
throw ResponseTimeoutException();
}
// Save the server's response
responseText = socket->readAll();
// Extract the respose code from the server's responce (first 3 digits)
responseCode = responseText.left(3).toInt();
if (responseCode / 100 == 4)
emit smtpError(ServerError);
if (responseCode / 100 == 5)
emit smtpError(ClientError);
}
void SmtpClient::sendMessage(const QString &text)
{
socket->write(text.toUtf8() + "\r\n");
}
/* [4] --- */
/* [5] Slots for the socket's signals */
void SmtpClient::socketStateChanged(QAbstractSocket::SocketState state)
{
}
void SmtpClient::socketError(QAbstractSocket::SocketError socketError)
{
}
void SmtpClient::socketReadyRead()
{
}
/* [5] --- */