Clean up email notification plugin and prepare for improvement

This commit is contained in:
Simon Stürz 2019-04-29 16:31:57 +02:00
parent e6347ba0a9
commit 4b11f1b481
4 changed files with 77 additions and 225 deletions

View File

@ -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,48 +75,6 @@ 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);
@ -133,9 +86,9 @@ DeviceManager::DeviceSetupStatus DevicePluginMailNotification::setupDevice(Devic
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;
} }
@ -166,13 +119,23 @@ 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) {
if(action.actionTypeId() == customMailNotifyActionTypeId) {
SmtpClient *smtpClient = m_clients.key(device); SmtpClient *smtpClient = m_clients.key(device);
smtpClient->sendMail(action.param(googleMailSendMailActionSubjectParamTypeId).value().toString(), action.param(googleMailSendMailActionBodyParamTypeId).value().toString(), action.id()); 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::DeviceErrorAsync;
} }
return DeviceManager::DeviceErrorActionTypeNotFound; return DeviceManager::DeviceErrorActionTypeNotFound;
} }
return DeviceManager::DeviceErrorDeviceClassNotFound;
}
void DevicePluginMailNotification::deviceRemoved(Device *device) void DevicePluginMailNotification::deviceRemoved(Device *device)
{ {

View File

@ -13,6 +13,7 @@
"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",
@ -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"

View File

@ -27,30 +27,23 @@ 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, 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:
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: default:
break; break;
} }
@ -82,18 +75,23 @@ void SmtpClient::readData()
} }
responseLine.truncate(3); responseLine.truncate(3);
qCDebug(dcMailNotification()) << "<--" << response << "|" << responseLine;
switch (m_state) { switch (m_state) {
case InitState: case InitState:
if (responseLine == "220") { if (responseLine == "220") {
send("EHLO localhost"); send("EHLO localhost");
if (m_encryptionType == EncryptionTypeNone) { if (m_encryptionType == EncryptionTypeNone) {
m_state = AuthentificationState; m_state = AuthentificationState;
break; break;
} }
if (m_encryptionType == EncryptionTypeSSL) { if (m_encryptionType == EncryptionTypeSSL) {
m_state = HandShakeState; m_state = HandShakeState;
break; break;
} }
if (m_encryptionType == EncryptionTypeTLS) { if (m_encryptionType == EncryptionTypeTLS) {
m_state = StartTlsState; m_state = StartTlsState;
break; break;
@ -108,28 +106,32 @@ void SmtpClient::readData()
send("EHLO localhost"); send("EHLO localhost");
m_state = AuthentificationState; m_state = AuthentificationState;
} }
if (responseLine == "220") { if (responseLine == "220") {
if (!m_socket->isEncrypted() && m_encryptionType != EncryptionTypeNone) { if (!m_socket->isEncrypted() && m_encryptionType != EncryptionTypeNone) {
m_socket->startClientEncryption(); m_socket->startClientEncryption();
} }
send("EHLO localhost"); send("EHLO localhost");
m_state = AuthentificationState; m_state = AuthentificationState;
} }
break; break;
case StartTlsState: case StartTlsState:
if (responseLine == "250") { if (responseLine == "250") {
send("STARTTLS"); send("STARTTLS");
m_state = HandShakeState; m_state = HandShakeState;
} }
break; break;
case AuthentificationState: case AuthentificationState:
if (responseLine == "250") { if (responseLine == "250") {
if(m_authMethod == AuthMethodLogin) { if (m_authenticationMethod == AuthenticationMethodLogin) {
send("AUTH LOGIN"); send("AUTH LOGIN");
m_state = UserState; m_state = UserState;
break; break;
} }
if(m_authMethod == AuthMethodPlain) { if (m_authenticationMethod == AuthenticationMethodPlain) {
send("AUTH PLAIN " + QByteArray().append((char) 0).append(m_user).append((char) 0).append(m_password).toBase64()); 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 we just want to test the Login, we are almost done here
if (!m_testLogin) { if (!m_testLogin) {
@ -256,9 +258,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)
@ -281,13 +283,14 @@ void SmtpClient::setRecipient(const QString &rcpt)
m_rcpt = rcpt; m_rcpt = rcpt;
} }
void SmtpClient::socketError(QAbstractSocket::SocketError error) void SmtpClient::onSocketError(QAbstractSocket::SocketError error)
{ {
qCWarning(dcMailNotification) << "Mail socket -> " << error << m_socket->errorString(); qCWarning(dcMailNotification) << "Mail socket error" << error << m_socket->errorString();
} }
void SmtpClient::send(const QString &data) void SmtpClient::send(const QString &data)
{ {
qCDebug(dcMailNotification()) << "-->" << qUtf8Printable(data.toUtf8());
m_socket->write(data.toUtf8() + "\r\n"); m_socket->write(data.toUtf8() + "\r\n");
m_socket->flush(); m_socket->flush();
} }

View File

@ -35,10 +35,11 @@ class SmtpClient : public QObject
Q_OBJECT Q_OBJECT
public: public:
enum AuthMethod{ enum AuthenticationMethod{
AuthMethodPlain, AuthenticationMethodPlain,
AuthMethodLogin AuthenticationMethodLogin
}; };
Q_ENUM(AuthenticationMethod)
enum SendState{ enum SendState{
InitState, InitState,
@ -55,12 +56,14 @@ public:
QuitState, QuitState,
CloseState CloseState
}; };
Q_ENUM(SendState)
enum EncryptionType{ enum EncryptionType{
EncryptionTypeNone, EncryptionTypeNone,
EncryptionTypeSSL, EncryptionTypeSSL,
EncryptionTypeTLS EncryptionTypeTLS
}; };
Q_ENUM(EncryptionType)
explicit SmtpClient(QObject *parent = 0); explicit SmtpClient(QObject *parent = 0);
@ -71,22 +74,22 @@ public:
void setHost(const QString &host); void setHost(const QString &host);
void setPort(const int &port); void setPort(const int &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 setRecipient(const QString &rcpt);
private: private:
QSslSocket *m_socket; QSslSocket *m_socket = nullptr;
SendState m_state; SendState m_state = InitState;
QString m_host; QString m_host = "127.0.0.1";
int m_port; int 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; QString m_rcpt;
QString m_subject; QString m_subject;
@ -94,14 +97,14 @@ private:
QString m_message; QString m_message;
ActionId m_actionId; ActionId m_actionId;
bool m_testLogin; bool m_testLogin = false;
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 readData(); void readData();