SmtpClient-for-Qt/src/smtpclient.cpp
2011-12-16 14:42:26 +02:00

348 lines
7.7 KiB
C++

/*
Copyright (c) 2011 - Tőkés Attila
This file is part of SmtpClient for Qt.
SmtpClient for Qt 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 2 of the License, or
(at your option) any later version.
SmtpClient for Qt is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the LICENSE file for more details.
*/
#include "smtpclient.h"
#include <QFileInfo>
#include <QByteArray>
/* [1] Constructors and destructors */
SmtpClient::SmtpClient(const 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 authentication was faild
if (responseCode != 235)
{
emit smtpError(AuthenticationFailedError);
return false;
}
}
else if (method == AuthLogin)
{
// Sending command: AUTH LOGIN
sendMessage("AUTH LOGIN");
// Wait for 334 response code
waitForResponse();
if (responseCode != 334) { emit smtpError(AuthenticationFailedError); return false; }
// Send the username in base64
sendMessage(QByteArray().append(user).toBase64());
// Wait for 334
waitForResponse();
if (responseCode != 334) { emit smtpError(AuthenticationFailedError); 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 authentication was faild
if (responseCode != 235)
{
emit smtpError(AuthenticationFailedError);
return false;
}
}
}
catch (ResponseTimeoutException e)
{
// Responce Timeout exceeded
emit smtpError(AuthenticationFailedError);
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 \r\n.\r\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] --- */