added async setup and fixed inline comments

This commit is contained in:
Simon Stürz 2014-10-22 13:06:05 +02:00 committed by Michael Zanetti
parent 7a6dacff9f
commit f7aac2554c
5 changed files with 133 additions and 121 deletions

View File

@ -2,7 +2,7 @@
GUH_VERSION_STRING=$$system('dpkg-parsechangelog | sed -n -e "s/^Version: //p"') GUH_VERSION_STRING=$$system('dpkg-parsechangelog | sed -n -e "s/^Version: //p"')
DEFINES += GUH_VERSION_STRING=\\\"$${GUH_VERSION_STRING}\\\" DEFINES += GUH_VERSION_STRING=\\\"$${GUH_VERSION_STRING}\\\"
#QMAKE_CXXFLAGS += -Werror QMAKE_CXXFLAGS += -Werror
CONFIG += c++11 CONFIG += c++11
# Enable coverage option # Enable coverage option

View File

@ -234,7 +234,6 @@ DeviceClassId customMailDeviceClassId = DeviceClassId("f4844c97-7ca6-4349-904e-f
ActionTypeId sendMailActionTypeId = ActionTypeId("054613b0-3666-4dad-9252-e0ebca187edc"); ActionTypeId sendMailActionTypeId = ActionTypeId("054613b0-3666-4dad-9252-e0ebca187edc");
DevicePluginMailNotification::DevicePluginMailNotification() DevicePluginMailNotification::DevicePluginMailNotification()
{ {
} }
@ -248,22 +247,25 @@ DeviceManager::DeviceSetupStatus DevicePluginMailNotification::setupDevice(Devic
// Google mail // Google mail
if(device->deviceClassId() == googleMailDeviceClassId){ if(device->deviceClassId() == googleMailDeviceClassId){
device->setName("Google Mail (" + device->paramValue("user").toString() + ")"); device->setName("Google Mail (" + device->paramValue("user").toString() + ")");
SmtpClient *smtpClient = new SmtpClient("smtp.gmail.com", SmtpClient *smtpClient = new SmtpClient(this);
465, smtpClient->setHost("smtp.gmail.com");
device->paramValue("user").toString(), smtpClient->setPort(465);
device->paramValue("password").toString(), smtpClient->setUser(device->paramValue("user").toString());
SmtpClient::AuthLogin,
SmtpClient::EncryptionSSL, // TODO: use cryptography to save password not as plain text
this); smtpClient->setPassword(device->paramValue("password").toString());
smtpClient->setAuthMethod(SmtpClient::AuthMethodLogin);
smtpClient->setEncryptionType(SmtpClient::EncryptionTypeSSL);
smtpClient->setSender(device->paramValue("user").toString()); 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); connect(smtpClient, &SmtpClient::sendMailFinished, this, &DevicePluginMailNotification::sendMailFinished);
// TODO: test connection;
m_clients.insert(smtpClient,device); m_clients.insert(smtpClient,device);
return DeviceManager::DeviceSetupStatusSuccess;
//return DeviceManager::DeviceSetupStatusAsync; smtpClient->testLogin();
return DeviceManager::DeviceSetupStatusAsync;
} }
// Custom mail // Custom mail
if(device->deviceClassId() == customMailDeviceClassId){ if(device->deviceClassId() == customMailDeviceClassId){
@ -272,33 +274,38 @@ DeviceManager::DeviceSetupStatus DevicePluginMailNotification::setupDevice(Devic
smtpClient->setHost(device->paramValue("SMTP server").toString()); smtpClient->setHost(device->paramValue("SMTP server").toString());
smtpClient->setPort(device->paramValue("port").toInt()); smtpClient->setPort(device->paramValue("port").toInt());
smtpClient->setUser(device->paramValue("user").toString()); smtpClient->setUser(device->paramValue("user").toString());
// TODO: use cryptography to save password not as plain text
smtpClient->setPassword(device->paramValue("password").toString()); smtpClient->setPassword(device->paramValue("password").toString());
if(device->paramValue("authentification").toString() == "PLAIN"){ if(device->paramValue("authentification").toString() == "PLAIN"){
smtpClient->setAuthMethod(SmtpClient::AuthPlain); smtpClient->setAuthMethod(SmtpClient::AuthMethodPlain);
} }else if(device->paramValue("authentification").toString() == "LOGIN"){
if(device->paramValue("authentification").toString() == "LOGIN"){ smtpClient->setAuthMethod(SmtpClient::AuthMethodLogin);
smtpClient->setAuthMethod(SmtpClient::AuthLogin); }else{
return DeviceManager::DeviceSetupStatusFailure;
} }
if(device->paramValue("encryption").toString() == "NONE"){ 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); smtpClient->setRecipient(device->paramValue("recipient").toString());
}
if(device->paramValue("encryption").toString() == "TLS"){
smtpClient->setEncryptionType(SmtpClient::EncryptionTLS);
}
smtpClient->setRecipiant(device->paramValue("recipient").toString());
smtpClient->setSender(device->paramValue("sender mail").toString()); smtpClient->setSender(device->paramValue("sender mail").toString());
connect(smtpClient, &SmtpClient::testLoginFinished, this, &DevicePluginMailNotification::testLoginFinished);
connect(smtpClient, &SmtpClient::sendMailFinished, this, &DevicePluginMailNotification::sendMailFinished); connect(smtpClient, &SmtpClient::sendMailFinished, this, &DevicePluginMailNotification::sendMailFinished);
// TODO: test connection;
m_clients.insert(smtpClient,device); m_clients.insert(smtpClient,device);
return DeviceManager::DeviceSetupStatusSuccess;
//return DeviceManager::DeviceSetupStatusAsync; smtpClient->testLogin();
return DeviceManager::DeviceSetupStatusAsync;
} }
return DeviceManager::DeviceSetupStatusFailure; return DeviceManager::DeviceSetupStatusFailure;
} }
@ -319,6 +326,26 @@ DeviceManager::DeviceError DevicePluginMailNotification::executeAction(Device *d
return DeviceManager::DeviceErrorActionTypeNotFound; 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<SmtpClient*>(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) void DevicePluginMailNotification::sendMailFinished(const bool &success, const ActionId &actionId)
{ {
if(success){ if(success){

View File

@ -36,16 +36,15 @@ public:
DeviceManager::DeviceSetupStatus setupDevice(Device *device) override; DeviceManager::DeviceSetupStatus setupDevice(Device *device) override;
DeviceManager::HardwareResources requiredHardware() const override; DeviceManager::HardwareResources requiredHardware() const override;
DeviceManager::DeviceError executeAction(Device *device, const Action &action) override; DeviceManager::DeviceError executeAction(Device *device, const Action &action) override;
void deviceRemoved(Device *device) override;
private: private:
QHash <SmtpClient*, Device*> m_clients; QHash <SmtpClient*, Device*> m_clients;
private slots: private slots:
void testLoginFinished(const bool &success);
public slots:
void sendMailFinished(const bool &success, const ActionId &actionId); void sendMailFinished(const bool &success, const ActionId &actionId);
}; };
#endif // DEVICEPLUGINMAILNOTIFICATION_H #endif // DEVICEPLUGINMAILNOTIFICATION_H

View File

@ -21,45 +21,29 @@
SmtpClient::SmtpClient(QObject *parent): SmtpClient::SmtpClient(QObject *parent):
QObject(parent) QObject(parent)
{ {
m_state = InitState;
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))); connect(m_socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(socketError(QAbstractSocket::SocketError)));
connect(m_socket,SIGNAL(connected()),this,SLOT(connected())); // error because QSslSocket has also a method called error...also QAbstractSocket or QTcpSocket don't work...
connect(m_socket,SIGNAL(readyRead()),this,SLOT(readData())); //connect(m_socket, &QSslSocket::error, this, &SmtpClient::socketError);
connect(m_socket,SIGNAL(disconnected()),this,SLOT(disconnected())); 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() void SmtpClient::connectToHost()
{ {
switch (m_encryptionType) { switch (m_encryptionType) {
case EncryptionNone: case EncryptionTypeNone:
m_socket->connectToHost(m_host, m_port); m_socket->connectToHost(m_host, m_port);
break; break;
case EncryptionSSL: case EncryptionTypeSSL:
m_socket->connectToHostEncrypted(m_host, m_port); m_socket->connectToHostEncrypted(m_host, m_port);
break; break;
case EncryptionTLS: case EncryptionTypeTLS:
m_socket->connectToHost(m_host,m_port); m_socket->connectToHost(m_host,m_port);
break; break;
default: default:
@ -67,10 +51,19 @@ void SmtpClient::connectToHost()
} }
} }
void SmtpClient::testLogin()
{
m_socket->close();
m_testLogin = true;
connectToHost();
}
void SmtpClient::connected() void SmtpClient::connected()
{ {
// qDebug() << "connected to" << m_host; }
// qDebug() << "-----------------------";
void SmtpClient::disconnected()
{
} }
void SmtpClient::readData() void SmtpClient::readData()
@ -84,25 +77,19 @@ void SmtpClient::readData()
} }
responseLine.truncate( 3 ); responseLine.truncate( 3 );
// qDebug() << "---------------------------------------------";
// qDebug() << "Server code:" << responseLine;
// qDebug() << "---------------------------------------------";
// qDebug() << "Server data: " << response;
// qDebug() << "---------------------------------------------";
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 == EncryptionNone){ if(m_encryptionType == EncryptionTypeNone){
m_state = AuthentificationState; m_state = AuthentificationState;
break; break;
} }
if(m_encryptionType == EncryptionSSL){ if(m_encryptionType == EncryptionTypeSSL){
m_state = HandShakeState; m_state = HandShakeState;
break; break;
} }
if(m_encryptionType == EncryptionTLS){ if(m_encryptionType == EncryptionTypeTLS){
m_state = StartTlsState; m_state = StartTlsState;
break; break;
} }
@ -110,14 +97,14 @@ void SmtpClient::readData()
break; break;
case HandShakeState: case HandShakeState:
if(responseLine == "250"){ if(responseLine == "250"){
if(!m_socket->isEncrypted() && m_encryptionType != EncryptionNone){ 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;
} }
if(responseLine == "220"){ if(responseLine == "220"){
if(!m_socket->isEncrypted() && m_encryptionType != EncryptionNone){ if(!m_socket->isEncrypted() && m_encryptionType != EncryptionTypeNone){
m_socket->startClientEncryption(); m_socket->startClientEncryption();
} }
send("EHLO localhost"); send("EHLO localhost");
@ -132,14 +119,19 @@ void SmtpClient::readData()
break; break;
case AuthentificationState: case AuthentificationState:
if(responseLine == "250"){ if(responseLine == "250"){
if(m_authMethod == AuthLogin){ if(m_authMethod == AuthMethodLogin){
send("AUTH LOGIN"); send("AUTH LOGIN");
m_state = UserState; m_state = UserState;
break; 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()); 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; break;
} }
} }
@ -153,7 +145,19 @@ void SmtpClient::readData()
case PasswordState: case PasswordState:
if(responseLine == "334"){ if(responseLine == "334"){
send(QByteArray().append(m_password).toBase64()); 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; break;
case MailState: case MailState:
@ -183,10 +187,7 @@ void SmtpClient::readData()
case QuitState: case QuitState:
if(responseLine == "250"){ if(responseLine == "250"){
emit sendMailFinished(true, m_actionId); emit sendMailFinished(true, m_actionId);
// qDebug() << "--------------------------------------------"; send("QUIT");
// qDebug() << " MAIL SENT!!!!";
// qDebug() << "--------------------------------------------";
logout();
m_state = CloseState; m_state = CloseState;
} }
break; break;
@ -194,34 +195,23 @@ void SmtpClient::readData()
if(responseLine == "221"){ if(responseLine == "221"){
m_socket->close(); m_socket->close();
} }
// some mail server does not recognize the QUIT command...so close the connection either way
m_socket->close(); m_socket->close();
break; break;
default: 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); emit sendMailFinished(false, m_actionId);
m_socket->close();
break; 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) bool SmtpClient::sendMail(const QString &subject, const QString &body, const ActionId &actionId)
{ {
m_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 = "To: " + m_rcpt + "\n";
m_message.append("From: " + m_sender + "\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.append(body);
m_message.replace( QString::fromLatin1( "\n" ), QString::fromLatin1( "\r\n" ) ); 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.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; m_sender = sender;
} }
void SmtpClient::setRecipiant(const QString &rcpt) void SmtpClient::setRecipient(const QString &rcpt)
{ {
m_rcpt = rcpt; m_rcpt = rcpt;
} }
void SmtpClient::socketError(QAbstractSocket::SocketError error) 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) void SmtpClient::send(const QString &data)
{ {
//qDebug() << "sending to host:" << data;
m_socket->write(data.toUtf8() + "\r\n"); m_socket->write(data.toUtf8() + "\r\n");
m_socket->flush(); m_socket->flush();
} }

View File

@ -32,8 +32,8 @@ class SmtpClient : public QObject
public: public:
enum AuthMethod{ enum AuthMethod{
AuthPlain, AuthMethodPlain,
AuthLogin AuthMethodLogin
}; };
enum SendState{ enum SendState{
@ -43,6 +43,7 @@ public:
StartTlsState, StartTlsState,
UserState, UserState,
PasswordState, PasswordState,
TestLoginFinishedState,
MailState, MailState,
RcptState, RcptState,
DataState, DataState,
@ -52,17 +53,15 @@ public:
}; };
enum EncryptionType{ enum EncryptionType{
EncryptionNone, // no encryption EncryptionTypeNone,
EncryptionSSL, // SSL EncryptionTypeSSL,
EncryptionTLS // STARTTLS EncryptionTypeTLS
}; };
explicit SmtpClient(QObject *parent = 0); 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 connectToHost();
void login(const QString &user, const QString &password); void testLogin();
void logout();
bool sendMail(const QString &subject, const QString &body, const ActionId &actionId); bool sendMail(const QString &subject, const QString &body, const ActionId &actionId);
void setHost(const QString &host); void setHost(const QString &host);
@ -72,12 +71,12 @@ public:
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 setRecipiant(const QString &rcpt); void setRecipient(const QString &rcpt);
private: private:
SendState m_state;
QSslSocket *m_socket; QSslSocket *m_socket;
SendState m_state;
QString m_host; QString m_host;
int m_port; int m_port;
QString m_user; QString m_user;
@ -91,20 +90,18 @@ private:
QString m_message; QString m_message;
ActionId m_actionId; ActionId m_actionId;
bool m_testLogin;
signals: signals:
void sendMailFinished(const bool &success, const ActionId &actionId); void sendMailFinished(const bool &success, const ActionId &actionId);
void testLoginFinished(const bool &success);
private slots: private slots:
void socketError(QAbstractSocket::SocketError error); void socketError(QAbstractSocket::SocketError error);
void connected(); void connected();
void readData();
void disconnected(); void disconnected();
void readData();
void send(const QString &data); void send(const QString &data);
public slots:
}; };
#endif // SMTPCLIENT_H #endif // SMTPCLIENT_H