This repository has been archived on 2026-05-31. You can view files and clone it, but cannot push or open issues or pull requests.
Simon Stürz 37c2d0219d add debug categories to each plugin
fix loading vendorId
improoved man page
improoved help message
add extern ids to extern-plugininfo.h
2019-04-01 20:48:17 +02:00

307 lines
9.1 KiB
C++

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2015 Simon Stuerz <simon.stuerz@guh.guru> *
* *
* 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"
#include "extern-plugininfo.h"
SmtpClient::SmtpClient(QObject *parent):
QObject(parent)
{
m_socket = new QSslSocket(this);
m_state = InitState;
m_testLogin = false;
connect(m_socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(socketError(QAbstractSocket::SocketError)));
// error because QSslSocket has also a method called error...also QAbstractSocket or QTcpSocket don't work...
//connect(m_socket, &QSslSocket::error, this, &SmtpClient::socketError);
connect(m_socket, &QSslSocket::connected, this, &SmtpClient::connected);
connect(m_socket, &QSslSocket::readyRead, this, &SmtpClient::readData);
connect(m_socket, &QSslSocket::disconnected, this, &SmtpClient::disconnected);
}
void SmtpClient::connectToHost()
{
switch (m_encryptionType) {
case EncryptionTypeNone:
m_socket->connectToHost(m_host, m_port);
break;
case EncryptionTypeSSL:
m_socket->connectToHostEncrypted(m_host, m_port);
break;
case EncryptionTypeTLS:
m_socket->connectToHost(m_host,m_port);
break;
default:
break;
}
}
void SmtpClient::testLogin()
{
m_socket->close();
m_testLogin = true;
connectToHost();
}
void SmtpClient::connected()
{
}
void SmtpClient::disconnected()
{
}
void SmtpClient::readData()
{
QString response;
QString responseLine;
while(m_socket->canReadLine() && responseLine[3] != ' ') {
responseLine = m_socket->readLine();
response.append(responseLine);
}
responseLine.truncate( 3 );
switch (m_state) {
case InitState:
if(responseLine == "220") {
send("EHLO localhost");
if(m_encryptionType == EncryptionTypeNone) {
m_state = AuthentificationState;
break;
}
if(m_encryptionType == EncryptionTypeSSL) {
m_state = HandShakeState;
break;
}
if(m_encryptionType == EncryptionTypeTLS) {
m_state = StartTlsState;
break;
}
}
break;
case HandShakeState:
if(responseLine == "250") {
if(!m_socket->isEncrypted() && m_encryptionType != EncryptionTypeNone) {
m_socket->startClientEncryption();
}
send("EHLO localhost");
m_state = AuthentificationState;
}
if(responseLine == "220") {
if(!m_socket->isEncrypted() && m_encryptionType != EncryptionTypeNone) {
m_socket->startClientEncryption();
}
send("EHLO localhost");
m_state = AuthentificationState;
}
if(responseLine == "220"){
if(!m_socket->isEncrypted() && m_encryptionType != EncryptionTypeNone){
m_socket->startClientEncryption();
}
send("EHLO localhost");
m_state = AuthentificationState;
}
break;
case StartTlsState:
if(responseLine == "250"){
send("STARTTLS");
m_state = HandShakeState;
}
break;
case StartTlsState:
if(responseLine == "250") {
send("STARTTLS");
m_state = HandShakeState;
}
break;
case AuthentificationState:
if(responseLine == "250") {
if(m_authMethod == AuthMethodLogin) {
send("AUTH LOGIN");
m_state = UserState;
break;
}
if(m_authMethod == AuthMethodPlain) {
send("AUTH PLAIN " + QByteArray().append((char) 0).append(m_user).append((char) 0).append(m_password).toBase64());
// if we just want to test the Login, we are almost done here
if(!m_testLogin) {
m_state = MailState;
} else {
m_state = TestLoginFinishedState;
}
break;
}
}
break;
case UserState:
if(responseLine == "334") {
send(QByteArray().append(m_user).toBase64());
m_state = PasswordState;
}
break;
case PasswordState:
if(responseLine == "334") {
send(QByteArray().append(m_password).toBase64());
// if we just want to test the Login, we are almost done here
if(!m_testLogin) {
m_state = MailState;
} else {
m_state = TestLoginFinishedState;
}
break;
}
break;
case TestLoginFinishedState:
if(responseLine == "235") {
emit testLoginFinished(true);
} else {
emit testLoginFinished(false);
}
m_socket->close();
m_testLogin = false;
break;
case MailState:
if(responseLine == "235") {
send("MAIL FROM:<" + m_sender + ">");
m_state = RcptState;
}
break;
case RcptState:
if(responseLine == "250") {
send("RCPT TO:<" + m_rcpt + ">");
m_state = DataState;
}
break;
case DataState:
if(responseLine == "250") {
send("DATA");
m_state = BodyState;
}
break;
case BodyState:
if(responseLine == "354") {
send(m_message + "\r\n.\r\n");
m_state = QuitState;
}
break;
case QuitState:
if(responseLine == "250") {
emit sendMailFinished(true, m_actionId);
send("QUIT");
m_state = CloseState;
}
break;
case CloseState:
if(responseLine == "221") {
m_socket->close();
}
// some mail server does not recognize the QUIT command...so close the connection either way
m_socket->close();
break;
default:
// unexpecterd response code received...
if(m_testLogin) {
emit testLoginFinished(false);
m_testLogin = false;
m_socket->close();
break;
}
emit sendMailFinished(false, m_actionId);
m_socket->close();
break;
}
}
bool SmtpClient::sendMail(const QString &subject, const QString &body, const ActionId &actionId)
{
m_actionId = actionId;
// create mail content
m_state = InitState;
m_message.clear();
m_message = "To: " + m_rcpt + "\n";
m_message.append("From: " + m_sender + "\n");
m_message.append("Subject: [guh notification] | " + subject + "\n");
m_message.append(body);
m_message.replace( QString::fromLatin1( "\n" ), QString::fromLatin1( "\r\n" ) );
m_message.replace( QString::fromLatin1( "\r\n.\r\n" ), QString::fromLatin1( "\r\n..\r\n" ) );
m_message.append("\r\n.\r\n");
m_socket->close();
connectToHost();
return true;
}
void SmtpClient::setHost(const QString &host)
{
m_host = host;
}
void SmtpClient::setPort(const int &port)
{
m_port = port;
}
void SmtpClient::setEncryptionType(const SmtpClient::EncryptionType &encryptionType)
{
m_encryptionType = encryptionType;
}
void SmtpClient::setAuthMethod(const SmtpClient::AuthMethod &authMethod)
{
m_authMethod = authMethod;
}
void SmtpClient::setUser(const QString &user)
{
m_user = user;
}
void SmtpClient::setPassword(const QString &password)
{
m_password = password;
}
void SmtpClient::setSender(const QString &sender)
{
m_sender = sender;
}
void SmtpClient::setRecipient(const QString &rcpt)
{
m_rcpt = rcpt;
}
void SmtpClient::socketError(QAbstractSocket::SocketError error)
{
qCWarning(dcMailNotification) << "ERROR: mail socket -> " << error << m_socket->errorString();
}
void SmtpClient::send(const QString &data)
{
m_socket->write(data.toUtf8() + "\r\n");
m_socket->flush();
}