diff --git a/guh.pri b/guh.pri index 5f2c633c..20989324 100644 --- a/guh.pri +++ b/guh.pri @@ -2,7 +2,7 @@ GUH_VERSION_STRING=$$system('dpkg-parsechangelog | sed -n -e "s/^Version: //p"') DEFINES += GUH_VERSION_STRING=\\\"$${GUH_VERSION_STRING}\\\" -#QMAKE_CXXFLAGS += -Werror +QMAKE_CXXFLAGS += -Werror CONFIG += c++11 # Enable coverage option diff --git a/plugins/deviceplugins/mailnotification/devicepluginmailnotification.cpp b/plugins/deviceplugins/mailnotification/devicepluginmailnotification.cpp index c8c97e7e..1e863183 100644 --- a/plugins/deviceplugins/mailnotification/devicepluginmailnotification.cpp +++ b/plugins/deviceplugins/mailnotification/devicepluginmailnotification.cpp @@ -234,7 +234,6 @@ DeviceClassId customMailDeviceClassId = DeviceClassId("f4844c97-7ca6-4349-904e-f ActionTypeId sendMailActionTypeId = ActionTypeId("054613b0-3666-4dad-9252-e0ebca187edc"); - DevicePluginMailNotification::DevicePluginMailNotification() { } @@ -248,22 +247,25 @@ DeviceManager::DeviceSetupStatus DevicePluginMailNotification::setupDevice(Devic // Google mail if(device->deviceClassId() == googleMailDeviceClassId){ device->setName("Google Mail (" + device->paramValue("user").toString() + ")"); - SmtpClient *smtpClient = new SmtpClient("smtp.gmail.com", - 465, - device->paramValue("user").toString(), - device->paramValue("password").toString(), - SmtpClient::AuthLogin, - SmtpClient::EncryptionSSL, - this); + SmtpClient *smtpClient = new SmtpClient(this); + smtpClient->setHost("smtp.gmail.com"); + smtpClient->setPort(465); + smtpClient->setUser(device->paramValue("user").toString()); + + // TODO: use cryptography to save password not as plain text + smtpClient->setPassword(device->paramValue("password").toString()); + smtpClient->setAuthMethod(SmtpClient::AuthMethodLogin); + smtpClient->setEncryptionType(SmtpClient::EncryptionTypeSSL); smtpClient->setSender(device->paramValue("user").toString()); - smtpClient->setRecipiant(device->paramValue("recipient").toString()); + smtpClient->setRecipient(device->paramValue("recipient").toString()); + connect(smtpClient, &SmtpClient::testLoginFinished, this, &DevicePluginMailNotification::testLoginFinished); connect(smtpClient, &SmtpClient::sendMailFinished, this, &DevicePluginMailNotification::sendMailFinished); - - // TODO: test connection; m_clients.insert(smtpClient,device); - return DeviceManager::DeviceSetupStatusSuccess; - //return DeviceManager::DeviceSetupStatusAsync; + + smtpClient->testLogin(); + + return DeviceManager::DeviceSetupStatusAsync; } // Custom mail if(device->deviceClassId() == customMailDeviceClassId){ @@ -272,33 +274,38 @@ DeviceManager::DeviceSetupStatus DevicePluginMailNotification::setupDevice(Devic smtpClient->setHost(device->paramValue("SMTP server").toString()); smtpClient->setPort(device->paramValue("port").toInt()); smtpClient->setUser(device->paramValue("user").toString()); + + // TODO: use cryptography to save password not as plain text smtpClient->setPassword(device->paramValue("password").toString()); if(device->paramValue("authentification").toString() == "PLAIN"){ - smtpClient->setAuthMethod(SmtpClient::AuthPlain); - } - if(device->paramValue("authentification").toString() == "LOGIN"){ - smtpClient->setAuthMethod(SmtpClient::AuthLogin); + smtpClient->setAuthMethod(SmtpClient::AuthMethodPlain); + }else if(device->paramValue("authentification").toString() == "LOGIN"){ + smtpClient->setAuthMethod(SmtpClient::AuthMethodLogin); + }else{ + return DeviceManager::DeviceSetupStatusFailure; } if(device->paramValue("encryption").toString() == "NONE"){ - smtpClient->setEncryptionType(SmtpClient::EncryptionNone); + smtpClient->setEncryptionType(SmtpClient::EncryptionTypeNone); + } else if(device->paramValue("encryption").toString() == "SSL"){ + smtpClient->setEncryptionType(SmtpClient::EncryptionTypeSSL); + }else if(device->paramValue("encryption").toString() == "TLS"){ + smtpClient->setEncryptionType(SmtpClient::EncryptionTypeTLS); + }else{ + return DeviceManager::DeviceSetupStatusFailure; } - if(device->paramValue("encryption").toString() == "SSL"){ - smtpClient->setEncryptionType(SmtpClient::EncryptionSSL); - } - if(device->paramValue("encryption").toString() == "TLS"){ - smtpClient->setEncryptionType(SmtpClient::EncryptionTLS); - } - smtpClient->setRecipiant(device->paramValue("recipient").toString()); + + smtpClient->setRecipient(device->paramValue("recipient").toString()); smtpClient->setSender(device->paramValue("sender mail").toString()); + connect(smtpClient, &SmtpClient::testLoginFinished, this, &DevicePluginMailNotification::testLoginFinished); connect(smtpClient, &SmtpClient::sendMailFinished, this, &DevicePluginMailNotification::sendMailFinished); - - // TODO: test connection; m_clients.insert(smtpClient,device); - return DeviceManager::DeviceSetupStatusSuccess; - //return DeviceManager::DeviceSetupStatusAsync; + + smtpClient->testLogin(); + + return DeviceManager::DeviceSetupStatusAsync; } return DeviceManager::DeviceSetupStatusFailure; } @@ -319,6 +326,26 @@ DeviceManager::DeviceError DevicePluginMailNotification::executeAction(Device *d return DeviceManager::DeviceErrorActionTypeNotFound; } +void DevicePluginMailNotification::deviceRemoved(Device *device) +{ + SmtpClient *smtpClient = m_clients.key(device); + m_clients.remove(smtpClient); + delete smtpClient; +} + +void DevicePluginMailNotification::testLoginFinished(const bool &success) +{ + SmtpClient *smtpClient = static_cast(sender()); + Device *device = m_clients.value(smtpClient); + if(success){ + emit deviceSetupFinished(device, DeviceManager::DeviceSetupStatusSuccess); + }else{ + emit deviceSetupFinished(device, DeviceManager::DeviceSetupStatusFailure); + m_clients.remove(smtpClient); + delete smtpClient; + } +} + void DevicePluginMailNotification::sendMailFinished(const bool &success, const ActionId &actionId) { if(success){ diff --git a/plugins/deviceplugins/mailnotification/devicepluginmailnotification.h b/plugins/deviceplugins/mailnotification/devicepluginmailnotification.h index 68dba6d0..a328437f 100644 --- a/plugins/deviceplugins/mailnotification/devicepluginmailnotification.h +++ b/plugins/deviceplugins/mailnotification/devicepluginmailnotification.h @@ -36,16 +36,15 @@ public: DeviceManager::DeviceSetupStatus setupDevice(Device *device) override; DeviceManager::HardwareResources requiredHardware() const override; DeviceManager::DeviceError executeAction(Device *device, const Action &action) override; + void deviceRemoved(Device *device) override; private: QHash m_clients; private slots: - -public slots: + void testLoginFinished(const bool &success); void sendMailFinished(const bool &success, const ActionId &actionId); - }; #endif // DEVICEPLUGINMAILNOTIFICATION_H diff --git a/plugins/deviceplugins/mailnotification/smtpclient.cpp b/plugins/deviceplugins/mailnotification/smtpclient.cpp index 86e7c6d2..33bba8dc 100644 --- a/plugins/deviceplugins/mailnotification/smtpclient.cpp +++ b/plugins/deviceplugins/mailnotification/smtpclient.cpp @@ -21,45 +21,29 @@ SmtpClient::SmtpClient(QObject *parent): QObject(parent) { - m_state = InitState; m_socket = new QSslSocket(this); + m_state = InitState; + m_testLogin = false; - connect(m_socket,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(socketError(QAbstractSocket::SocketError))); - connect(m_socket,SIGNAL(connected()),this,SLOT(connected())); - connect(m_socket,SIGNAL(readyRead()),this,SLOT(readData())); - connect(m_socket,SIGNAL(disconnected()),this,SLOT(disconnected())); + 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); } -SmtpClient::SmtpClient(QString host, int port, QString user, QString password, SmtpClient::AuthMethod authMethod, SmtpClient::EncryptionType encryptionType, QObject *parent): - m_host(host), - m_port(port), - m_user(user), - m_password(password), - m_authMethod(authMethod), - m_encryptionType(encryptionType), - QObject(parent) -{ - m_state = InitState; - m_socket = new QSslSocket(this); - - connect(m_socket,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(socketError(QAbstractSocket::SocketError))); - connect(m_socket,SIGNAL(connected()),this,SLOT(connected())); - connect(m_socket,SIGNAL(readyRead()),this,SLOT(readData())); - connect(m_socket,SIGNAL(disconnected()),this,SLOT(disconnected())); -} - - void SmtpClient::connectToHost() { switch (m_encryptionType) { - case EncryptionNone: + case EncryptionTypeNone: m_socket->connectToHost(m_host, m_port); break; - case EncryptionSSL: + case EncryptionTypeSSL: m_socket->connectToHostEncrypted(m_host, m_port); break; - case EncryptionTLS: + case EncryptionTypeTLS: m_socket->connectToHost(m_host,m_port); break; default: @@ -67,10 +51,19 @@ void SmtpClient::connectToHost() } } +void SmtpClient::testLogin() +{ + m_socket->close(); + m_testLogin = true; + connectToHost(); +} + void SmtpClient::connected() { -// qDebug() << "connected to" << m_host; -// qDebug() << "-----------------------"; +} + +void SmtpClient::disconnected() +{ } void SmtpClient::readData() @@ -84,25 +77,19 @@ void SmtpClient::readData() } responseLine.truncate( 3 ); -// qDebug() << "---------------------------------------------"; -// qDebug() << "Server code:" << responseLine; -// qDebug() << "---------------------------------------------"; -// qDebug() << "Server data: " << response; -// qDebug() << "---------------------------------------------"; - switch (m_state) { case InitState: if(responseLine == "220"){ send("EHLO localhost"); - if(m_encryptionType == EncryptionNone){ + if(m_encryptionType == EncryptionTypeNone){ m_state = AuthentificationState; break; } - if(m_encryptionType == EncryptionSSL){ + if(m_encryptionType == EncryptionTypeSSL){ m_state = HandShakeState; break; } - if(m_encryptionType == EncryptionTLS){ + if(m_encryptionType == EncryptionTypeTLS){ m_state = StartTlsState; break; } @@ -110,14 +97,14 @@ void SmtpClient::readData() break; case HandShakeState: if(responseLine == "250"){ - if(!m_socket->isEncrypted() && m_encryptionType != EncryptionNone){ + 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 != EncryptionNone){ + if(!m_socket->isEncrypted() && m_encryptionType != EncryptionTypeNone){ m_socket->startClientEncryption(); } send("EHLO localhost"); @@ -132,14 +119,19 @@ void SmtpClient::readData() break; case AuthentificationState: if(responseLine == "250"){ - if(m_authMethod == AuthLogin){ + if(m_authMethod == AuthMethodLogin){ send("AUTH LOGIN"); m_state = UserState; break; } - if(m_authMethod == AuthPlain){ + if(m_authMethod == AuthMethodPlain){ send("AUTH PLAIN " + QByteArray().append((char) 0).append(m_user).append((char) 0).append(m_password).toBase64()); - m_state = MailState; + // if we just want to test the Login, we are almost done here + if(!m_testLogin){ + m_state = MailState; + }else{ + m_state = TestLoginFinishedState; + } break; } } @@ -153,7 +145,19 @@ void SmtpClient::readData() case PasswordState: if(responseLine == "334"){ send(QByteArray().append(m_password).toBase64()); - m_state = MailState; + // 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); + m_socket->close(); + m_testLogin = false; } break; case MailState: @@ -183,10 +187,7 @@ void SmtpClient::readData() case QuitState: if(responseLine == "250"){ emit sendMailFinished(true, m_actionId); -// qDebug() << "--------------------------------------------"; -// qDebug() << " MAIL SENT!!!!"; -// qDebug() << "--------------------------------------------"; - logout(); + send("QUIT"); m_state = CloseState; } break; @@ -194,34 +195,23 @@ void SmtpClient::readData() 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: - //qDebug() << "ERROR: unexpected response from server: " << response; + // 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; } } -void SmtpClient::disconnected() -{ -// qDebug() << "disconnected from" << m_host; -// qDebug() << "-----------------------"; -} - -void SmtpClient::login(const QString &user, const QString &password) -{ - if(!m_socket->isOpen()){ - connectToHost(); - } - // qDebug() << "Try to login with: " << user << password; -} - -void SmtpClient::logout() -{ - send("QUIT"); -} - bool SmtpClient::sendMail(const QString &subject, const QString &body, const ActionId &actionId) { m_actionId = actionId; @@ -232,7 +222,7 @@ bool SmtpClient::sendMail(const QString &subject, const QString &body, const Act m_message = "To: " + m_rcpt + "\n"; m_message.append("From: " + m_sender + "\n"); - m_message.append("Subject: " + subject + "\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" ) ); @@ -278,19 +268,18 @@ void SmtpClient::setSender(const QString &sender) m_sender = sender; } -void SmtpClient::setRecipiant(const QString &rcpt) +void SmtpClient::setRecipient(const QString &rcpt) { m_rcpt = rcpt; } void SmtpClient::socketError(QAbstractSocket::SocketError error) { - qWarning() << "mail socket:" << error << m_socket->errorString(); + qWarning() << "ERROR: mail socket -> " << error << m_socket->errorString(); } void SmtpClient::send(const QString &data) { - //qDebug() << "sending to host:" << data; m_socket->write(data.toUtf8() + "\r\n"); m_socket->flush(); } diff --git a/plugins/deviceplugins/mailnotification/smtpclient.h b/plugins/deviceplugins/mailnotification/smtpclient.h index 4c7c96d4..f8611196 100644 --- a/plugins/deviceplugins/mailnotification/smtpclient.h +++ b/plugins/deviceplugins/mailnotification/smtpclient.h @@ -32,8 +32,8 @@ class SmtpClient : public QObject public: enum AuthMethod{ - AuthPlain, - AuthLogin + AuthMethodPlain, + AuthMethodLogin }; enum SendState{ @@ -43,6 +43,7 @@ public: StartTlsState, UserState, PasswordState, + TestLoginFinishedState, MailState, RcptState, DataState, @@ -52,17 +53,15 @@ public: }; enum EncryptionType{ - EncryptionNone, // no encryption - EncryptionSSL, // SSL - EncryptionTLS // STARTTLS + EncryptionTypeNone, + EncryptionTypeSSL, + EncryptionTypeTLS }; explicit SmtpClient(QObject *parent = 0); - explicit SmtpClient(QString host = QString(), int port = 465, QString user = QString(), QString password = QString(), AuthMethod authMethod = AuthPlain, EncryptionType encryptionType = EncryptionNone, QObject *parent = 0); void connectToHost(); - void login(const QString &user, const QString &password); - void logout(); + void testLogin(); bool sendMail(const QString &subject, const QString &body, const ActionId &actionId); void setHost(const QString &host); @@ -72,12 +71,12 @@ public: void setUser(const QString &user); void setPassword(const QString &password); void setSender(const QString &sender); - void setRecipiant(const QString &rcpt); + void setRecipient(const QString &rcpt); private: - SendState m_state; QSslSocket *m_socket; + SendState m_state; QString m_host; int m_port; QString m_user; @@ -91,20 +90,18 @@ private: QString m_message; ActionId m_actionId; + bool m_testLogin; + signals: void sendMailFinished(const bool &success, const ActionId &actionId); + void testLoginFinished(const bool &success); private slots: void socketError(QAbstractSocket::SocketError error); void connected(); - void readData(); void disconnected(); + void readData(); void send(const QString &data); - -public slots: - - - }; #endif // SMTPCLIENT_H