nymea/plugins/deviceplugins/googlemail/smtpclient.cpp

245 lines
7.5 KiB
C++

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* This file is part of guh. *
* *
* Guh 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, version 2 of the License. *
* *
* Guh 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 guh. If not, see <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "smtpclient.h"
SmtpClient::SmtpClient(const QString &host, int port, SmtpClient::ConnectionType connectionType):
m_host(host), m_port(port), m_connectionType(connectionType)
{
m_socket = new QSslSocket(this);
m_authMethod = AuthLogin;
m_connectionTimeout = 30000;
m_responseTimeout = 30000;
m_sendMessageTimeout = 60000;
connect(m_socket,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(socketError(QAbstractSocket::SocketError)));
connect(m_socket,SIGNAL(connected()),this,SLOT(connected()));
connect(m_socket,SIGNAL(disconnected()),this,SLOT(disconnected()));
}
bool SmtpClient::connectToHost()
{
switch (m_connectionType) {
case TlsConnection:
m_socket->connectToHostEncrypted(m_host, m_port);
break;
case TcpConnection:
m_socket->connectToHost(m_host,m_port);
break;
case SslConnection:
m_socket->connectToHostEncrypted(m_host, m_port);
break;
default:
break;
}
if (!m_socket->waitForConnected(m_connectionTimeout)){
qWarning() << "Mail TCP connection timeout (5s).";
return false;
}
if(waitForResponse() != 220){
qWarning() << "ERROR: could not connect.";
m_socket->close();
return false;
}
send("EHLO localhost");
if(waitForResponse() != 250){
qWarning() << "ERROR: could not connect.";
m_socket->close();
return false;
}
if(m_connectionType == TlsConnection){
//qDebug() << "start client ecryption";
m_socket->startClientEncryption();
if(!m_socket->waitForEncrypted(m_connectionTimeout)){
qDebug() << "encryption falied...";
m_socket->close();
return false;
}
send("EHLO localhost");
if(waitForResponse() != 250){
qWarning() << "ERROR: could not connect.";
m_socket->close();
return false;
}
}
return true;
}
void SmtpClient::connected()
{
qDebug() << "connected to" << m_host;
qDebug() << "-----------------------";
}
void SmtpClient::disconnected()
{
qDebug() << "disconnected from" << m_host;
qDebug() << "-----------------------";
}
bool SmtpClient::login(const QString &user, const QString &password, SmtpClient::AuthMethod method)
{
if(!connectToHost()){
m_socket->disconnect();
return false;
}
qDebug() << "Try to login with: " << user << password;
if(method == AuthPlain){
send("AUTH PLAIN " + QByteArray().append((char) 0).append(user).append((char) 0).append(password).toBase64());
if(waitForResponse() != 235){
qWarning() << "ERROR: could not login AUTH PLAIN";
m_socket->close();
return false;
}
}else if(method == AuthLogin){
send("AUTH LOGIN");
if(waitForResponse() != 334){
qWarning() << "ERROR: could not login AUTH LOGIN";
m_socket->close();
return false;
}
send(QByteArray().append(user).toBase64());
if(waitForResponse() != 334){
qWarning() << "ERROR: could not login AUTH LOGIN...wrong username or password";
m_socket->close();
return false;
}
send(QByteArray().append(password).toBase64());
if(waitForResponse() != 235){
qWarning() << "ERROR: could not login AUTH LOGIN...wrong username or password";
m_socket->close();
return false;
}
}
qDebug() << "login....OK";
qDebug() << "-----------------------";
return true;
}
bool SmtpClient::logout()
{
send("QUIT");
if(waitForResponse() != 221){
qWarning() << "ERROR: could not QUIT connection.";
}
m_socket->close();
return true;
}
int SmtpClient::waitForResponse()
{
while(true){
if(!m_socket->waitForReadyRead(m_responseTimeout)){
qWarning() << "ERROR: mail TCP response timeout.";
return -1;
}
qDebug() << "-----------------------";
QString responseText;
QString responseLine;
while (m_socket->canReadLine() && responseLine[3] != ' ') {
// Save the server's response
responseLine = m_socket->readLine();
responseText.append(responseLine);
}
int responseCode = responseText.left(3).toInt();
qDebug() << responseText;
qDebug() << "-----------------------";
return responseCode;
}
}
bool SmtpClient::sendMail(const QString &from, const QString &to, const QString &subject, const QString &body)
{
send("MAIL FROM:<" + from + ">");
if(waitForResponse() != 250){
qWarning() << "ERROR: could not send mail.";
return false;
}
send("RCPT TO:<" + to + ">");
if(waitForResponse() != 250){
qWarning() << "ERROR: could not send mail.";
return false;
}
send("DATA");
if(waitForResponse() != 354){
qWarning() << "ERROR: could not send mail.";
return false;
}
// mail
QString message;
message = "To: " + to + "\n";
message.append("From: " + from + "\n");
message.append("Subject: " + subject + "\n");
message.append(body);
message.replace( QString::fromLatin1( "\n" ), QString::fromLatin1( "\r\n" ) );
message.replace( QString::fromLatin1( "\r\n.\r\n" ),
QString::fromLatin1( "\r\n..\r\n" ) );
qDebug() << "sending...\n";
qDebug() << "--------------------------------------------";
send(message + "\r\n.");
if(waitForResponse() != 250){
qWarning() << "ERROR: could not send mail.";
return false;
}
logout();
qDebug() << "--------------------------------------------";
qDebug() << " MAIL SENT!!!!";
qDebug() << "--------------------------------------------";
return true;
}
void SmtpClient::socketError(QAbstractSocket::SocketError error)
{
qWarning() << "mail socket:" << error << m_socket->errorString();
}
void SmtpClient::send(const QString &data)
{
qDebug() << "send:" << data;
m_socket->write(data.toUtf8() + "\r\n");
m_socket->flush();
if (m_socket->waitForBytesWritten(m_sendMessageTimeout)){
qWarning() << "mail TCP send timeout (60s)";
}
}