Commit c0bb640a authored by Zach's avatar Zach
Browse files

Merge pull request #1295 from ctrlaltca/servatrice_email_v2

Refactor servatrice email send
parents 9aa16157 9c38b084
......@@ -16,18 +16,11 @@ SET(servatrice_SOURCES
src/isl_interface.cpp
src/signalhandler.cpp
${VERSION_STRING_CPP}
src/smtp/emailaddress.cpp
src/smtp/mimeattachment.cpp
src/smtp/mimecontentformatter.cpp
src/smtp/mimefile.cpp
src/smtp/mimehtml.cpp
src/smtp/mimeinlinefile.cpp
src/smtp/mimemessage.cpp
src/smtp/mimemultipart.cpp
src/smtp/mimepart.cpp
src/smtp/mimetext.cpp
src/smtp/quotedprintable.cpp
src/smtp/smtpclient.cpp
src/smtpclient.cpp
src/smtp/qxthmac.cpp
src/smtp/qxtmailattachment.cpp
src/smtp/qxtmailmessage.cpp
src/smtp/qxtsmtp.cpp
)
set(servatrice_RESOURCES servatrice.qrc)
......
-- Servatrice db migration from version 1 to version 2
-- FIX #1281
CREATE TABLE IF NOT EXISTS `cockatrice_activation_emails` (
`name` varchar(35) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
UPDATE cockatrice_schema_version SET version=2 WHERE version=1;
......@@ -90,11 +90,11 @@ allowpunctuationprefix=false
[smtp]
; Connectin type: currently supported method are "tcp", "ssl" and "tls"
; Connectin type: currently supported method are "tcp" and "ssl"; tls is autodetected if available
connection=tcp
; Auth type: currently supported method are "plain" and "login"
auth=plain
; Accept all certificates: in ssl mode, enable this if your server is using an invalid/self signed certificate
acceptallcerts=false;
; Hostname or IP addres of the smtp server
host=localhost
......
......@@ -205,3 +205,7 @@ CREATE TABLE IF NOT EXISTS `cockatrice_log` (
KEY `target_id` (`target_id`),
KEY `target_name` (`target_name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `cockatrice_activation_emails` (
`name` varchar(35) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
......@@ -29,6 +29,7 @@
#include "server_logger.h"
#include "settingscache.h"
#include "signalhandler.h"
#include "smtpclient.h"
#include "rng_sfmt.h"
#include "version_string.h"
#include <google/protobuf/stubs/common.h>
......@@ -38,6 +39,7 @@ ServerLogger *logger;
QThread *loggerThread;
SettingsCache *settingsCache;
SignalHandler *signalhandler;
SmtpClient *smtpClient;
/* Prototypes */
......@@ -181,6 +183,8 @@ int main(int argc, char *argv[])
testRNG();
if (testHashFunction)
testHash();
smtpClient = new SmtpClient();
Servatrice *server = new Servatrice();
QObject::connect(server, SIGNAL(destroyed()), &app, SLOT(quit()), Qt::QueuedConnection);
......@@ -200,6 +204,7 @@ int main(int argc, char *argv[])
std::cerr << "-------------------------" << std::endl;
}
delete smtpClient;
delete rng;
delete signalhandler;
delete settingsCache;
......
......@@ -4,9 +4,11 @@
class ServerLogger;
class QThread;
class SettingsCache;
class SmtpClient;
extern ServerLogger *logger;
extern QThread *loggerThread;
extern SettingsCache *settingsCache;
extern SmtpClient *smtpClient;
#endif
......@@ -34,6 +34,7 @@
#include "server_logger.h"
#include "main.h"
#include "decklist.h"
#include "smtpclient.h"
#include "pb/event_server_message.pb.h"
#include "pb/event_server_shutdown.pb.h"
#include "pb/event_connection_closed.pb.h"
......@@ -473,6 +474,32 @@ void Servatrice::statusUpdate()
query->bindValue(":tx", tx);
query->bindValue(":rx", rx);
servatriceDatabaseInterface->execSqlQuery(query);
// send activation emails
bool registrationEnabled = settingsCache->value("registration/enabled", false).toBool();
bool requireEmailForRegistration = settingsCache->value("registration/requireemail", true).toBool();
if (registrationEnabled && requireEmailForRegistration)
{
QSqlQuery *query = servatriceDatabaseInterface->prepareQuery("select a.name, b.email, b.token from {prefix}_activation_emails a left join {prefix}_users b on a.name = b.name");
if (!servatriceDatabaseInterface->execSqlQuery(query))
return;
QSqlQuery *queryDelete = servatriceDatabaseInterface->prepareQuery("delete from {prefix}_activation_emails where name = :name");
while (query->next()) {
const QString userName = query->value(0).toString();
const QString emailAddress = query->value(1).toString();
const QString token = query->value(2).toString();
if(smtpClient->enqueueActivationTokenMail(userName, emailAddress, token))
{
queryDelete->bindValue(":name", userName);
servatriceDatabaseInterface->execSqlQuery(queryDelete);
}
}
smtpClient->sendAllEmails();
}
}
void Servatrice::scheduleShutdown(const QString &reason, int minutes)
......
......@@ -9,7 +9,7 @@
#include "server.h"
#include "server_database_interface.h"
#define DATABASE_SCHEMA_VERSION 1
#define DATABASE_SCHEMA_VERSION 2
class Servatrice;
......
......@@ -59,8 +59,6 @@
#include "pb/serverinfo_user.pb.h"
#include "pb/serverinfo_deckstorage.pb.h"
#include "smtp/SmtpMime"
#include "version_string.h"
#include <string>
#include <iostream>
......@@ -854,8 +852,11 @@ Response::ResponseCode ServerSocketInterface::cmdRegisterAccount(const Command_R
qDebug() << "Accepted register command for user: " << userName;
if(requireEmailForRegistration)
{
// TODO call a slot on another thread to send email
sendActivationTokenMail(userName, emailAddress, token);
QSqlQuery *query = sqlInterface->prepareQuery("insert into {prefix}_activation_emails (name) values(:name)");
query->bindValue(":name", userName);
if (!sqlInterface->execSqlQuery(query))
return Response::RespRegistrationFailed;
return Response::RespRegistrationAcceptedNeedsActivation;
} else {
return Response::RespRegistrationAccepted;
......@@ -865,88 +866,6 @@ Response::ResponseCode ServerSocketInterface::cmdRegisterAccount(const Command_R
}
}
bool ServerSocketInterface::sendActivationTokenMail(const QString &nickname, const QString &recipient, const QString &token)
{
QString tmp = settingsCache->value("smtp/connection", "tcp").toString();
SmtpClient::ConnectionType connection = SmtpClient::TcpConnection;
if(tmp == "ssl")
connection = SmtpClient::SslConnection;
else if(tmp == "tls")
connection = SmtpClient::TlsConnection;
tmp = settingsCache->value("smtp/auth", "plain").toString();
SmtpClient::AuthMethod auth = SmtpClient::AuthPlain;
if(tmp == "login")
auth = SmtpClient::AuthLogin;
QString host = settingsCache->value("smtp/host", "localhost").toString();
int port = settingsCache->value("smtp/port", 25).toInt();
QString username = settingsCache->value("smtp/username", "").toString();
QString password = settingsCache->value("smtp/password", "").toString();
QString email = settingsCache->value("smtp/email", "").toString();
QString name = settingsCache->value("smtp/name", "").toString();
QString subject = settingsCache->value("smtp/subject", "").toString();
QString body = settingsCache->value("smtp/body", "").toString();
if(email.isEmpty())
{
qDebug() << "[MAIL] Missing email field" << endl;
return false;
}
if(body.isEmpty())
{
qDebug() << "[MAIL] Missing body field" << endl;
return false;
}
if(recipient.isEmpty())
{
qDebug() << "[MAIL] Missing recipient field" << endl;
return false;
}
if(token.isEmpty())
{
qDebug() << "[MAIL] Missing token field" << endl;
return false;
}
SmtpClient smtp(host, port, connection);
smtp.setUser(username);
smtp.setPassword(password);
smtp.setAuthMethod(auth);
MimeMessage message;
EmailAddress sender(email, name);
message.setSender(&sender);
EmailAddress to(recipient, nickname);
message.addRecipient(&to);
message.setSubject(subject);
MimeText text;
text.setText(body.replace("%username", nickname).replace("%token", token));
message.addPart(&text);
// Now we can send the mail
if (!smtp.connectToHost()) {
qDebug() << "[MAIL] Failed to connect to host" << host << "on port" << port;
return false;
}
if (!smtp.login()) {
qDebug() << "[MAIL] Failed to login as " << username;
return false;
}
if (!smtp.sendMail(message)) {
qDebug() << "[MAIL] Failed to send mail to " << recipient;
return false;
}
smtp.quit();
qDebug() << "[MAIL] Sent activation email to " << recipient << " for nickname " << nickname;
return true;
}
bool ServerSocketInterface::tooManyRegistrationAttempts(const QString &ipAddress)
{
// TODO: implement
......
......@@ -108,8 +108,6 @@ private:
Response::ResponseCode cmdAccountEdit(const Command_AccountEdit &cmd, ResponseContainer &rc);
Response::ResponseCode cmdAccountImage(const Command_AccountImage &cmd, ResponseContainer &rc);
Response::ResponseCode cmdAccountPassword(const Command_AccountPassword &cmd, ResponseContainer &rc);
bool sendActivationTokenMail(const QString &nickname, const QString &recipient, const QString &token);
public:
ServerSocketInterface(Servatrice *_server, Servatrice_DatabaseInterface *_databaseInterface, QObject *parent = 0);
~ServerSocketInterface();
......
/*
Copyright (c) 2011-2012 - Tőkés Attila
This file is part of SmtpClient for Qt.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
See the LICENSE file for more details.
*/
#ifndef SMTPMIME_H
#define SMTPMIME_H
#include "smtpclient.h"
#include "mimepart.h"
#include "mimehtml.h"
#include "mimeattachment.h"
#include "mimemessage.h"
#include "mimetext.h"
#include "mimeinlinefile.h"
#include "mimefile.h"
#endif // SMTPMIME_H
/*
Copyright (c) 2011-2012 - Tőkés Attila
This file is part of SmtpClient for Qt.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
See the LICENSE file for more details.
*/
#include "emailaddress.h"
/* [1] Constructors and Destructors */
EmailAddress::EmailAddress(const QString & address, const QString & name)
{
this->address = address;
this->name = name;
}
EmailAddress::~EmailAddress()
{
}
/* [1] --- */
/* [2] Getters and Setters */
void EmailAddress::setName(const QString & name)
{
this->name = name;
}
void EmailAddress::setAddress(const QString & address)
{
this->address = address;
}
const QString & EmailAddress::getName() const
{
return name;
}
const QString & EmailAddress::getAddress() const
{
return address;
}
/* [2] --- */
/*
Copyright (c) 2011-2012 - Tőkés Attila
This file is part of SmtpClient for Qt.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
See the LICENSE file for more details.
*/
#ifndef EMAILADDRESS_H
#define EMAILADDRESS_H
#include <QObject>
#include "smtpexports.h"
class SMTP_EXPORT EmailAddress : public QObject
{
Q_OBJECT
public:
/* [1] Constructors and Destructors */
EmailAddress();
EmailAddress(const QString & address, const QString & name="");
~EmailAddress();
/* [1] --- */
/* [2] Getters and Setters */
void setName(const QString & name);
void setAddress(const QString & address);
const QString & getName() const;
const QString & getAddress() const;
/* [2] --- */
private:
/* [3] Private members */
QString name;
QString address;
/* [3] --- */
};
#endif // EMAILADDRESS_H
/*
Copyright (c) 2011-2012 - Tőkés Attila
This file is part of SmtpClient for Qt.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
See the LICENSE file for more details.
*/
#include "mimeattachment.h"
#include <QFileInfo>
/* [1] Constructors and Destructors */
MimeAttachment::MimeAttachment(QFile *file)
: MimeFile(file)
{
}
MimeAttachment::MimeAttachment(const QByteArray& stream, const QString& fileName): MimeFile(stream, fileName)
{
}
MimeAttachment::~MimeAttachment()
{
}
/* [1] --- */
/* [2] Protected methods */
void MimeAttachment::prepare()
{
this->header += "Content-disposition: attachment\r\n";
/* !!! IMPORTANT !!! */
MimeFile::prepare();
}
/* [2] --- */
/*
Copyright (c) 2011-2012 - Tőkés Attila
This file is part of SmtpClient for Qt.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
See the LICENSE file for more details.
*/
#ifndef MIMEATTACHMENT_H
#define MIMEATTACHMENT_H
#include <QFile>
#include "mimepart.h"
#include "mimefile.h"
#include "smtpexports.h"
class SMTP_EXPORT MimeAttachment : public MimeFile
{
Q_OBJECT
public:
/* [1] Constructors and Destructors */
MimeAttachment(QFile* file);
MimeAttachment(const QByteArray& stream, const QString& fileName);
~MimeAttachment();
/* [1] --- */
protected:
/* [2] Protected methods */
virtual void prepare();
/* [2] --- */
};
#endif // MIMEATTACHMENT_H
/*
Copyright (c) 2011-2012 - Tőkés Attila
This file is part of SmtpClient for Qt.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
See the LICENSE file for more details.
*/
#include "mimecontentformatter.h"
MimeContentFormatter::MimeContentFormatter(int max_length) :
max_length(max_length)
{}
QString MimeContentFormatter::format(const QString &content, bool quotedPrintable) const {
QString out;
int chars = 0;
for (int i = 0; i < content.length() ; ++i) {
chars++;
if (!quotedPrintable) {
if (chars > max_length) {
out.append("\r\n");
chars = 1;
}
}
else {
if (content[i] == '\n') { // new line
out.append(content[i]);
chars = 0;
continue;
}
if ((chars > max_length - 1)
|| ((content[i] == '=') && (chars > max_length - 3) )) {
out.append('=');
out.append("\r\n");
chars = 1;
}
}
out.append(content[i]);
}
return out;
}
void MimeContentFormatter::setMaxLength(int l) {
max_length = l;
}
int MimeContentFormatter::getMaxLength() const {
return max_length;
}
/*
Copyright (c) 2011-2012 - Tőkés Attila
This file is part of SmtpClient for Qt.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
See the LICENSE file for more details.
*/
#ifndef MIMECONTENTFORMATTER_H
#define MIMECONTENTFORMATTER_H
#include <QObject>
#include <QByteArray>
#include "smtpexports.h"
class SMTP_EXPORT MimeContentFormatter : public QObject
{
Q_OBJECT
public:
MimeContentFormatter (int max_length = 76);
void setMaxLength(int l);
int getMaxLength() const;
QString format(const QString &content, bool quotedPrintable = false) const;
protected:
int max_length;
};
#endif // MIMECONTENTFORMATTER_H
/*
Copyright (c) 2011-2012 - Tőkés Attila
This file is part of SmtpClient for Qt.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
See the LICENSE file for more details.
*/
#include "mimefile.h"
#include <QFileInfo>
/* [1] Constructors and Destructors */
MimeFile::MimeFile(QFile *file)
{
this->file = file;
this->cType = "application/octet-stream";
this->cName = QFileInfo(*file).fileName();
this->cEncoding = Base64;
}
MimeFile::MimeFile(const QByteArray& stream, const QString& fileName)
{
this->cEncoding = Base64;
this->cType = "application/octet-stream";
this->file = 0;
this->cName = fileName;
this->content = stream;
}
MimeFile::~MimeFile()
{
if (file)
delete file;
}
/* [1] --- */
/* [2] Getters and setters */
/* [2] --- */
/* [3] Protected methods */
void MimeFile::prepare()
{
if (this->file)
{
file->open(QIODevice::ReadOnly);
this->content = file->readAll();
file->close();
}
/* !!! IMPORTANT !!!! */
MimePart::prepare();
}
/* [3] --- */
/*
Copyright (c) 2011-2012 - Tőkés Attila
This file is part of SmtpClient for Qt.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
See the LICENSE file for more details.
*/
#ifndef MIMEFILE_H
#define MIMEFILE_H
#include "mimepart.h"
#include <QFile>
#include "smtpexports.h"
class SMTP_EXPORT MimeFile : public MimePart
{
Q_OBJECT
public:
/* [1] Constructors and Destructors */
MimeFile(const QByteArray& stream, const QString& fileName);
MimeFile(QFile *f);
~MimeFile();
/* [1] --- */
/* [2] Getters and Setters */
/* [2] --- */
protected:
/* [3] Protected members */
QFile* file;
/* [3] --- */
/* [4] Protected methods */
virtual void prepare();
/* [4] --- */
};
#endif // MIMEFILE_H
/*
Copyright (c) 2011-2012 - Tőkés Attila
This file is part of SmtpClient for Qt.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
See the LICENSE file for more details.
*/
#include "mimehtml.h"
/* [1] Constructors and Destructors */
MimeHtml::MimeHtml(const QString &html) : MimeText(html)
{
this->cType = "text/html";
}
MimeHtml::~MimeHtml() {}
/* [1] --- */
/* [2] Getters and Setters */
void MimeHtml::setHtml(const QString & html)
{
this->text = html;
}
const QString & MimeHtml::getHtml() const
{
return text;
}
/* [2] --- */
/* [3] Protected methods */
void MimeHtml::prepare()
{
/* !!! IMPORTANT !!! */
MimeText::prepare();
}
/* [3] --- */
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment