Merge PR #109: Update mail notifications plugin
This commit is contained in:
commit
097b794549
@ -36,11 +36,6 @@
|
|||||||
|
|
||||||
\chapter Supported services
|
\chapter Supported services
|
||||||
|
|
||||||
\section2 Google Mail
|
|
||||||
With the Google Mail Notification you can send a mail with your gmail address to a recipient. The
|
|
||||||
username is your mail address (e.g. "chuck.norris@gmail.com"). The recipient will receive the notification
|
|
||||||
from your gmail account.
|
|
||||||
|
|
||||||
\section2 Yahoo Mail
|
\section2 Yahoo Mail
|
||||||
The Yahoo Mail Notification you can send a mail with your yahoo address to a recipient. The username
|
The Yahoo Mail Notification you can send a mail with your yahoo address to a recipient. The username
|
||||||
is your mail address (e.g. "chuck.norris@yahoo.com"). The recipient will receive the notification
|
is your mail address (e.g. "chuck.norris@yahoo.com"). The recipient will receive the notification
|
||||||
@ -80,62 +75,20 @@ DevicePluginMailNotification::~DevicePluginMailNotification()
|
|||||||
|
|
||||||
DeviceManager::DeviceSetupStatus DevicePluginMailNotification::setupDevice(Device *device)
|
DeviceManager::DeviceSetupStatus DevicePluginMailNotification::setupDevice(Device *device)
|
||||||
{
|
{
|
||||||
// Google mail
|
|
||||||
if(device->deviceClassId() == googleMailDeviceClassId) {
|
|
||||||
SmtpClient *smtpClient = new SmtpClient(this);
|
|
||||||
smtpClient->setHost("smtp.gmail.com");
|
|
||||||
smtpClient->setPort(465);
|
|
||||||
smtpClient->setUser(device->paramValue(googleMailDeviceUserParamTypeId).toString());
|
|
||||||
// TODO: use cryptography to save password not as plain text
|
|
||||||
smtpClient->setPassword(device->paramValue(googleMailDevicePasswordParamTypeId).toString());
|
|
||||||
smtpClient->setAuthMethod(SmtpClient::AuthMethodLogin);
|
|
||||||
smtpClient->setEncryptionType(SmtpClient::EncryptionTypeSSL);
|
|
||||||
smtpClient->setSender(device->paramValue(googleMailDeviceUserParamTypeId).toString());
|
|
||||||
smtpClient->setRecipient(device->paramValue(googleMailDeviceRecipientParamTypeId).toString());
|
|
||||||
|
|
||||||
connect(smtpClient, &SmtpClient::testLoginFinished, this, &DevicePluginMailNotification::testLoginFinished);
|
|
||||||
connect(smtpClient, &SmtpClient::sendMailFinished, this, &DevicePluginMailNotification::sendMailFinished);
|
|
||||||
m_clients.insert(smtpClient,device);
|
|
||||||
|
|
||||||
smtpClient->testLogin();
|
|
||||||
|
|
||||||
return DeviceManager::DeviceSetupStatusAsync;
|
|
||||||
}
|
|
||||||
// Yahoo mail
|
|
||||||
if(device->deviceClassId() == yahooMailDeviceClassId) {
|
|
||||||
SmtpClient *smtpClient = new SmtpClient(this);
|
|
||||||
smtpClient->setHost("smtp.mail.yahoo.com");
|
|
||||||
smtpClient->setPort(465);
|
|
||||||
smtpClient->setUser(device->paramValue(yahooMailDeviceUserParamTypeId).toString());
|
|
||||||
// TODO: use cryptography to save password not as plain text
|
|
||||||
smtpClient->setPassword(device->paramValue(yahooMailDevicePasswordParamTypeId).toString());
|
|
||||||
smtpClient->setAuthMethod(SmtpClient::AuthMethodLogin);
|
|
||||||
smtpClient->setEncryptionType(SmtpClient::EncryptionTypeSSL);
|
|
||||||
smtpClient->setSender(device->paramValue(yahooMailDeviceUserParamTypeId).toString());
|
|
||||||
smtpClient->setRecipient(device->paramValue(yahooMailDeviceRecipientParamTypeId).toString());
|
|
||||||
|
|
||||||
connect(smtpClient, &SmtpClient::testLoginFinished, this, &DevicePluginMailNotification::testLoginFinished);
|
|
||||||
connect(smtpClient, &SmtpClient::sendMailFinished, this, &DevicePluginMailNotification::sendMailFinished);
|
|
||||||
m_clients.insert(smtpClient,device);
|
|
||||||
|
|
||||||
smtpClient->testLogin();
|
|
||||||
|
|
||||||
return DeviceManager::DeviceSetupStatusAsync;
|
|
||||||
}
|
|
||||||
// Custom mail
|
// Custom mail
|
||||||
if(device->deviceClassId() == customMailDeviceClassId) {
|
if(device->deviceClassId() == customMailDeviceClassId) {
|
||||||
SmtpClient *smtpClient = new SmtpClient(this);
|
SmtpClient *smtpClient = new SmtpClient(this);
|
||||||
smtpClient->setHost(device->paramValue(customMailDeviceSmtpParamTypeId).toString());
|
smtpClient->setHost(device->paramValue(customMailDeviceSmtpParamTypeId).toString());
|
||||||
smtpClient->setPort(device->paramValue(customMailDevicePortParamTypeId).toInt());
|
smtpClient->setPort(static_cast<quint16>(device->paramValue(customMailDevicePortParamTypeId).toUInt()));
|
||||||
smtpClient->setUser(device->paramValue(customMailDeviceCustomUserParamTypeId).toString());
|
smtpClient->setUser(device->paramValue(customMailDeviceCustomUserParamTypeId).toString());
|
||||||
|
|
||||||
// TODO: use cryptography to save password not as plain text
|
// TODO: use cryptography to save password not as plain text
|
||||||
smtpClient->setPassword(device->paramValue(customMailDeviceCustomPasswordParamTypeId).toString());
|
smtpClient->setPassword(device->paramValue(customMailDeviceCustomPasswordParamTypeId).toString());
|
||||||
|
|
||||||
if(device->paramValue(customMailDeviceAuthenticationParamTypeId).toString() == "PLAIN") {
|
if(device->paramValue(customMailDeviceAuthenticationParamTypeId).toString() == "PLAIN") {
|
||||||
smtpClient->setAuthMethod(SmtpClient::AuthMethodPlain);
|
smtpClient->setAuthenticationMethod(SmtpClient::AuthenticationMethodPlain);
|
||||||
} else if(device->paramValue(customMailDeviceAuthenticationParamTypeId).toString() == "LOGIN") {
|
} else if(device->paramValue(customMailDeviceAuthenticationParamTypeId).toString() == "LOGIN") {
|
||||||
smtpClient->setAuthMethod(SmtpClient::AuthMethodLogin);
|
smtpClient->setAuthenticationMethod(SmtpClient::AuthenticationMethodLogin);
|
||||||
} else {
|
} else {
|
||||||
return DeviceManager::DeviceSetupStatusFailure;
|
return DeviceManager::DeviceSetupStatusFailure;
|
||||||
}
|
}
|
||||||
@ -150,7 +103,10 @@ DeviceManager::DeviceSetupStatus DevicePluginMailNotification::setupDevice(Devic
|
|||||||
return DeviceManager::DeviceSetupStatusFailure;
|
return DeviceManager::DeviceSetupStatusFailure;
|
||||||
}
|
}
|
||||||
|
|
||||||
smtpClient->setRecipient(device->paramValue(customMailDeviceCustomRecipientParamTypeId).toString());
|
QString recipientsString = device->paramValue(customMailDeviceCustomRecipientParamTypeId).toString();
|
||||||
|
QStringList recipients = recipientsString.split(",");
|
||||||
|
|
||||||
|
smtpClient->setRecipients(recipients);
|
||||||
smtpClient->setSender(device->paramValue(customMailDeviceCustomSenderParamTypeId).toString());
|
smtpClient->setSender(device->paramValue(customMailDeviceCustomSenderParamTypeId).toString());
|
||||||
|
|
||||||
connect(smtpClient, &SmtpClient::testLoginFinished, this, &DevicePluginMailNotification::testLoginFinished);
|
connect(smtpClient, &SmtpClient::testLoginFinished, this, &DevicePluginMailNotification::testLoginFinished);
|
||||||
@ -166,12 +122,22 @@ DeviceManager::DeviceSetupStatus DevicePluginMailNotification::setupDevice(Devic
|
|||||||
|
|
||||||
DeviceManager::DeviceError DevicePluginMailNotification::executeAction(Device *device, const Action &action)
|
DeviceManager::DeviceError DevicePluginMailNotification::executeAction(Device *device, const Action &action)
|
||||||
{
|
{
|
||||||
if(action.actionTypeId() == googleMailSendMailActionTypeId) {
|
if (device->deviceClassId() == customMailDeviceClassId) {
|
||||||
SmtpClient *smtpClient = m_clients.key(device);
|
if(action.actionTypeId() == customMailNotifyActionTypeId) {
|
||||||
smtpClient->sendMail(action.param(googleMailSendMailActionSubjectParamTypeId).value().toString(), action.param(googleMailSendMailActionBodyParamTypeId).value().toString(), action.id());
|
SmtpClient *smtpClient = m_clients.key(device);
|
||||||
return DeviceManager::DeviceErrorAsync;
|
if (!smtpClient) {
|
||||||
|
qCWarning(dcMailNotification()) << "Could not find SMTP client for " << device;
|
||||||
|
return DeviceManager::DeviceErrorHardwareNotAvailable;
|
||||||
|
}
|
||||||
|
|
||||||
|
smtpClient->sendMail(action.param(customMailNotifyActionTitleParamTypeId).value().toString(),
|
||||||
|
action.param(customMailNotifyActionBodyParamTypeId).value().toString(),
|
||||||
|
action.id());
|
||||||
|
return DeviceManager::DeviceErrorAsync;
|
||||||
|
}
|
||||||
|
return DeviceManager::DeviceErrorActionTypeNotFound;
|
||||||
}
|
}
|
||||||
return DeviceManager::DeviceErrorActionTypeNotFound;
|
return DeviceManager::DeviceErrorDeviceClassNotFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DevicePluginMailNotification::deviceRemoved(Device *device)
|
void DevicePluginMailNotification::deviceRemoved(Device *device)
|
||||||
@ -185,9 +151,11 @@ void DevicePluginMailNotification::testLoginFinished(const bool &success)
|
|||||||
{
|
{
|
||||||
SmtpClient *smtpClient = static_cast<SmtpClient*>(sender());
|
SmtpClient *smtpClient = static_cast<SmtpClient*>(sender());
|
||||||
Device *device = m_clients.value(smtpClient);
|
Device *device = m_clients.value(smtpClient);
|
||||||
if(success) {
|
if (success) {
|
||||||
|
qCDebug(dcMailNotification()) << "Email login test successfull";
|
||||||
emit deviceSetupFinished(device, DeviceManager::DeviceSetupStatusSuccess);
|
emit deviceSetupFinished(device, DeviceManager::DeviceSetupStatusSuccess);
|
||||||
} else {
|
} else {
|
||||||
|
qCWarning(dcMailNotification()) << "Email login test failed";
|
||||||
emit deviceSetupFinished(device, DeviceManager::DeviceSetupStatusFailure);
|
emit deviceSetupFinished(device, DeviceManager::DeviceSetupStatusFailure);
|
||||||
if(m_clients.contains(smtpClient)) {
|
if(m_clients.contains(smtpClient)) {
|
||||||
m_clients.remove(smtpClient);
|
m_clients.remove(smtpClient);
|
||||||
@ -198,9 +166,11 @@ void DevicePluginMailNotification::testLoginFinished(const bool &success)
|
|||||||
|
|
||||||
void DevicePluginMailNotification::sendMailFinished(const bool &success, const ActionId &actionId)
|
void DevicePluginMailNotification::sendMailFinished(const bool &success, const ActionId &actionId)
|
||||||
{
|
{
|
||||||
if(success) {
|
if (success) {
|
||||||
|
qCDebug(dcMailNotification()) << "Email sent successfully";
|
||||||
emit actionExecutionFinished(actionId, DeviceManager::DeviceErrorNoError);
|
emit actionExecutionFinished(actionId, DeviceManager::DeviceErrorNoError);
|
||||||
} else {
|
} else {
|
||||||
|
qCWarning(dcMailNotification()) << "Email sending failed";
|
||||||
emit actionExecutionFinished(actionId, DeviceManager::DeviceErrorDeviceNotFound);
|
emit actionExecutionFinished(actionId, DeviceManager::DeviceErrorDeviceNotFound);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,33 +12,34 @@
|
|||||||
"id": "f4844c97-7ca6-4349-904e-ff9749a9fe74",
|
"id": "f4844c97-7ca6-4349-904e-ff9749a9fe74",
|
||||||
"name": "customMail",
|
"name": "customMail",
|
||||||
"displayName": "Custom mail",
|
"displayName": "Custom mail",
|
||||||
"createMethods": ["user"],
|
"createMethods": [ "user" ],
|
||||||
|
"interfaces": [ "notifications" ],
|
||||||
"paramTypes": [
|
"paramTypes": [
|
||||||
{
|
{
|
||||||
"id": "af30ce7b-fb6b-42f0-889d-20b32f8b8fa4",
|
"id": "af30ce7b-fb6b-42f0-889d-20b32f8b8fa4",
|
||||||
"name": "customSender",
|
"name": "customSender",
|
||||||
"displayName": "sender mail",
|
"displayName": "Sender mail",
|
||||||
"type": "QString",
|
"type": "QString",
|
||||||
"inputType": "Mail"
|
"inputType": "Mail"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "b91d0ecc-6903-4991-ae8d-f36757ce40a7",
|
"id": "b91d0ecc-6903-4991-ae8d-f36757ce40a7",
|
||||||
"name": "customUser",
|
"name": "customUser",
|
||||||
"displayName": "user",
|
"displayName": "User",
|
||||||
"type": "QString",
|
"type": "QString",
|
||||||
"inputType": "TextLine"
|
"inputType": "TextLine"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "ac29e643-1d18-4612-8d2f-65fb07a67182",
|
"id": "ac29e643-1d18-4612-8d2f-65fb07a67182",
|
||||||
"name": "customPassword",
|
"name": "customPassword",
|
||||||
"displayName": "password",
|
"displayName": "Password",
|
||||||
"type": "QString",
|
"type": "QString",
|
||||||
"inputType": "Password"
|
"inputType": "Password"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "d657f002-9741-42e1-9fef-32eae96dacdb",
|
"id": "d657f002-9741-42e1-9fef-32eae96dacdb",
|
||||||
"name": "customRecipient",
|
"name": "customRecipient",
|
||||||
"displayName": "recipient",
|
"displayName": "Recipient",
|
||||||
"type": "QString",
|
"type": "QString",
|
||||||
"inputType": "Mail"
|
"inputType": "Mail"
|
||||||
},
|
},
|
||||||
@ -52,9 +53,9 @@
|
|||||||
{
|
{
|
||||||
"id": "56ec204f-2e02-4a17-b9d1-e855e384b689",
|
"id": "56ec204f-2e02-4a17-b9d1-e855e384b689",
|
||||||
"name": "port",
|
"name": "port",
|
||||||
"displayName": "port",
|
"displayName": "Port",
|
||||||
"type": "int",
|
"type": "int",
|
||||||
"defaultValue": "465"
|
"defaultValue": 25
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "789b963b-4143-4e21-853c-2612707d726f",
|
"id": "789b963b-4143-4e21-853c-2612707d726f",
|
||||||
@ -75,130 +76,12 @@
|
|||||||
"actionTypes": [
|
"actionTypes": [
|
||||||
{
|
{
|
||||||
"id": "054613b0-3666-4dad-9252-e0ebca187edc",
|
"id": "054613b0-3666-4dad-9252-e0ebca187edc",
|
||||||
"name": "send",
|
"name": "notify",
|
||||||
"displayName": "send mail",
|
"displayName": "send mail",
|
||||||
"paramTypes": [
|
"paramTypes": [
|
||||||
{
|
{
|
||||||
"id": "2047e0f4-3d34-4214-bc8f-9ab741ae6006",
|
"id": "2047e0f4-3d34-4214-bc8f-9ab741ae6006",
|
||||||
"name": "subject",
|
"name": "title",
|
||||||
"displayName": "subject",
|
|
||||||
"type": "QString",
|
|
||||||
"inputType": "TextLine"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "aeb6e79e-9862-43e1-9873-cbdce549344a",
|
|
||||||
"name": "body",
|
|
||||||
"displayName": "body",
|
|
||||||
"type": "QString",
|
|
||||||
"inputType": "TextArea"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "google",
|
|
||||||
"displayName": "Google",
|
|
||||||
"id": "d02399c5-8e79-40be-8cf6-e00b55bbfe7c",
|
|
||||||
"deviceClasses": [
|
|
||||||
{
|
|
||||||
"id": "3869884a-1592-4b8f-84a7-994be18ff555",
|
|
||||||
"name": "googleMail",
|
|
||||||
"displayName": "Google mail",
|
|
||||||
"createMethods": ["user"],
|
|
||||||
"paramTypes": [
|
|
||||||
{
|
|
||||||
"id": "0a4ea3ff-ea76-4a5f-adbb-b8f79faa2156",
|
|
||||||
"name": "user",
|
|
||||||
"displayName": "user",
|
|
||||||
"type": "QString",
|
|
||||||
"inputType": "Mail"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "f63f6486-5340-472a-b37c-be828111725c",
|
|
||||||
"name": "password",
|
|
||||||
"displayName": "password",
|
|
||||||
"type": "QString",
|
|
||||||
"inputType": "Password"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "76697fe2-3393-4ed0-a15d-9d041502cfd3",
|
|
||||||
"name": "recipient",
|
|
||||||
"displayName": "recipient",
|
|
||||||
"type": "QString",
|
|
||||||
"inputType": "Mail"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"actionTypes": [
|
|
||||||
{
|
|
||||||
"id": "054613b0-3666-4dad-9252-e0ebca187edc",
|
|
||||||
"name": "sendMail",
|
|
||||||
"displayName": "send mail",
|
|
||||||
"paramTypes": [
|
|
||||||
{
|
|
||||||
"id": "2047e0f4-3d34-4214-bc8f-9ab741ae6006",
|
|
||||||
"name": "subject",
|
|
||||||
"displayName": "subject",
|
|
||||||
"type": "QString",
|
|
||||||
"inputType": "TextLine"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "aeb6e79e-9862-43e1-9873-cbdce549344a",
|
|
||||||
"name": "body",
|
|
||||||
"displayName": "body",
|
|
||||||
"type": "QString",
|
|
||||||
"inputType": "TextArea"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "yahoo",
|
|
||||||
"displayName": "Yahoo",
|
|
||||||
"id": "5eb3e1e9-25a7-4740-806e-5cfc836e4bf5",
|
|
||||||
"deviceClasses": [
|
|
||||||
{
|
|
||||||
"id": "59409e8f-0c83-414f-abd5-bbbf2758acba",
|
|
||||||
"name": "yahooMail",
|
|
||||||
"displayName": "Yahoo mail",
|
|
||||||
"createMethods": ["user"],
|
|
||||||
"paramTypes": [
|
|
||||||
{
|
|
||||||
"id": "0a4ea3ff-ea76-4a5f-adbb-b8f79faa2156",
|
|
||||||
"name": "user",
|
|
||||||
"displayName": "user",
|
|
||||||
"type": "QString",
|
|
||||||
"inputType": "Mail"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "f63f6486-5340-472a-b37c-be828111725c",
|
|
||||||
"name": "password",
|
|
||||||
"displayName": "password",
|
|
||||||
"type": "QString",
|
|
||||||
"inputType": "Password"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "76697fe2-3393-4ed0-a15d-9d041502cfd3",
|
|
||||||
"name": "recipient",
|
|
||||||
"displayName": "recipient",
|
|
||||||
"type": "QString",
|
|
||||||
"inputType": "Mail"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"actionTypes": [
|
|
||||||
{
|
|
||||||
"id": "054613b0-3666-4dad-9252-e0ebca187edc",
|
|
||||||
"name": "send",
|
|
||||||
"displayName": "send mail",
|
|
||||||
"paramTypes": [
|
|
||||||
{
|
|
||||||
"id": "2047e0f4-3d34-4214-bc8f-9ab741ae6006",
|
|
||||||
"name": "subject",
|
|
||||||
"displayName": "subject",
|
"displayName": "subject",
|
||||||
"type": "QString",
|
"type": "QString",
|
||||||
"inputType": "TextLine"
|
"inputType": "TextLine"
|
||||||
|
|||||||
@ -23,222 +23,94 @@
|
|||||||
#include "smtpclient.h"
|
#include "smtpclient.h"
|
||||||
#include "extern-plugininfo.h"
|
#include "extern-plugininfo.h"
|
||||||
|
|
||||||
|
#include <QDateTime>
|
||||||
|
|
||||||
|
Q_LOGGING_CATEGORY(dcSmtpClient, "SmtpClient")
|
||||||
|
|
||||||
SmtpClient::SmtpClient(QObject *parent):
|
SmtpClient::SmtpClient(QObject *parent):
|
||||||
QObject(parent)
|
QObject(parent)
|
||||||
{
|
{
|
||||||
m_socket = new QSslSocket(this);
|
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::connected, this, &SmtpClient::connected);
|
||||||
connect(m_socket, &QSslSocket::readyRead, this, &SmtpClient::readData);
|
connect(m_socket, &QSslSocket::readyRead, this, &SmtpClient::readData);
|
||||||
connect(m_socket, &QSslSocket::disconnected, this, &SmtpClient::disconnected);
|
connect(m_socket, &QSslSocket::disconnected, this, &SmtpClient::disconnected);
|
||||||
|
connect(m_socket, &QSslSocket::encrypted, this, &SmtpClient::onEncrypted);
|
||||||
|
connect(m_socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onSocketError(QAbstractSocket::SocketError)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SmtpClient::connectToHost()
|
void SmtpClient::connectToHost()
|
||||||
{
|
{
|
||||||
switch (m_encryptionType) {
|
switch (m_encryptionType) {
|
||||||
case EncryptionTypeNone:
|
case EncryptionTypeNone:
|
||||||
|
case EncryptionTypeTLS:
|
||||||
|
// Note: the handshake will be done later, not from the beginning
|
||||||
m_socket->connectToHost(m_host, m_port);
|
m_socket->connectToHost(m_host, m_port);
|
||||||
break;
|
break;
|
||||||
case EncryptionTypeSSL:
|
case EncryptionTypeSSL:
|
||||||
m_socket->connectToHostEncrypted(m_host, m_port);
|
m_socket->connectToHostEncrypted(m_host, m_port);
|
||||||
break;
|
break;
|
||||||
case EncryptionTypeTLS:
|
|
||||||
m_socket->connectToHost(m_host,m_port);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SmtpClient::testLogin()
|
void SmtpClient::testLogin()
|
||||||
{
|
{
|
||||||
m_socket->close();
|
|
||||||
m_testLogin = true;
|
m_testLogin = true;
|
||||||
|
setState(StateInitialize);
|
||||||
|
m_socket->close();
|
||||||
connectToHost();
|
connectToHost();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SmtpClient::connected()
|
void SmtpClient::connected()
|
||||||
{
|
{
|
||||||
|
qCDebug(dcSmtpClient()) << "Connected";
|
||||||
}
|
}
|
||||||
|
|
||||||
void SmtpClient::disconnected()
|
void SmtpClient::disconnected()
|
||||||
{
|
{
|
||||||
|
qCDebug(dcSmtpClient()) << "Disconnected";
|
||||||
|
setState(StateIdle);
|
||||||
|
sendNextMail();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmtpClient::onEncrypted()
|
||||||
|
{
|
||||||
|
qCDebug(dcSmtpClient()) << "Socket encrypted";
|
||||||
|
send("EHLO localhost");
|
||||||
|
setState(StateAuthentification);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SmtpClient::readData()
|
void SmtpClient::readData()
|
||||||
{
|
{
|
||||||
QString response;
|
while(m_socket->canReadLine()) {
|
||||||
QString responseLine;
|
QString responseLine;
|
||||||
|
|
||||||
while(m_socket->canReadLine() && responseLine[3] != ' ') {
|
|
||||||
responseLine = m_socket->readLine();
|
responseLine = m_socket->readLine();
|
||||||
response.append(responseLine);
|
|
||||||
}
|
|
||||||
responseLine.truncate( 3 );
|
|
||||||
|
|
||||||
switch (m_state) {
|
qCDebug(dcSmtpClient()) << "<--" << responseLine;
|
||||||
case InitState:
|
|
||||||
if(responseLine == "220") {
|
bool responseCodeParseSuccess = false;
|
||||||
send("EHLO localhost");
|
int responseCode = responseLine.left(3).toInt(&responseCodeParseSuccess);
|
||||||
if(m_encryptionType == EncryptionTypeNone) {
|
if (!responseCodeParseSuccess) {
|
||||||
m_state = AuthentificationState;
|
qCWarning(dcSmtpClient()) << "Could not convert status code to a valid integer" << responseLine;
|
||||||
break;
|
if (m_state != StateIdle) {
|
||||||
|
handleSmtpFailure();
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
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;
|
|
||||||
}
|
|
||||||
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 {
|
} else {
|
||||||
emit testLoginFinished(false);
|
processServerResponse(responseCode, responseLine);
|
||||||
}
|
}
|
||||||
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)
|
void SmtpClient::sendMail(const QString &subject, const QString &body, const ActionId &actionId)
|
||||||
{
|
{
|
||||||
m_actionId = actionId;
|
Message message;
|
||||||
|
message.subject = subject;
|
||||||
|
message.body = body;
|
||||||
|
message.actionId = actionId;
|
||||||
|
|
||||||
// create mail content
|
m_messageQueue.enqueue(message);
|
||||||
m_state = InitState;
|
sendNextMail();
|
||||||
m_message.clear();
|
|
||||||
|
|
||||||
m_message = "To: " + m_rcpt + "\n";
|
|
||||||
m_message.append("From: " + m_sender + "\n");
|
|
||||||
m_message.append("Subject: [nymea 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)
|
void SmtpClient::setHost(const QString &host)
|
||||||
@ -246,7 +118,7 @@ void SmtpClient::setHost(const QString &host)
|
|||||||
m_host = host;
|
m_host = host;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SmtpClient::setPort(const int &port)
|
void SmtpClient::setPort(const quint16 &port)
|
||||||
{
|
{
|
||||||
m_port = port;
|
m_port = port;
|
||||||
}
|
}
|
||||||
@ -256,9 +128,9 @@ void SmtpClient::setEncryptionType(const SmtpClient::EncryptionType &encryptionT
|
|||||||
m_encryptionType = encryptionType;
|
m_encryptionType = encryptionType;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SmtpClient::setAuthMethod(const SmtpClient::AuthMethod &authMethod)
|
void SmtpClient::setAuthenticationMethod(const SmtpClient::AuthenticationMethod &authenticationMethod)
|
||||||
{
|
{
|
||||||
m_authMethod = authMethod;
|
m_authenticationMethod = authenticationMethod;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SmtpClient::setUser(const QString &user)
|
void SmtpClient::setUser(const QString &user)
|
||||||
@ -276,18 +148,297 @@ void SmtpClient::setSender(const QString &sender)
|
|||||||
m_sender = sender;
|
m_sender = sender;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SmtpClient::setRecipient(const QString &rcpt)
|
void SmtpClient::setRecipients(const QStringList &recipients)
|
||||||
{
|
{
|
||||||
m_rcpt = rcpt;
|
m_recipients = recipients;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SmtpClient::socketError(QAbstractSocket::SocketError error)
|
QString SmtpClient::createDateString()
|
||||||
{
|
{
|
||||||
qCWarning(dcMailNotification) << "Mail socket -> " << error << m_socket->errorString();
|
return QDateTime::currentDateTime().toString(Qt::RFC2822Date);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmtpClient::setState(SmtpClient::State state)
|
||||||
|
{
|
||||||
|
if (m_state == state)
|
||||||
|
return;
|
||||||
|
|
||||||
|
qCDebug(dcSmtpClient()) << state;
|
||||||
|
m_state = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmtpClient::processServerResponse(int responseCode, const QString &response)
|
||||||
|
{
|
||||||
|
switch (m_state) {
|
||||||
|
case StateIdle:
|
||||||
|
// Check if we have to send an other email, otherwise we are done and remain in idle
|
||||||
|
sendNextMail();
|
||||||
|
break;
|
||||||
|
case StateInitialize:
|
||||||
|
if (responseCode == 220) {
|
||||||
|
send("EHLO localhost");
|
||||||
|
|
||||||
|
if (m_encryptionType == EncryptionTypeNone) {
|
||||||
|
setState(StateAuthentification);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_encryptionType == EncryptionTypeSSL) {
|
||||||
|
setState(StateHandShake);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_encryptionType == EncryptionTypeTLS) {
|
||||||
|
setState(StateStartTls);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case StateHandShake:
|
||||||
|
// Ignore server information messages
|
||||||
|
if (responseCode == 250) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We need a 220 befor continue
|
||||||
|
if (responseCode == 220) {
|
||||||
|
if (!m_socket->isEncrypted() && m_encryptionType != EncryptionTypeNone) {
|
||||||
|
qCDebug(dcSmtpClient()) << "Start client encryption...";
|
||||||
|
m_socket->startClientEncryption();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
handleUnexpectedSmtpCode(responseCode, response);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case StateStartTls:
|
||||||
|
// Ignore server information messages until we get a '250 ...' instead of '250-....'
|
||||||
|
if (responseCode == 250 && response.at(3) != ' ') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (responseCode == 250) {
|
||||||
|
send("STARTTLS");
|
||||||
|
setState(StateHandShake);
|
||||||
|
} else {
|
||||||
|
handleUnexpectedSmtpCode(responseCode, response);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case StateAuthentification:
|
||||||
|
// Ignore server information messages until we get a '250 ...' instead of '250-....'
|
||||||
|
if (responseCode == 250 && response.at(3) != ' ') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (responseCode == 250) {
|
||||||
|
if (m_authenticationMethod == AuthenticationMethodLogin) {
|
||||||
|
send("AUTH LOGIN");
|
||||||
|
setState(StateUser);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_authenticationMethod == AuthenticationMethodPlain) {
|
||||||
|
send("AUTH PLAIN " + QByteArray().append(static_cast<char>(0))
|
||||||
|
.append(m_user)
|
||||||
|
.append(static_cast<char>(0))
|
||||||
|
.append(m_password)
|
||||||
|
.toBase64());
|
||||||
|
|
||||||
|
// If we just want to test the Login, we are almost done here
|
||||||
|
if (!m_testLogin) {
|
||||||
|
setState(StateMail);
|
||||||
|
} else {
|
||||||
|
setState(StateTestLoginFinished);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
handleUnexpectedSmtpCode(responseCode, response);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case StateUser:
|
||||||
|
if (responseCode == 334) {
|
||||||
|
send(QByteArray().append(m_user).toBase64());
|
||||||
|
setState(StatePassword);
|
||||||
|
} else {
|
||||||
|
handleUnexpectedSmtpCode(responseCode, response);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case StatePassword:
|
||||||
|
if (responseCode == 334) {
|
||||||
|
send(QByteArray().append(m_password).toBase64());
|
||||||
|
// if we just want to test the Login, we are almost done here
|
||||||
|
if (!m_testLogin) {
|
||||||
|
setState(StateMail);
|
||||||
|
} else {
|
||||||
|
setState(StateTestLoginFinished);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
handleUnexpectedSmtpCode(responseCode, response);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case StateTestLoginFinished:
|
||||||
|
if (responseCode == 235) {
|
||||||
|
emit testLoginFinished(true);
|
||||||
|
} else {
|
||||||
|
emit testLoginFinished(false);
|
||||||
|
}
|
||||||
|
m_socket->close();
|
||||||
|
m_testLogin = false;
|
||||||
|
break;
|
||||||
|
case StateMail:
|
||||||
|
if (responseCode == 235) {
|
||||||
|
send("MAIL FROM:<" + m_sender + ">");
|
||||||
|
|
||||||
|
// Prepare queue for recipients
|
||||||
|
m_recipientsQueue.clear();
|
||||||
|
qCDebug(dcSmtpClient()) << "Prepare recipients list" << m_recipients;
|
||||||
|
foreach (const QString &recipient, m_recipients) {
|
||||||
|
m_recipientsQueue.enqueue(recipient.trimmed());
|
||||||
|
}
|
||||||
|
setState(StateRcpt);
|
||||||
|
} else {
|
||||||
|
handleUnexpectedSmtpCode(responseCode, response);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case StateRcpt:
|
||||||
|
// Ignore server information messages until we get a '250 ...' instead of '250-....'
|
||||||
|
if (responseCode == 250 && response.at(3) != ' ') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (responseCode == 250) {
|
||||||
|
send("RCPT TO:<" + m_recipientsQueue.dequeue() + ">");
|
||||||
|
|
||||||
|
if (m_recipientsQueue.isEmpty()) {
|
||||||
|
setState(StateData);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
handleUnexpectedSmtpCode(responseCode, response);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case StateData:
|
||||||
|
// Ignore server information messages until we get a '250 ...' instead of '250-....'
|
||||||
|
if (responseCode == 250 && response.at(3) != ' ') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (responseCode == 250) {
|
||||||
|
send("DATA");
|
||||||
|
setState(StateBody);
|
||||||
|
} else {
|
||||||
|
handleUnexpectedSmtpCode(responseCode, response);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case StateBody:
|
||||||
|
if (responseCode == 354) {
|
||||||
|
send(m_messageData + "\r\n.\r\n");
|
||||||
|
setState(StateQuit);
|
||||||
|
} else {
|
||||||
|
handleUnexpectedSmtpCode(responseCode, response);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case StateQuit:
|
||||||
|
// Ignore server information messages until we get a '250 ...' instead of '250-....'
|
||||||
|
if (responseCode == 250 && response.at(3) != ' ') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (responseCode == 250) {
|
||||||
|
emit sendMailFinished(true, m_message.actionId);
|
||||||
|
send("QUIT");
|
||||||
|
setState(StateClose);
|
||||||
|
} else {
|
||||||
|
handleUnexpectedSmtpCode(responseCode, response);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case StateClose:
|
||||||
|
if (responseCode == 221) {
|
||||||
|
m_socket->close();
|
||||||
|
} else {
|
||||||
|
qCDebug(dcSmtpClient()) << "The server does not handle the QUIT command. This is ok, we close the socket either way.";
|
||||||
|
}
|
||||||
|
|
||||||
|
// some mail server does not recognize the QUIT command...so close the connection either way
|
||||||
|
m_socket->close();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmtpClient::sendNextMail()
|
||||||
|
{
|
||||||
|
// Check if there is a mail left to send
|
||||||
|
if (m_messageQueue.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Check if busy
|
||||||
|
if (m_state != StateIdle)
|
||||||
|
return;
|
||||||
|
|
||||||
|
sendEmailInternally(m_messageQueue.dequeue());
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmtpClient::sendEmailInternally(const Message &message)
|
||||||
|
{
|
||||||
|
qCDebug(dcMailNotification()) << "Start sending message" << message.subject << message.body;
|
||||||
|
|
||||||
|
// Initialize data for sending
|
||||||
|
m_message = message;
|
||||||
|
m_messageData.clear();
|
||||||
|
|
||||||
|
// Create plain message content
|
||||||
|
m_messageData = "To: " + m_recipients.join(",") + "\r\n";
|
||||||
|
m_messageData.append("From: " + m_sender + "\r\n");
|
||||||
|
m_messageData.append("Subject: " + message.subject + "\r\n");
|
||||||
|
m_messageData.append("Date: " + createDateString() + "\r\n");
|
||||||
|
m_messageData.append("Content-Type: text/plain; charset=\"UTF-8\"\r\n");
|
||||||
|
m_messageData.append("Content-Transfer-Encoding: quoted-printable\r\n");
|
||||||
|
m_messageData.append("MIME-Version: 1.0\r\n");
|
||||||
|
m_messageData.append("X-Mailer: nymea;\r\n");
|
||||||
|
m_messageData.append("\r\n");
|
||||||
|
m_messageData.append(message.body);
|
||||||
|
m_messageData.append("\r\n.\r\n");
|
||||||
|
|
||||||
|
setState(StateInitialize);
|
||||||
|
|
||||||
|
// Make sure the connection starts from the beginning
|
||||||
|
m_socket->close();
|
||||||
|
connectToHost();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmtpClient::handleSmtpFailure()
|
||||||
|
{
|
||||||
|
if (m_testLogin) {
|
||||||
|
emit testLoginFinished(false);
|
||||||
|
} else {
|
||||||
|
emit sendMailFinished(false, m_message.actionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up
|
||||||
|
m_socket->close();
|
||||||
|
m_messageData.clear();
|
||||||
|
m_testLogin = false;
|
||||||
|
|
||||||
|
// Set idle state (handles the queue)
|
||||||
|
setState(StateIdle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmtpClient::handleUnexpectedSmtpCode(int responseCode, const QString &serverMessage)
|
||||||
|
{
|
||||||
|
qCWarning(dcMailNotification()) << "Received unexpected error code from smtp server" << responseCode << serverMessage;
|
||||||
|
handleSmtpFailure();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmtpClient::onSocketError(QAbstractSocket::SocketError error)
|
||||||
|
{
|
||||||
|
qCWarning(dcMailNotification()) << "Mail socket error" << error << m_socket->errorString();
|
||||||
|
if (m_state != StateIdle) {
|
||||||
|
handleSmtpFailure();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SmtpClient::send(const QString &data)
|
void SmtpClient::send(const QString &data)
|
||||||
{
|
{
|
||||||
|
qCDebug(dcSmtpClient()) << "-->" << data;
|
||||||
m_socket->write(data.toUtf8() + "\r\n");
|
m_socket->write(data.toUtf8() + "\r\n");
|
||||||
m_socket->flush();
|
m_socket->flush();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,87 +23,119 @@
|
|||||||
#ifndef SMTPCLIENT_H
|
#ifndef SMTPCLIENT_H
|
||||||
#define SMTPCLIENT_H
|
#define SMTPCLIENT_H
|
||||||
|
|
||||||
#include <QObject>
|
#include <QQueue>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include <QObject>
|
||||||
#include <QTcpSocket>
|
#include <QTcpSocket>
|
||||||
#include <QSslSocket>
|
#include <QSslSocket>
|
||||||
|
#include <QStringList>
|
||||||
|
#include <QLoggingCategory>
|
||||||
|
|
||||||
#include "plugin/deviceplugin.h"
|
#include "plugin/deviceplugin.h"
|
||||||
|
|
||||||
|
Q_DECLARE_LOGGING_CATEGORY(dcSmtpClient)
|
||||||
|
|
||||||
|
struct Message {
|
||||||
|
QString subject;
|
||||||
|
QString body;
|
||||||
|
ActionId actionId;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class SmtpClient : public QObject
|
class SmtpClient : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
|
|
||||||
enum AuthMethod{
|
enum AuthenticationMethod{
|
||||||
AuthMethodPlain,
|
AuthenticationMethodPlain,
|
||||||
AuthMethodLogin
|
AuthenticationMethodLogin
|
||||||
};
|
};
|
||||||
|
Q_ENUM(AuthenticationMethod)
|
||||||
|
|
||||||
enum SendState{
|
enum State{
|
||||||
InitState,
|
StateIdle,
|
||||||
HandShakeState,
|
StateInitialize,
|
||||||
AuthentificationState,
|
StateHandShake,
|
||||||
StartTlsState,
|
StateAuthentification,
|
||||||
UserState,
|
StateStartTls,
|
||||||
PasswordState,
|
StateUser,
|
||||||
TestLoginFinishedState,
|
StatePassword,
|
||||||
MailState,
|
StateTestLoginFinished,
|
||||||
RcptState,
|
StateMail,
|
||||||
DataState,
|
StateRcpt,
|
||||||
BodyState,
|
StateData,
|
||||||
QuitState,
|
StateBody,
|
||||||
CloseState
|
StateQuit,
|
||||||
|
StateClose
|
||||||
};
|
};
|
||||||
|
Q_ENUM(State)
|
||||||
|
|
||||||
enum EncryptionType{
|
enum EncryptionType{
|
||||||
EncryptionTypeNone,
|
EncryptionTypeNone,
|
||||||
EncryptionTypeSSL,
|
EncryptionTypeSSL,
|
||||||
EncryptionTypeTLS
|
EncryptionTypeTLS
|
||||||
};
|
};
|
||||||
|
Q_ENUM(EncryptionType)
|
||||||
|
|
||||||
explicit SmtpClient(QObject *parent = 0);
|
explicit SmtpClient(QObject *parent = nullptr);
|
||||||
|
|
||||||
void connectToHost();
|
void connectToHost();
|
||||||
void testLogin();
|
void testLogin();
|
||||||
bool sendMail(const QString &subject, const QString &body, const ActionId &actionId);
|
void sendMail(const QString &subject, const QString &body, const ActionId &actionId);
|
||||||
|
|
||||||
void setHost(const QString &host);
|
void setHost(const QString &host);
|
||||||
void setPort(const int &port);
|
void setPort(const quint16 &port);
|
||||||
void setEncryptionType(const EncryptionType &encryptionType);
|
void setEncryptionType(const EncryptionType &encryptionType);
|
||||||
void setAuthMethod(const AuthMethod &authMethod);
|
void setAuthenticationMethod(const AuthenticationMethod &authenticationMethod);
|
||||||
void setUser(const QString &user);
|
void setUser(const QString &user);
|
||||||
void setPassword(const QString &password);
|
void setPassword(const QString &password);
|
||||||
void setSender(const QString &sender);
|
void setSender(const QString &sender);
|
||||||
void setRecipient(const QString &rcpt);
|
void setRecipients(const QStringList &recipients);
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QSslSocket *m_socket;
|
QSslSocket *m_socket = nullptr;
|
||||||
SendState m_state;
|
State m_state = StateIdle;
|
||||||
QString m_host;
|
QString m_host = "127.0.0.1";
|
||||||
int m_port;
|
quint16 m_port = 25;
|
||||||
|
|
||||||
QString m_user;
|
QString m_user;
|
||||||
QString m_password;
|
QString m_password;
|
||||||
QString m_sender;
|
QString m_sender;
|
||||||
AuthMethod m_authMethod;
|
AuthenticationMethod m_authenticationMethod;
|
||||||
EncryptionType m_encryptionType;
|
EncryptionType m_encryptionType;
|
||||||
QString m_rcpt;
|
QStringList m_recipients;
|
||||||
QString m_subject;
|
QQueue<QString> m_recipientsQueue;
|
||||||
QString m_boy;
|
|
||||||
QString m_message;
|
|
||||||
ActionId m_actionId;
|
|
||||||
|
|
||||||
bool m_testLogin;
|
// Created for each message
|
||||||
|
Message m_message;
|
||||||
|
QString m_messageData;
|
||||||
|
|
||||||
|
QQueue<Message> m_messageQueue;
|
||||||
|
|
||||||
|
bool m_testLogin = false;
|
||||||
|
|
||||||
|
QString createDateString();
|
||||||
|
void setState(State state);
|
||||||
|
|
||||||
|
void processServerResponse(int responseCode, const QString &response);
|
||||||
|
|
||||||
|
void sendNextMail();
|
||||||
|
void sendEmailInternally(const Message &message);
|
||||||
|
|
||||||
|
void handleSmtpFailure();
|
||||||
|
void handleUnexpectedSmtpCode(int responseCode, const QString &serverMessage);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void sendMailFinished(const bool &success, const ActionId &actionId);
|
void sendMailFinished(const bool &success, const ActionId &actionId);
|
||||||
void testLoginFinished(const bool &success);
|
void testLoginFinished(const bool &success);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void socketError(QAbstractSocket::SocketError error);
|
|
||||||
|
void onSocketError(QAbstractSocket::SocketError error);
|
||||||
void connected();
|
void connected();
|
||||||
void disconnected();
|
void disconnected();
|
||||||
|
void onEncrypted();
|
||||||
void readData();
|
void readData();
|
||||||
void send(const QString &data);
|
void send(const QString &data);
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user