Merge pull request #1295 from ctrlaltca/servatrice_email_v2
Refactor servatrice email send
This commit is contained in:
commit
c0bb640a37
49 changed files with 2521 additions and 2574 deletions
|
@ -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)
|
||||
|
|
8
servatrice/migrations/servatrice_0001_to_0002.sql
Normal file
8
servatrice/migrations/servatrice_0001_to_0002.sql
Normal file
|
@ -0,0 +1,8 @@
|
|||
-- 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();
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
/*
|
||||
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
|
|
@ -1,60 +0,0 @@
|
|||
/*
|
||||
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] --- */
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
/*
|
||||
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
|
|
@ -1,50 +0,0 @@
|
|||
/*
|
||||
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] --- */
|
|
@ -1,51 +0,0 @@
|
|||
/*
|
||||
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
|
|
@ -1,66 +0,0 @@
|
|||
/*
|
||||
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;
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
/*
|
||||
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
|
|
@ -1,70 +0,0 @@
|
|||
/*
|
||||
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] --- */
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
/*
|
||||
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
|
|
@ -1,57 +0,0 @@
|
|||
/*
|
||||
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] --- */
|
|
@ -1,61 +0,0 @@
|
|||
/*
|
||||
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 MIMEHTML_H
|
||||
#define MIMEHTML_H
|
||||
|
||||
#include "mimetext.h"
|
||||
|
||||
#include "smtpexports.h"
|
||||
|
||||
class SMTP_EXPORT MimeHtml : public MimeText
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
/* [1] Constructors and Destructors */
|
||||
|
||||
MimeHtml(const QString &html = "");
|
||||
~MimeHtml();
|
||||
|
||||
/* [1] --- */
|
||||
|
||||
|
||||
/* [2] Getters and Setters */
|
||||
|
||||
void setHtml(const QString & html);
|
||||
|
||||
const QString& getHtml() const;
|
||||
|
||||
/* [2] --- */
|
||||
|
||||
protected:
|
||||
|
||||
/* [3] Protected members */
|
||||
|
||||
/* [3] --- */
|
||||
|
||||
|
||||
/* [4] Protected methods */
|
||||
|
||||
virtual void prepare();
|
||||
|
||||
/* [4] --- */
|
||||
};
|
||||
|
||||
#endif // MIMEHTML_H
|
|
@ -1,52 +0,0 @@
|
|||
/*
|
||||
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 "mimeinlinefile.h"
|
||||
|
||||
/* [1] Constructors and Destructors */
|
||||
|
||||
MimeInlineFile::MimeInlineFile(QFile *f)
|
||||
: MimeFile(f)
|
||||
{
|
||||
}
|
||||
|
||||
MimeInlineFile::~MimeInlineFile()
|
||||
{}
|
||||
|
||||
/* [1] --- */
|
||||
|
||||
|
||||
/* [2] Getters and Setters */
|
||||
|
||||
/* [2] --- */
|
||||
|
||||
|
||||
/* [3] Protected methods */
|
||||
|
||||
void MimeInlineFile::prepare()
|
||||
{
|
||||
this->header += "Content-Disposition: inline\r\n";
|
||||
|
||||
/* !!! IMPORTANT !!! */
|
||||
MimeFile::prepare();
|
||||
}
|
||||
|
||||
/* [3] --- */
|
||||
|
||||
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
/*
|
||||
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 MIMEINLINEFILE_H
|
||||
#define MIMEINLINEFILE_H
|
||||
|
||||
#include "mimefile.h"
|
||||
|
||||
#include "smtpexports.h"
|
||||
|
||||
class SMTP_EXPORT MimeInlineFile : public MimeFile
|
||||
{
|
||||
public:
|
||||
|
||||
/* [1] Constructors and Destructors */
|
||||
|
||||
MimeInlineFile(QFile *f);
|
||||
~MimeInlineFile();
|
||||
|
||||
/* [1] --- */
|
||||
|
||||
|
||||
/* [2] Getters and Setters */
|
||||
|
||||
/* [2] --- */
|
||||
|
||||
protected:
|
||||
|
||||
/* [3] Protected members */
|
||||
|
||||
/* [3] --- */
|
||||
|
||||
|
||||
/* [4] Protected methods */
|
||||
|
||||
virtual void prepare();
|
||||
|
||||
/* [4] --- */
|
||||
};
|
||||
|
||||
#endif // MIMEINLINEFILE_H
|
|
@ -1,257 +0,0 @@
|
|||
/*
|
||||
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 "mimemessage.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include "quotedprintable.h"
|
||||
#include <typeinfo>
|
||||
|
||||
/* [1] Constructors and Destructors */
|
||||
MimeMessage::MimeMessage(bool createAutoMimeContent) :
|
||||
hEncoding(MimePart::_8Bit)
|
||||
{
|
||||
if (createAutoMimeContent)
|
||||
this->content = new MimeMultiPart();
|
||||
|
||||
autoMimeContentCreated = createAutoMimeContent;
|
||||
}
|
||||
|
||||
MimeMessage::~MimeMessage()
|
||||
{
|
||||
if (this->autoMimeContentCreated)
|
||||
{
|
||||
this->autoMimeContentCreated = false;
|
||||
delete (this->content);
|
||||
}
|
||||
}
|
||||
|
||||
/* [1] --- */
|
||||
|
||||
|
||||
/* [2] Getters and Setters */
|
||||
MimePart& MimeMessage::getContent() {
|
||||
return *content;
|
||||
}
|
||||
|
||||
void MimeMessage::setContent(MimePart *content) {
|
||||
if (this->autoMimeContentCreated)
|
||||
{
|
||||
this->autoMimeContentCreated = false;
|
||||
delete (this->content);
|
||||
}
|
||||
this->content = content;
|
||||
}
|
||||
|
||||
void MimeMessage::setSender(EmailAddress* e)
|
||||
{
|
||||
this->sender = e;
|
||||
}
|
||||
|
||||
void MimeMessage::addRecipient(EmailAddress* rcpt, RecipientType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case To:
|
||||
recipientsTo << rcpt;
|
||||
break;
|
||||
case Cc:
|
||||
recipientsCc << rcpt;
|
||||
break;
|
||||
case Bcc:
|
||||
recipientsBcc << rcpt;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void MimeMessage::addTo(EmailAddress* rcpt) {
|
||||
this->recipientsTo << rcpt;
|
||||
}
|
||||
|
||||
void MimeMessage::addCc(EmailAddress* rcpt) {
|
||||
this->recipientsCc << rcpt;
|
||||
}
|
||||
|
||||
void MimeMessage::addBcc(EmailAddress* rcpt) {
|
||||
this->recipientsBcc << rcpt;
|
||||
}
|
||||
|
||||
void MimeMessage::setSubject(const QString & subject)
|
||||
{
|
||||
this->subject = subject;
|
||||
}
|
||||
|
||||
void MimeMessage::addPart(MimePart *part)
|
||||
{
|
||||
if (typeid(*content) == typeid(MimeMultiPart)) {
|
||||
((MimeMultiPart*) content)->addPart(part);
|
||||
};
|
||||
}
|
||||
|
||||
void MimeMessage::setHeaderEncoding(MimePart::Encoding hEnc)
|
||||
{
|
||||
this->hEncoding = hEnc;
|
||||
}
|
||||
|
||||
const EmailAddress & MimeMessage::getSender() const
|
||||
{
|
||||
return *sender;
|
||||
}
|
||||
|
||||
const QList<EmailAddress*> & MimeMessage::getRecipients(RecipientType type) const
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
default:
|
||||
case To:
|
||||
return recipientsTo;
|
||||
case Cc:
|
||||
return recipientsCc;
|
||||
case Bcc:
|
||||
return recipientsBcc;
|
||||
}
|
||||
}
|
||||
|
||||
const QString & MimeMessage::getSubject() const
|
||||
{
|
||||
return subject;
|
||||
}
|
||||
|
||||
const QList<MimePart*> & MimeMessage::getParts() const
|
||||
{
|
||||
if (typeid(*content) == typeid(MimeMultiPart)) {
|
||||
return ((MimeMultiPart*) content)->getParts();
|
||||
}
|
||||
else {
|
||||
QList<MimePart*> *res = new QList<MimePart*>();
|
||||
res->append(content);
|
||||
return *res;
|
||||
}
|
||||
}
|
||||
|
||||
/* [2] --- */
|
||||
|
||||
|
||||
/* [3] Public Methods */
|
||||
|
||||
QString MimeMessage::toString()
|
||||
{
|
||||
QString mime;
|
||||
|
||||
/* =========== MIME HEADER ============ */
|
||||
|
||||
/* ---------- Sender / From ----------- */
|
||||
mime = "From:";
|
||||
if (sender->getName() != "")
|
||||
{
|
||||
switch (hEncoding)
|
||||
{
|
||||
case MimePart::Base64:
|
||||
mime += " =?utf-8?B?" + QByteArray().append(sender->getName()).toBase64() + "?=";
|
||||
break;
|
||||
case MimePart::QuotedPrintable:
|
||||
mime += " =?utf-8?Q?" + QuotedPrintable::encode(QByteArray().append(sender->getName())).replace(' ', "_").replace(':',"=3A") + "?=";
|
||||
break;
|
||||
default:
|
||||
mime += " " + sender->getName();
|
||||
}
|
||||
}
|
||||
mime += " <" + sender->getAddress() + ">\r\n";
|
||||
/* ---------------------------------- */
|
||||
|
||||
|
||||
/* ------- Recipients / To ---------- */
|
||||
mime += "To:";
|
||||
QList<EmailAddress*>::iterator it; int i;
|
||||
for (i = 0, it = recipientsTo.begin(); it != recipientsTo.end(); ++it, ++i)
|
||||
{
|
||||
if (i != 0) { mime += ","; }
|
||||
|
||||
if ((*it)->getName() != "")
|
||||
{
|
||||
switch (hEncoding)
|
||||
{
|
||||
case MimePart::Base64:
|
||||
mime += " =?utf-8?B?" + QByteArray().append((*it)->getName()).toBase64() + "?=";
|
||||
break;
|
||||
case MimePart::QuotedPrintable:
|
||||
mime += " =?utf-8?Q?" + QuotedPrintable::encode(QByteArray().append((*it)->getName())).replace(' ', "_").replace(':',"=3A") + "?=";
|
||||
break;
|
||||
default:
|
||||
mime += " " + (*it)->getName();
|
||||
}
|
||||
}
|
||||
mime += " <" + (*it)->getAddress() + ">";
|
||||
}
|
||||
mime += "\r\n";
|
||||
/* ---------------------------------- */
|
||||
|
||||
/* ------- Recipients / Cc ---------- */
|
||||
if (recipientsCc.size() != 0) {
|
||||
mime += "Cc:";
|
||||
}
|
||||
for (i = 0, it = recipientsCc.begin(); it != recipientsCc.end(); ++it, ++i)
|
||||
{
|
||||
if (i != 0) { mime += ","; }
|
||||
|
||||
if ((*it)->getName() != "")
|
||||
{
|
||||
switch (hEncoding)
|
||||
{
|
||||
case MimePart::Base64:
|
||||
mime += " =?utf-8?B?" + QByteArray().append((*it)->getName()).toBase64() + "?=";
|
||||
break;
|
||||
case MimePart::QuotedPrintable:
|
||||
mime += " =?utf-8?Q?" + QuotedPrintable::encode(QByteArray().append((*it)->getName())).replace(' ', "_").replace(':',"=3A") + "?=";
|
||||
break;
|
||||
default:
|
||||
mime += " " + (*it)->getName();
|
||||
}
|
||||
}
|
||||
mime += " <" + (*it)->getAddress() + ">";
|
||||
}
|
||||
if (recipientsCc.size() != 0) {
|
||||
mime += "\r\n";
|
||||
}
|
||||
/* ---------------------------------- */
|
||||
|
||||
/* ------------ Subject ------------- */
|
||||
mime += "Subject: ";
|
||||
|
||||
|
||||
switch (hEncoding)
|
||||
{
|
||||
case MimePart::Base64:
|
||||
mime += "=?utf-8?B?" + QByteArray().append(subject).toBase64() + "?=";
|
||||
break;
|
||||
case MimePart::QuotedPrintable:
|
||||
mime += "=?utf-8?Q?" + QuotedPrintable::encode(QByteArray().append(subject)).replace(' ', "_").replace(':',"=3A") + "?=";
|
||||
break;
|
||||
default:
|
||||
mime += subject;
|
||||
}
|
||||
/* ---------------------------------- */
|
||||
|
||||
mime += "\r\n";
|
||||
mime += "MIME-Version: 1.0\r\n";
|
||||
|
||||
mime += content->toString();
|
||||
return mime;
|
||||
}
|
||||
|
||||
/* [3] --- */
|
|
@ -1,92 +0,0 @@
|
|||
/*
|
||||
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 MIMEMESSAGE_H
|
||||
#define MIMEMESSAGE_H
|
||||
|
||||
#include "mimepart.h"
|
||||
#include "mimemultipart.h"
|
||||
#include "emailaddress.h"
|
||||
#include <QList>
|
||||
|
||||
#include "smtpexports.h"
|
||||
|
||||
class SMTP_EXPORT MimeMessage : public QObject
|
||||
{
|
||||
public:
|
||||
|
||||
enum RecipientType {
|
||||
To, // primary
|
||||
Cc, // carbon copy
|
||||
Bcc // blind carbon copy
|
||||
};
|
||||
|
||||
/* [1] Constructors and Destructors */
|
||||
|
||||
MimeMessage(bool createAutoMimeConent = true);
|
||||
~MimeMessage();
|
||||
|
||||
/* [1] --- */
|
||||
|
||||
|
||||
/* [2] Getters and Setters */
|
||||
|
||||
void setSender(EmailAddress* e);
|
||||
void addRecipient(EmailAddress* rcpt, RecipientType type = To);
|
||||
void addTo(EmailAddress* rcpt);
|
||||
void addCc(EmailAddress* rcpt);
|
||||
void addBcc(EmailAddress* rcpt);
|
||||
void setSubject(const QString & subject);
|
||||
void addPart(MimePart* part);
|
||||
|
||||
void setHeaderEncoding(MimePart::Encoding);
|
||||
|
||||
const EmailAddress & getSender() const;
|
||||
const QList<EmailAddress*> & getRecipients(RecipientType type = To) const;
|
||||
const QString & getSubject() const;
|
||||
const QList<MimePart*> & getParts() const;
|
||||
|
||||
MimePart& getContent();
|
||||
void setContent(MimePart *content);
|
||||
/* [2] --- */
|
||||
|
||||
|
||||
/* [3] Public methods */
|
||||
|
||||
virtual QString toString();
|
||||
|
||||
/* [3] --- */
|
||||
|
||||
protected:
|
||||
|
||||
/* [4] Protected members */
|
||||
|
||||
EmailAddress* sender;
|
||||
QList<EmailAddress*> recipientsTo, recipientsCc, recipientsBcc;
|
||||
QString subject;
|
||||
MimePart *content;
|
||||
bool autoMimeContentCreated;
|
||||
|
||||
MimePart::Encoding hEncoding;
|
||||
|
||||
/* [4] --- */
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // MIMEMESSAGE_H
|
|
@ -1,78 +0,0 @@
|
|||
/*
|
||||
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 "mimemultipart.h"
|
||||
#include <QTime>
|
||||
#include <QCryptographicHash>
|
||||
|
||||
const QString MULTI_PART_NAMES[] = {
|
||||
"multipart/mixed", // Mixed
|
||||
"multipart/digest", // Digest
|
||||
"multipart/alternative", // Alternative
|
||||
"multipart/related", // Related
|
||||
"multipart/report", // Report
|
||||
"multipart/signed", // Signed
|
||||
"multipart/encrypted" // Encrypted
|
||||
};
|
||||
|
||||
MimeMultiPart::MimeMultiPart(MultiPartType type)
|
||||
{
|
||||
this->type = type;
|
||||
this->cType = MULTI_PART_NAMES[this->type];
|
||||
this->cEncoding = _8Bit;
|
||||
|
||||
QCryptographicHash md5(QCryptographicHash::Md5);
|
||||
md5.addData(QByteArray().append(qrand()));
|
||||
cBoundary = md5.result().toHex();
|
||||
}
|
||||
|
||||
MimeMultiPart::~MimeMultiPart() {
|
||||
|
||||
}
|
||||
|
||||
void MimeMultiPart::addPart(MimePart *part) {
|
||||
parts.append(part);
|
||||
}
|
||||
|
||||
const QList<MimePart*> & MimeMultiPart::getParts() const {
|
||||
return parts;
|
||||
}
|
||||
|
||||
void MimeMultiPart::prepare() {
|
||||
QList<MimePart*>::iterator it;
|
||||
|
||||
content = "";
|
||||
for (it = parts.begin(); it != parts.end(); it++) {
|
||||
content += "--" + cBoundary + "\r\n";
|
||||
(*it)->prepare();
|
||||
content += (*it)->toString();
|
||||
};
|
||||
|
||||
content += "--" + cBoundary + "--\r\n";
|
||||
|
||||
MimePart::prepare();
|
||||
}
|
||||
|
||||
void MimeMultiPart::setMimeType(const MultiPartType type) {
|
||||
this->type = type;
|
||||
this->cType = MULTI_PART_NAMES[type];
|
||||
}
|
||||
|
||||
MimeMultiPart::MultiPartType MimeMultiPart::getMimeType() const {
|
||||
return type;
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
/*
|
||||
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 MIMEMULTIPART_H
|
||||
#define MIMEMULTIPART_H
|
||||
|
||||
#include "mimepart.h"
|
||||
|
||||
#include "smtpexports.h"
|
||||
|
||||
class SMTP_EXPORT MimeMultiPart : public MimePart
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
/* [0] Enums */
|
||||
enum MultiPartType {
|
||||
Mixed = 0, // RFC 2046, section 5.1.3
|
||||
Digest = 1, // RFC 2046, section 5.1.5
|
||||
Alternative = 2, // RFC 2046, section 5.1.4
|
||||
Related = 3, // RFC 2387
|
||||
Report = 4, // RFC 6522
|
||||
Signed = 5, // RFC 1847, section 2.1
|
||||
Encrypted = 6 // RFC 1847, section 2.2
|
||||
};
|
||||
|
||||
/* [0] --- */
|
||||
|
||||
/* [1] Constructors and Destructors */
|
||||
MimeMultiPart(const MultiPartType type = Related);
|
||||
|
||||
~MimeMultiPart();
|
||||
|
||||
/* [1] --- */
|
||||
|
||||
/* [2] Getters and Setters */
|
||||
|
||||
void setMimeType(const MultiPartType type);
|
||||
MultiPartType getMimeType() const;
|
||||
|
||||
const QList<MimePart*> & getParts() const;
|
||||
|
||||
/* [2] --- */
|
||||
|
||||
/* [3] Public methods */
|
||||
|
||||
void addPart(MimePart *part);
|
||||
|
||||
virtual void prepare();
|
||||
|
||||
/* [3] --- */
|
||||
|
||||
protected:
|
||||
QList< MimePart* > parts;
|
||||
|
||||
MultiPartType type;
|
||||
|
||||
};
|
||||
|
||||
#endif // MIMEMULTIPART_H
|
|
@ -1,214 +0,0 @@
|
|||
/*
|
||||
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 "mimepart.h"
|
||||
#include "quotedprintable.h"
|
||||
|
||||
/* [1] Constructors and Destructors */
|
||||
|
||||
MimePart::MimePart()
|
||||
{
|
||||
cEncoding = _7Bit;
|
||||
prepared = false;
|
||||
cBoundary = "";
|
||||
}
|
||||
|
||||
MimePart::~MimePart()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* [1] --- */
|
||||
|
||||
|
||||
/* [2] Getters and Setters */
|
||||
|
||||
void MimePart::setContent(const QByteArray & content)
|
||||
{
|
||||
this->content = content;
|
||||
}
|
||||
|
||||
void MimePart::setHeader(const QString & header)
|
||||
{
|
||||
this->header = header;
|
||||
}
|
||||
|
||||
void MimePart::addHeaderLine(const QString & line)
|
||||
{
|
||||
this->header += line + "\r\n";
|
||||
}
|
||||
|
||||
const QString& MimePart::getHeader() const
|
||||
{
|
||||
return header;
|
||||
}
|
||||
|
||||
const QByteArray& MimePart::getContent() const
|
||||
{
|
||||
return content;
|
||||
}
|
||||
|
||||
void MimePart::setContentId(const QString & cId)
|
||||
{
|
||||
this->cId = cId;
|
||||
}
|
||||
|
||||
const QString & MimePart::getContentId() const
|
||||
{
|
||||
return this->cId;
|
||||
}
|
||||
|
||||
void MimePart::setContentName(const QString & cName)
|
||||
{
|
||||
this->cName = cName;
|
||||
}
|
||||
|
||||
const QString & MimePart::getContentName() const
|
||||
{
|
||||
return this->cName;
|
||||
}
|
||||
|
||||
void MimePart::setContentType(const QString & cType)
|
||||
{
|
||||
this->cType = cType;
|
||||
}
|
||||
|
||||
const QString & MimePart::getContentType() const
|
||||
{
|
||||
return this->cType;
|
||||
}
|
||||
|
||||
void MimePart::setCharset(const QString & charset)
|
||||
{
|
||||
this->cCharset = charset;
|
||||
}
|
||||
|
||||
const QString & MimePart::getCharset() const
|
||||
{
|
||||
return this->cCharset;
|
||||
}
|
||||
|
||||
void MimePart::setEncoding(Encoding enc)
|
||||
{
|
||||
this->cEncoding = enc;
|
||||
}
|
||||
|
||||
MimePart::Encoding MimePart::getEncoding() const
|
||||
{
|
||||
return this->cEncoding;
|
||||
}
|
||||
|
||||
MimeContentFormatter& MimePart::getContentFormatter()
|
||||
{
|
||||
return this->formatter;
|
||||
}
|
||||
|
||||
/* [2] --- */
|
||||
|
||||
|
||||
/* [3] Public methods */
|
||||
|
||||
QString MimePart::toString()
|
||||
{
|
||||
if (!prepared)
|
||||
prepare();
|
||||
|
||||
return mimeString;
|
||||
}
|
||||
|
||||
/* [3] --- */
|
||||
|
||||
|
||||
/* [4] Protected methods */
|
||||
|
||||
void MimePart::prepare()
|
||||
{
|
||||
mimeString = QString();
|
||||
|
||||
/* === Header Prepare === */
|
||||
|
||||
/* Content-Type */
|
||||
mimeString.append("Content-Type: ").append(cType);
|
||||
|
||||
if (cName != "")
|
||||
mimeString.append("; name=\"").append(cName).append("\"");
|
||||
|
||||
if (cCharset != "")
|
||||
mimeString.append("; charset=").append(cCharset);
|
||||
|
||||
if (cBoundary != "")
|
||||
mimeString.append("; boundary=").append(cBoundary);
|
||||
|
||||
mimeString.append("\r\n");
|
||||
/* ------------ */
|
||||
|
||||
/* Content-Transfer-Encoding */
|
||||
mimeString.append("Content-Transfer-Encoding: ");
|
||||
switch (cEncoding)
|
||||
{
|
||||
case _7Bit:
|
||||
mimeString.append("7bit\r\n");
|
||||
break;
|
||||
case _8Bit:
|
||||
mimeString.append("8bit\r\n");
|
||||
break;
|
||||
case Base64:
|
||||
mimeString.append("base64\r\n");
|
||||
break;
|
||||
case QuotedPrintable:
|
||||
mimeString.append("quoted-printable\r\n");
|
||||
break;
|
||||
}
|
||||
/* ------------------------ */
|
||||
|
||||
/* Content-Id */
|
||||
if (cId != NULL)
|
||||
mimeString.append("Content-ID: <").append(cId).append(">\r\n");
|
||||
/* ---------- */
|
||||
|
||||
/* Addition header lines */
|
||||
|
||||
mimeString.append(header).append("\r\n");
|
||||
|
||||
/* ------------------------- */
|
||||
|
||||
/* === End of Header Prepare === */
|
||||
|
||||
/* === Content === */
|
||||
switch (cEncoding)
|
||||
{
|
||||
case _7Bit:
|
||||
mimeString.append(QString(content).toLatin1());
|
||||
break;
|
||||
case _8Bit:
|
||||
mimeString.append(content);
|
||||
break;
|
||||
case Base64:
|
||||
mimeString.append(formatter.format(content.toBase64()));
|
||||
break;
|
||||
case QuotedPrintable:
|
||||
mimeString.append(formatter.format(QuotedPrintable::encode(content), true));
|
||||
break;
|
||||
}
|
||||
mimeString.append("\r\n");
|
||||
/* === End of Content === */
|
||||
|
||||
prepared = true;
|
||||
}
|
||||
|
||||
/* [4] --- */
|
|
@ -1,114 +0,0 @@
|
|||
/*
|
||||
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 MIMEPART_H
|
||||
#define MIMEPART_H
|
||||
|
||||
#include <QObject>
|
||||
#include "mimecontentformatter.h"
|
||||
|
||||
#include "smtpexports.h"
|
||||
|
||||
class SMTP_EXPORT MimePart : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
/* [0] Enumerations */
|
||||
enum Encoding {
|
||||
_7Bit,
|
||||
_8Bit,
|
||||
Base64,
|
||||
QuotedPrintable
|
||||
};
|
||||
|
||||
|
||||
/* [0] --- */
|
||||
|
||||
|
||||
/* [1] Constructors and Destructors */
|
||||
|
||||
MimePart();
|
||||
~MimePart();
|
||||
|
||||
/* [1] --- */
|
||||
|
||||
|
||||
/* [2] Getters and Setters */
|
||||
|
||||
const QString& getHeader() const;
|
||||
const QByteArray& getContent() const;
|
||||
|
||||
void setContent(const QByteArray & content);
|
||||
void setHeader(const QString & header);
|
||||
|
||||
void addHeaderLine(const QString & line);
|
||||
|
||||
void setContentId(const QString & cId);
|
||||
const QString & getContentId() const;
|
||||
|
||||
void setContentName(const QString & cName);
|
||||
const QString & getContentName() const;
|
||||
|
||||
void setContentType(const QString & cType);
|
||||
const QString & getContentType() const;
|
||||
|
||||
void setCharset(const QString & charset);
|
||||
const QString & getCharset() const;
|
||||
|
||||
void setEncoding(Encoding enc);
|
||||
Encoding getEncoding() const;
|
||||
|
||||
MimeContentFormatter& getContentFormatter();
|
||||
|
||||
/* [2] --- */
|
||||
|
||||
|
||||
/* [3] Public methods */
|
||||
|
||||
virtual QString toString();
|
||||
|
||||
virtual void prepare();
|
||||
|
||||
/* [3] --- */
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
/* [4] Protected members */
|
||||
|
||||
QString header;
|
||||
QByteArray content;
|
||||
|
||||
QString cId;
|
||||
QString cName;
|
||||
QString cType;
|
||||
QString cCharset;
|
||||
QString cBoundary;
|
||||
Encoding cEncoding;
|
||||
|
||||
QString mimeString;
|
||||
bool prepared;
|
||||
|
||||
MimeContentFormatter formatter;
|
||||
|
||||
/* [4] --- */
|
||||
};
|
||||
|
||||
#endif // MIMEPART_H
|
|
@ -1,62 +0,0 @@
|
|||
/*
|
||||
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 "mimetext.h"
|
||||
|
||||
/* [1] Constructors and Destructors */
|
||||
|
||||
MimeText::MimeText(const QString &txt)
|
||||
{
|
||||
this->text = txt;
|
||||
this->cType = "text/plain";
|
||||
this->cCharset = "utf-8";
|
||||
this->cEncoding = _8Bit;
|
||||
}
|
||||
|
||||
MimeText::~MimeText() { }
|
||||
|
||||
/* [1] --- */
|
||||
|
||||
|
||||
/* [2] Getters and Setters */
|
||||
|
||||
void MimeText::setText(const QString & text)
|
||||
{
|
||||
this->text = text;
|
||||
}
|
||||
|
||||
const QString & MimeText::getText() const
|
||||
{
|
||||
return text;
|
||||
}
|
||||
|
||||
/* [2] --- */
|
||||
|
||||
|
||||
/* [3] Protected Methods */
|
||||
|
||||
void MimeText::prepare()
|
||||
{
|
||||
this->content.clear();
|
||||
this->content.append(text);
|
||||
|
||||
/* !!! IMPORTANT !!! */
|
||||
MimePart::prepare();
|
||||
}
|
||||
|
||||
/* [3] --- */
|
|
@ -1,62 +0,0 @@
|
|||
/*
|
||||
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 MIMETEXT_H
|
||||
#define MIMETEXT_H
|
||||
|
||||
#include "mimepart.h"
|
||||
|
||||
#include "smtpexports.h"
|
||||
|
||||
class SMTP_EXPORT MimeText : public MimePart
|
||||
{
|
||||
public:
|
||||
|
||||
/* [1] Constructors and Destructors */
|
||||
|
||||
MimeText(const QString &text = "");
|
||||
~MimeText();
|
||||
|
||||
/* [1] --- */
|
||||
|
||||
|
||||
/* [2] Getters and Setters*/
|
||||
|
||||
void setText(const QString & text);
|
||||
|
||||
const QString & getText() const;
|
||||
|
||||
/* [2] --- */
|
||||
|
||||
protected:
|
||||
|
||||
/* [3] Protected members */
|
||||
|
||||
QString text;
|
||||
/* [3] --- */
|
||||
|
||||
|
||||
/* [4] Protected methods */
|
||||
|
||||
void prepare();
|
||||
|
||||
/* [4] --- */
|
||||
|
||||
};
|
||||
|
||||
#endif // MIMETEXT_H
|
|
@ -1,69 +0,0 @@
|
|||
/*
|
||||
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 "quotedprintable.h"
|
||||
|
||||
QString QuotedPrintable::encode(const QByteArray &input)
|
||||
{
|
||||
QString output;
|
||||
|
||||
char byte;
|
||||
const char hex[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
|
||||
|
||||
for (int i = 0; i < input.length() ; ++i)
|
||||
{
|
||||
byte = input[i];
|
||||
|
||||
if ((byte == 0x20) || ((byte >= 33) && (byte <= 126) && (byte != 61)))
|
||||
{
|
||||
output.append(byte);
|
||||
}
|
||||
else
|
||||
{
|
||||
output.append('=');
|
||||
output.append(hex[((byte >> 4) & 0x0F)]);
|
||||
output.append(hex[(byte & 0x0F)]);
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
QByteArray QuotedPrintable::decode(const QString &input)
|
||||
{
|
||||
// 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F
|
||||
const int hexVal[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 10, 11, 12, 13, 14, 15};
|
||||
|
||||
QByteArray output;
|
||||
|
||||
for (int i = 0; i < input.length(); ++i)
|
||||
{
|
||||
if (input.at(i).toLatin1() == '=')
|
||||
{
|
||||
output.append((hexVal[input.at(i + 1).toLatin1() - '0'] << 4) + hexVal[input.at(i + 2).toLatin1() - '0']);
|
||||
i += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
output.append(input.at(i).toLatin1());
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
/*
|
||||
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 QUOTEDPRINTABLE_H
|
||||
#define QUOTEDPRINTABLE_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QByteArray>
|
||||
|
||||
#include "smtpexports.h"
|
||||
|
||||
class SMTP_EXPORT QuotedPrintable : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
static QString encode(const QByteArray &input);
|
||||
static QByteArray decode(const QString &input);
|
||||
|
||||
private:
|
||||
QuotedPrintable();
|
||||
};
|
||||
|
||||
#endif // QUOTEDPRINTABLE_H
|
207
servatrice/src/smtp/qxtglobal.h
Normal file
207
servatrice/src/smtp/qxtglobal.h
Normal file
|
@ -0,0 +1,207 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) Qxt Foundation. Some rights reserved.
|
||||
**
|
||||
** This file is part of the QxtCore module of the Qxt library.
|
||||
**
|
||||
** This library is free software; you can redistribute it and/or modify it
|
||||
** under the terms of the Common Public License, version 1.0, as published
|
||||
** by IBM, and/or under the terms of the GNU Lesser General Public License,
|
||||
** version 2.1, as published by the Free Software Foundation.
|
||||
**
|
||||
** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
|
||||
** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
|
||||
** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
|
||||
** FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
** You should have received a copy of the CPL and the LGPL along with this
|
||||
** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files
|
||||
** included with the source distribution for more information.
|
||||
** If you did not receive a copy of the licenses, contact the Qxt Foundation.
|
||||
**
|
||||
** <http://libqxt.org> <foundation@libqxt.org>
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QXTGLOBAL_H
|
||||
#define QXTGLOBAL_H
|
||||
|
||||
#include <QtGlobal>
|
||||
|
||||
#define QXT_VERSION 0x000602
|
||||
#define QXT_VERSION_STR "0.6.2"
|
||||
|
||||
//--------------------------global macros------------------------------
|
||||
|
||||
#ifndef QXT_NO_MACROS
|
||||
|
||||
#endif // QXT_NO_MACROS
|
||||
|
||||
//--------------------------export macros------------------------------
|
||||
|
||||
#define QXT_DLLEXPORT DO_NOT_USE_THIS_ANYMORE
|
||||
|
||||
#if !defined(QXT_STATIC)
|
||||
# if defined(BUILD_QXT_CORE)
|
||||
# define QXT_CORE_EXPORT Q_DECL_EXPORT
|
||||
# else
|
||||
# define QXT_CORE_EXPORT Q_DECL_IMPORT
|
||||
# endif
|
||||
#else
|
||||
# define QXT_CORE_EXPORT
|
||||
#endif // BUILD_QXT_CORE
|
||||
|
||||
#if !defined(QXT_STATIC)
|
||||
# if defined(BUILD_QXT_GUI)
|
||||
# define QXT_GUI_EXPORT Q_DECL_EXPORT
|
||||
# else
|
||||
# define QXT_GUI_EXPORT Q_DECL_IMPORT
|
||||
# endif
|
||||
#else
|
||||
# define QXT_GUI_EXPORT
|
||||
#endif // BUILD_QXT_GUI
|
||||
|
||||
#if !defined(QXT_STATIC)
|
||||
# if defined(BUILD_QXT_NETWORK)
|
||||
# define QXT_NETWORK_EXPORT Q_DECL_EXPORT
|
||||
# else
|
||||
# define QXT_NETWORK_EXPORT Q_DECL_IMPORT
|
||||
# endif
|
||||
#else
|
||||
# define QXT_NETWORK_EXPORT
|
||||
#endif // BUILD_QXT_NETWORK
|
||||
|
||||
#if !defined(QXT_STATIC)
|
||||
# if defined(BUILD_QXT_SQL)
|
||||
# define QXT_SQL_EXPORT Q_DECL_EXPORT
|
||||
# else
|
||||
# define QXT_SQL_EXPORT Q_DECL_IMPORT
|
||||
# endif
|
||||
#else
|
||||
# define QXT_SQL_EXPORT
|
||||
#endif // BUILD_QXT_SQL
|
||||
|
||||
#if !defined(QXT_STATIC)
|
||||
# if defined(BUILD_QXT_WEB)
|
||||
# define QXT_WEB_EXPORT Q_DECL_EXPORT
|
||||
# else
|
||||
# define QXT_WEB_EXPORT Q_DECL_IMPORT
|
||||
# endif
|
||||
#else
|
||||
# define QXT_WEB_EXPORT
|
||||
#endif // BUILD_QXT_WEB
|
||||
|
||||
#if !defined(QXT_STATIC)
|
||||
# if defined(BUILD_QXT_BERKELEY)
|
||||
# define QXT_BERKELEY_EXPORT Q_DECL_EXPORT
|
||||
# else
|
||||
# define QXT_BERKELEY_EXPORT Q_DECL_IMPORT
|
||||
# endif
|
||||
#else
|
||||
# define QXT_BERKELEY_EXPORT
|
||||
#endif // BUILD_QXT_BERKELEY
|
||||
|
||||
#if !defined(QXT_STATIC)
|
||||
# if defined(BUILD_QXT_ZEROCONF)
|
||||
# define QXT_ZEROCONF_EXPORT Q_DECL_EXPORT
|
||||
# else
|
||||
# define QXT_ZEROCONF_EXPORT Q_DECL_IMPORT
|
||||
# endif
|
||||
#else
|
||||
# define QXT_ZEROCONF_EXPORT
|
||||
#endif // QXT_ZEROCONF_EXPORT
|
||||
|
||||
#if defined BUILD_QXT_CORE || defined BUILD_QXT_GUI || defined BUILD_QXT_SQL || defined BUILD_QXT_NETWORK || defined BUILD_QXT_WEB || defined BUILD_QXT_BERKELEY || defined BUILD_QXT_ZEROCONF
|
||||
# define BUILD_QXT
|
||||
#endif
|
||||
|
||||
QXT_CORE_EXPORT const char* qxtVersion();
|
||||
|
||||
#ifndef QT_BEGIN_NAMESPACE
|
||||
#define QT_BEGIN_NAMESPACE
|
||||
#endif
|
||||
|
||||
#ifndef QT_END_NAMESPACE
|
||||
#define QT_END_NAMESPACE
|
||||
#endif
|
||||
|
||||
#ifndef QT_FORWARD_DECLARE_CLASS
|
||||
#define QT_FORWARD_DECLARE_CLASS(Class) class Class;
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
** This file is derived from code bearing the following notice:
|
||||
** The sole author of this file, Adam Higerd, has explicitly disclaimed all
|
||||
** copyright interest and protection for the content within. This file has
|
||||
** been placed in the public domain according to United States copyright
|
||||
** statute and case law. In jurisdictions where this public domain dedication
|
||||
** is not legally recognized, anyone who receives a copy of this file is
|
||||
** permitted to use, modify, duplicate, and redistribute this file, in whole
|
||||
** or in part, with no restrictions or conditions. In these jurisdictions,
|
||||
** this file shall be copyright (C) 2006-2008 by Adam Higerd.
|
||||
****************************************************************************/
|
||||
|
||||
#define QXT_DECLARE_PRIVATE(PUB) friend class PUB##Private; QxtPrivateInterface<PUB, PUB##Private> qxt_d;
|
||||
#define QXT_DECLARE_PUBLIC(PUB) friend class PUB;
|
||||
#define QXT_INIT_PRIVATE(PUB) qxt_d.setPublic(this);
|
||||
#define QXT_D(PUB) PUB##Private& d = qxt_d()
|
||||
#define QXT_P(PUB) PUB& p = qxt_p()
|
||||
|
||||
template <typename PUB>
|
||||
class QxtPrivate
|
||||
{
|
||||
public:
|
||||
virtual ~QxtPrivate()
|
||||
{}
|
||||
inline void QXT_setPublic(PUB* pub)
|
||||
{
|
||||
qxt_p_ptr = pub;
|
||||
}
|
||||
|
||||
protected:
|
||||
inline PUB& qxt_p()
|
||||
{
|
||||
return *qxt_p_ptr;
|
||||
}
|
||||
inline const PUB& qxt_p() const
|
||||
{
|
||||
return *qxt_p_ptr;
|
||||
}
|
||||
|
||||
private:
|
||||
PUB* qxt_p_ptr;
|
||||
};
|
||||
|
||||
template <typename PUB, typename PVT>
|
||||
class QxtPrivateInterface
|
||||
{
|
||||
friend class QxtPrivate<PUB>;
|
||||
public:
|
||||
QxtPrivateInterface()
|
||||
{
|
||||
pvt = new PVT;
|
||||
}
|
||||
~QxtPrivateInterface()
|
||||
{
|
||||
delete pvt;
|
||||
}
|
||||
|
||||
inline void setPublic(PUB* pub)
|
||||
{
|
||||
pvt->QXT_setPublic(pub);
|
||||
}
|
||||
inline PVT& operator()()
|
||||
{
|
||||
return *static_cast<PVT*>(pvt);
|
||||
}
|
||||
inline const PVT& operator()() const
|
||||
{
|
||||
return *static_cast<PVT*>(pvt);
|
||||
}
|
||||
private:
|
||||
QxtPrivateInterface(const QxtPrivateInterface&) { }
|
||||
QxtPrivateInterface& operator=(const QxtPrivateInterface&) { }
|
||||
QxtPrivate<PUB>* pvt;
|
||||
};
|
||||
|
||||
#endif // QXT_GLOBAL
|
211
servatrice/src/smtp/qxthmac.cpp
Normal file
211
servatrice/src/smtp/qxthmac.cpp
Normal file
|
@ -0,0 +1,211 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) Qxt Foundation. Some rights reserved.
|
||||
**
|
||||
** This file is part of the QxtCore module of the Qxt library.
|
||||
**
|
||||
** This library is free software; you can redistribute it and/or modify it
|
||||
** under the terms of the Common Public License, version 1.0, as published
|
||||
** by IBM, and/or under the terms of the GNU Lesser General Public License,
|
||||
** version 2.1, as published by the Free Software Foundation.
|
||||
**
|
||||
** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
|
||||
** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
|
||||
** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
|
||||
** FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
** You should have received a copy of the CPL and the LGPL along with this
|
||||
** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files
|
||||
** included with the source distribution for more information.
|
||||
** If you did not receive a copy of the licenses, contact the Qxt Foundation.
|
||||
**
|
||||
** <http://libqxt.org> <foundation@libqxt.org>
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qxthmac.h"
|
||||
#include <QtGlobal>
|
||||
|
||||
#if QT_VERSION >= 0x040300
|
||||
|
||||
|
||||
/*
|
||||
\class QxtHmac
|
||||
|
||||
\inmodule QxtCore
|
||||
|
||||
\brief The QxtHmac class calculates keyed-Hash Message Authentication Codes
|
||||
|
||||
HMAC is a well-known algorithm for generating a message authentication code (MAC) that can be used to verify the
|
||||
integrity and authenticity of a message.
|
||||
|
||||
This class requires Qt 4.3.0 or greater.
|
||||
|
||||
To verify a message, the sender creates a MAC using a key, which is a secret known only to the sender and recipient,
|
||||
and the content of the message. This MAC is then sent along with the message. The recipient then creates another MAC
|
||||
using the shared key and the content of the message. If the two codes match, the message is verified.
|
||||
|
||||
HMAC has been used as a password encryption scheme. The final output of the HMAC algorithm depends on the shared key
|
||||
and an inner hash. This inner hash is generated from the message content and the key. To use HMAC as a password
|
||||
scheme, the key should be the username; the message should be the user's password. The authenticating party (for
|
||||
instance, a login server) only needs to store this inner hash generated by the innerHash() function. When requesting
|
||||
authentication, the user calculates a HMAC using this key and message and sends his username and this HMAC to the
|
||||
authenticator. The authenticator can then use verify() using the provided HMAC and the stored inner hash. When using
|
||||
this scheme, the password is never stored or transmitted in plain text.
|
||||
*/
|
||||
|
||||
#ifndef QXT_DOXYGEN_RUN
|
||||
class QxtHmacPrivate : public QxtPrivate<QxtHmac>
|
||||
{
|
||||
public:
|
||||
QXT_DECLARE_PUBLIC(QxtHmac)
|
||||
QxtHmacPrivate() : ohash(0), ihash(0) {}
|
||||
~QxtHmacPrivate()
|
||||
{
|
||||
// deleting NULL is safe, so no tests are needed here
|
||||
delete ohash;
|
||||
delete ihash;
|
||||
}
|
||||
QCryptographicHash* ohash;
|
||||
QCryptographicHash* ihash;
|
||||
QByteArray opad, ipad, result;
|
||||
QCryptographicHash::Algorithm algorithm;
|
||||
};
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* Constructs a QxtHmac object using the specified algorithm.
|
||||
*/
|
||||
QxtHmac::QxtHmac(QCryptographicHash::Algorithm algorithm)
|
||||
{
|
||||
QXT_INIT_PRIVATE(QxtHmac);
|
||||
qxt_d().ohash = new QCryptographicHash(algorithm);
|
||||
qxt_d().ihash = new QCryptographicHash(algorithm);
|
||||
qxt_d().algorithm = algorithm;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Sets the shared secret key for the message authentication code.
|
||||
*
|
||||
* Any data that had been processed using addData() will be discarded.
|
||||
*/
|
||||
void QxtHmac::setKey(QByteArray key)
|
||||
{
|
||||
// We make the assumption that all hashes use a 512-bit block size; as of Qt 4.4.0 this is true of all supported hash functions
|
||||
QxtHmacPrivate* d = &qxt_d();
|
||||
d->opad = QByteArray(64, 0x5c);
|
||||
d->ipad = QByteArray(64, 0x36);
|
||||
if (key.size() > 64)
|
||||
{
|
||||
key = QCryptographicHash::hash(key, d->algorithm);
|
||||
}
|
||||
for (int i = key.size() - 1; i >= 0; --i)
|
||||
{
|
||||
d->opad[i] = d->opad[i] ^ key[i];
|
||||
d->ipad[i] = d->ipad[i] ^ key[i];
|
||||
}
|
||||
reset();
|
||||
}
|
||||
|
||||
/*!
|
||||
* Resets the object.
|
||||
*
|
||||
* Any data that had been processed using addData() will be discarded.
|
||||
* The key, if set, will be preserved.
|
||||
*/
|
||||
void QxtHmac::reset()
|
||||
{
|
||||
QxtHmacPrivate* d = &qxt_d();
|
||||
d->ihash->reset();
|
||||
d->ihash->addData(d->ipad);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Returns the inner hash of the HMAC function.
|
||||
*
|
||||
* This hash can be stored in lieu of the shared secret on the authenticating side
|
||||
* and used for verifying an HMAC code. When used in this manner, HMAC can be used
|
||||
* to provide a form of secure password authentication. See the documentation above
|
||||
* for details.
|
||||
*/
|
||||
QByteArray QxtHmac::innerHash() const
|
||||
{
|
||||
return qxt_d().ihash->result();
|
||||
}
|
||||
|
||||
/*!
|
||||
* Returns the authentication code for the message.
|
||||
*/
|
||||
QByteArray QxtHmac::result()
|
||||
{
|
||||
QxtHmacPrivate* d = &qxt_d();
|
||||
Q_ASSERT(d->opad.size());
|
||||
if (d->result.size())
|
||||
return d->result;
|
||||
d->ohash->reset();
|
||||
d->ohash->addData(d->opad);
|
||||
d->ohash->addData(innerHash());
|
||||
d->result = d->ohash->result();
|
||||
return d->result;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Verifies the authentication code against a known inner hash.
|
||||
*
|
||||
* \sa innerHash()
|
||||
*/
|
||||
bool QxtHmac::verify(const QByteArray& otherInner)
|
||||
{
|
||||
result(); // populates d->result
|
||||
QxtHmacPrivate* d = &qxt_d();
|
||||
d->ohash->reset();
|
||||
d->ohash->addData(d->opad);
|
||||
d->ohash->addData(otherInner);
|
||||
return d->result == d->ohash->result();
|
||||
}
|
||||
|
||||
/*!
|
||||
* Adds the provided data to the message to be authenticated.
|
||||
*/
|
||||
void QxtHmac::addData(const char* data, int length)
|
||||
{
|
||||
Q_ASSERT(qxt_d().opad.size());
|
||||
qxt_d().ihash->addData(data, length);
|
||||
qxt_d().result.clear();
|
||||
}
|
||||
|
||||
/*!
|
||||
* Adds the provided data to the message to be authenticated.
|
||||
*/
|
||||
void QxtHmac::addData(const QByteArray& data)
|
||||
{
|
||||
addData(data.constData(), data.size());
|
||||
}
|
||||
|
||||
/*!
|
||||
* Returns the HMAC of the provided data using the specified key and hashing algorithm.
|
||||
*/
|
||||
QByteArray QxtHmac::hash(const QByteArray& key, const QByteArray& data, Algorithm algorithm)
|
||||
{
|
||||
QxtHmac hmac(algorithm);
|
||||
hmac.setKey(key);
|
||||
hmac.addData(data);
|
||||
return hmac.result();
|
||||
}
|
||||
|
||||
/*!
|
||||
* Verifies a HMAC against a known key and inner hash using the specified hashing algorithm.
|
||||
*/
|
||||
bool QxtHmac::verify(const QByteArray& key, const QByteArray& hmac, const QByteArray& inner, Algorithm algorithm)
|
||||
{
|
||||
QxtHmac calc(algorithm);
|
||||
calc.setKey(key);
|
||||
|
||||
QxtHmacPrivate* d = &calc.qxt_d();
|
||||
d->ohash->reset();
|
||||
d->ohash->addData(d->opad);
|
||||
d->ohash->addData(inner);
|
||||
return hmac == d->ohash->result();
|
||||
}
|
||||
|
||||
#endif
|
64
servatrice/src/smtp/qxthmac.h
Normal file
64
servatrice/src/smtp/qxthmac.h
Normal file
|
@ -0,0 +1,64 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) Qxt Foundation. Some rights reserved.
|
||||
**
|
||||
** This file is part of the QxtCore module of the Qxt library.
|
||||
**
|
||||
** This library is free software; you can redistribute it and/or modify it
|
||||
** under the terms of the Common Public License, version 1.0, as published
|
||||
** by IBM, and/or under the terms of the GNU Lesser General Public License,
|
||||
** version 2.1, as published by the Free Software Foundation.
|
||||
**
|
||||
** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
|
||||
** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
|
||||
** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
|
||||
** FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
** You should have received a copy of the CPL and the LGPL along with this
|
||||
** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files
|
||||
** included with the source distribution for more information.
|
||||
** If you did not receive a copy of the licenses, contact the Qxt Foundation.
|
||||
**
|
||||
** <http://libqxt.org> <foundation@libqxt.org>
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QXTHMAC_H
|
||||
#define QXTHMAC_H
|
||||
|
||||
#include <QtGlobal>
|
||||
|
||||
#if QT_VERSION < 0x040300
|
||||
# warning QxtHmac requires Qt 4.3.0 or greater
|
||||
#else
|
||||
|
||||
#include <QCryptographicHash>
|
||||
#include "qxtglobal.h"
|
||||
|
||||
class QxtHmacPrivate;
|
||||
class QXT_CORE_EXPORT QxtHmac
|
||||
{
|
||||
public:
|
||||
typedef QCryptographicHash::Algorithm Algorithm;
|
||||
|
||||
QxtHmac(QCryptographicHash::Algorithm algorithm);
|
||||
|
||||
void setKey(QByteArray key);
|
||||
void reset();
|
||||
|
||||
void addData(const char* data, int length);
|
||||
void addData(const QByteArray& data);
|
||||
|
||||
QByteArray innerHash() const;
|
||||
QByteArray result();
|
||||
bool verify(const QByteArray& otherInner);
|
||||
|
||||
static QByteArray hash(const QByteArray& key, const QByteArray& data, Algorithm algorithm);
|
||||
static bool verify(const QByteArray& key, const QByteArray& hmac, const QByteArray& inner, Algorithm algorithm);
|
||||
|
||||
private:
|
||||
QXT_DECLARE_PRIVATE(QxtHmac)
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
34
servatrice/src/smtp/qxtmail_p.h
Normal file
34
servatrice/src/smtp/qxtmail_p.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) Qxt Foundation. Some rights reserved.
|
||||
**
|
||||
** This file is part of the QxtWeb module of the Qxt library.
|
||||
**
|
||||
** This library is free software; you can redistribute it and/or modify it
|
||||
** under the terms of the Common Public License, version 1.0, as published
|
||||
** by IBM, and/or under the terms of the GNU Lesser General Public License,
|
||||
** version 2.1, as published by the Free Software Foundation.
|
||||
**
|
||||
** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
|
||||
** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
|
||||
** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
|
||||
** FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
** You should have received a copy of the CPL and the LGPL along with this
|
||||
** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files
|
||||
** included with the source distribution for more information.
|
||||
** If you did not receive a copy of the licenses, contact the Qxt Foundation.
|
||||
**
|
||||
** <http://libqxt.org> <foundation@libqxt.org>
|
||||
**
|
||||
****************************************************************************/
|
||||
#ifndef QXTMAIL_P_H
|
||||
#define QXTMAIL_P_H
|
||||
|
||||
#include <QByteArray>
|
||||
|
||||
#define QXT_MUST_QP(x) (x < char(32) || x > char(126) || x == '=' || x == '?')
|
||||
QByteArray qxt_fold_mime_header(const QString& key, const QString& value, QTextCodec* latin1,
|
||||
const QByteArray& prefix = QByteArray());
|
||||
|
||||
#endif // QXTMAIL_P_H
|
211
servatrice/src/smtp/qxtmailattachment.cpp
Normal file
211
servatrice/src/smtp/qxtmailattachment.cpp
Normal file
|
@ -0,0 +1,211 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) Qxt Foundation. Some rights reserved.
|
||||
**
|
||||
** This file is part of the QxtWeb module of the Qxt library.
|
||||
**
|
||||
** This library is free software; you can redistribute it and/or modify it
|
||||
** under the terms of the Common Public License, version 1.0, as published
|
||||
** by IBM, and/or under the terms of the GNU Lesser General Public License,
|
||||
** version 2.1, as published by the Free Software Foundation.
|
||||
**
|
||||
** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
|
||||
** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
|
||||
** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
|
||||
** FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
** You should have received a copy of the CPL and the LGPL along with this
|
||||
** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files
|
||||
** included with the source distribution for more information.
|
||||
** If you did not receive a copy of the licenses, contact the Qxt Foundation.
|
||||
**
|
||||
** <http://libqxt.org> <foundation@libqxt.org>
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
/*!
|
||||
* \class QxtMailAttachment
|
||||
* \inmodule QxtNetwork
|
||||
* \brief The QxtMailAttachment class represents an attachement to a QxtMailMessage
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
#include "qxtmailattachment.h"
|
||||
#include "qxtmail_p.h"
|
||||
#include <QTextCodec>
|
||||
#include <QBuffer>
|
||||
#include <QPointer>
|
||||
#include <QFile>
|
||||
#include <QtDebug>
|
||||
|
||||
struct QxtMailAttachmentPrivate : public QSharedData
|
||||
{
|
||||
QHash<QString, QString> extraHeaders;
|
||||
QString contentType;
|
||||
QPointer<QIODevice> content;
|
||||
bool deleteContent;
|
||||
|
||||
QxtMailAttachmentPrivate()
|
||||
{
|
||||
content = 0;
|
||||
deleteContent = false;
|
||||
contentType = "text/plain";
|
||||
}
|
||||
|
||||
~QxtMailAttachmentPrivate()
|
||||
{
|
||||
if (deleteContent && content)
|
||||
content->deleteLater();
|
||||
deleteContent = false;
|
||||
content = 0;
|
||||
}
|
||||
};
|
||||
|
||||
QxtMailAttachment::QxtMailAttachment()
|
||||
{
|
||||
qxt_d = new QxtMailAttachmentPrivate;
|
||||
}
|
||||
|
||||
QxtMailAttachment::QxtMailAttachment(const QxtMailAttachment& other) : qxt_d(other.qxt_d)
|
||||
{
|
||||
// trivial copy constructor
|
||||
}
|
||||
|
||||
QxtMailAttachment::QxtMailAttachment(const QByteArray& content, const QString& contentType)
|
||||
{
|
||||
qxt_d = new QxtMailAttachmentPrivate;
|
||||
setContentType(contentType);
|
||||
setContent(content);
|
||||
}
|
||||
|
||||
QxtMailAttachment::QxtMailAttachment(QIODevice* content, const QString& contentType)
|
||||
{
|
||||
qxt_d = new QxtMailAttachmentPrivate;
|
||||
setContentType(contentType);
|
||||
setContent(content);
|
||||
}
|
||||
|
||||
QxtMailAttachment& QxtMailAttachment::operator=(const QxtMailAttachment & other)
|
||||
{
|
||||
qxt_d = other.qxt_d;
|
||||
return *this;
|
||||
}
|
||||
|
||||
QxtMailAttachment::~QxtMailAttachment()
|
||||
{
|
||||
// trivial destructor
|
||||
}
|
||||
|
||||
QIODevice* QxtMailAttachment::content() const
|
||||
{
|
||||
return qxt_d->content;
|
||||
}
|
||||
|
||||
void QxtMailAttachment::setContent(const QByteArray& content)
|
||||
{
|
||||
if (qxt_d->deleteContent && qxt_d->content)
|
||||
qxt_d->content->deleteLater();
|
||||
qxt_d->content = new QBuffer;
|
||||
static_cast<QBuffer*>(qxt_d->content.data())->setData(content);
|
||||
}
|
||||
|
||||
void QxtMailAttachment::setContent(QIODevice* content)
|
||||
{
|
||||
if (qxt_d->deleteContent && qxt_d->content)
|
||||
qxt_d->content->deleteLater();
|
||||
qxt_d->content = content;
|
||||
}
|
||||
|
||||
bool QxtMailAttachment::deleteContent() const
|
||||
{
|
||||
return qxt_d->deleteContent;
|
||||
}
|
||||
|
||||
void QxtMailAttachment::setDeleteContent(bool enable)
|
||||
{
|
||||
qxt_d->deleteContent = enable;
|
||||
}
|
||||
|
||||
QString QxtMailAttachment::contentType() const
|
||||
{
|
||||
return qxt_d->contentType;
|
||||
}
|
||||
|
||||
void QxtMailAttachment::setContentType(const QString& contentType)
|
||||
{
|
||||
qxt_d->contentType = contentType;
|
||||
}
|
||||
|
||||
QHash<QString, QString> QxtMailAttachment::extraHeaders() const
|
||||
{
|
||||
return qxt_d->extraHeaders;
|
||||
}
|
||||
|
||||
QString QxtMailAttachment::extraHeader(const QString& key) const
|
||||
{
|
||||
return qxt_d->extraHeaders[key.toLower()];
|
||||
}
|
||||
|
||||
bool QxtMailAttachment::hasExtraHeader(const QString& key) const
|
||||
{
|
||||
return qxt_d->extraHeaders.contains(key.toLower());
|
||||
}
|
||||
|
||||
void QxtMailAttachment::setExtraHeader(const QString& key, const QString& value)
|
||||
{
|
||||
qxt_d->extraHeaders[key.toLower()] = value;
|
||||
}
|
||||
|
||||
void QxtMailAttachment::setExtraHeaders(const QHash<QString, QString>& a)
|
||||
{
|
||||
QHash<QString, QString>& headers = qxt_d->extraHeaders;
|
||||
headers.clear();
|
||||
foreach(const QString& key, a.keys())
|
||||
{
|
||||
headers[key.toLower()] = a[key];
|
||||
}
|
||||
}
|
||||
|
||||
void QxtMailAttachment::removeExtraHeader(const QString& key)
|
||||
{
|
||||
qxt_d->extraHeaders.remove(key.toLower());
|
||||
}
|
||||
|
||||
QByteArray QxtMailAttachment::mimeData()
|
||||
{
|
||||
QIODevice* c = content();
|
||||
if (!c)
|
||||
{
|
||||
qWarning() << "QxtMailAttachment::mimeData(): Content not set or already output";
|
||||
return QByteArray();
|
||||
}
|
||||
if (!c->isOpen() && !c->open(QIODevice::ReadOnly))
|
||||
{
|
||||
qWarning() << "QxtMailAttachment::mimeData(): Cannot open content for reading";
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
QTextCodec* latin1 = QTextCodec::codecForName("latin1");
|
||||
QByteArray rv = "Content-Type: " + qxt_d->contentType.toLatin1() + "\r\nContent-Transfer-Encoding: base64\r\n";
|
||||
foreach(const QString& r, qxt_d->extraHeaders.keys())
|
||||
{
|
||||
rv += qxt_fold_mime_header(r.toLatin1(), extraHeader(r), latin1);
|
||||
}
|
||||
rv += "\r\n";
|
||||
|
||||
while (!c->atEnd())
|
||||
{
|
||||
rv += c->read(57).toBase64() + "\r\n";
|
||||
}
|
||||
setContent((QIODevice*)0);
|
||||
return rv;
|
||||
}
|
||||
|
||||
QxtMailAttachment QxtMailAttachment::fromFile(const QString& filename)
|
||||
{
|
||||
QxtMailAttachment rv(new QFile(filename));
|
||||
rv.setDeleteContent(true);
|
||||
return rv;
|
||||
}
|
73
servatrice/src/smtp/qxtmailattachment.h
Normal file
73
servatrice/src/smtp/qxtmailattachment.h
Normal file
|
@ -0,0 +1,73 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) Qxt Foundation. Some rights reserved.
|
||||
**
|
||||
** This file is part of the QxtWeb module of the Qxt library.
|
||||
**
|
||||
** This library is free software; you can redistribute it and/or modify it
|
||||
** under the terms of the Common Public License, version 1.0, as published
|
||||
** by IBM, and/or under the terms of the GNU Lesser General Public License,
|
||||
** version 2.1, as published by the Free Software Foundation.
|
||||
**
|
||||
** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
|
||||
** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
|
||||
** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
|
||||
** FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
** You should have received a copy of the CPL and the LGPL along with this
|
||||
** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files
|
||||
** included with the source distribution for more information.
|
||||
** If you did not receive a copy of the licenses, contact the Qxt Foundation.
|
||||
**
|
||||
** <http://libqxt.org> <foundation@libqxt.org>
|
||||
**
|
||||
****************************************************************************/
|
||||
#ifndef QXTMAILATTACHMENT_H
|
||||
#define QXTMAILATTACHMENT_H
|
||||
|
||||
#include "qxtglobal.h"
|
||||
|
||||
#include <QStringList>
|
||||
#include <QHash>
|
||||
#include <QByteArray>
|
||||
#include <QMetaType>
|
||||
#include <QSharedDataPointer>
|
||||
#include <QIODevice>
|
||||
|
||||
class QxtMailAttachmentPrivate;
|
||||
class QXT_NETWORK_EXPORT QxtMailAttachment
|
||||
{
|
||||
public:
|
||||
QxtMailAttachment();
|
||||
QxtMailAttachment(const QxtMailAttachment& other);
|
||||
QxtMailAttachment(const QByteArray& content, const QString& contentType = QString("application/octet-stream"));
|
||||
QxtMailAttachment(QIODevice* content, const QString& contentType = QString("application/octet-stream"));
|
||||
QxtMailAttachment& operator=(const QxtMailAttachment& other);
|
||||
~QxtMailAttachment();
|
||||
static QxtMailAttachment fromFile(const QString& filename);
|
||||
|
||||
QIODevice* content() const;
|
||||
void setContent(const QByteArray& content);
|
||||
void setContent(QIODevice* content);
|
||||
|
||||
bool deleteContent() const;
|
||||
void setDeleteContent(bool enable);
|
||||
|
||||
QString contentType() const;
|
||||
void setContentType(const QString& contentType);
|
||||
|
||||
QHash<QString, QString> extraHeaders() const;
|
||||
QString extraHeader(const QString&) const;
|
||||
bool hasExtraHeader(const QString&) const;
|
||||
void setExtraHeader(const QString& key, const QString& value);
|
||||
void setExtraHeaders(const QHash<QString, QString>&);
|
||||
void removeExtraHeader(const QString& key);
|
||||
|
||||
QByteArray mimeData();
|
||||
|
||||
private:
|
||||
QSharedDataPointer<QxtMailAttachmentPrivate> qxt_d;
|
||||
};
|
||||
Q_DECLARE_TYPEINFO(QxtMailAttachment, Q_MOVABLE_TYPE);
|
||||
|
||||
#endif // QXTMAILATTACHMENT_H
|
537
servatrice/src/smtp/qxtmailmessage.cpp
Normal file
537
servatrice/src/smtp/qxtmailmessage.cpp
Normal file
|
@ -0,0 +1,537 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) Qxt Foundation. Some rights reserved.
|
||||
**
|
||||
** This file is part of the QxtWeb module of the Qxt library.
|
||||
**
|
||||
** This library is free software; you can redistribute it and/or modify it
|
||||
** under the terms of the Common Public License, version 1.0, as published
|
||||
** by IBM, and/or under the terms of the GNU Lesser General Public License,
|
||||
** version 2.1, as published by the Free Software Foundation.
|
||||
**
|
||||
** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
|
||||
** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
|
||||
** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
|
||||
** FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
** You should have received a copy of the CPL and the LGPL along with this
|
||||
** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files
|
||||
** included with the source distribution for more information.
|
||||
** If you did not receive a copy of the licenses, contact the Qxt Foundation.
|
||||
**
|
||||
** <http://libqxt.org> <foundation@libqxt.org>
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
/*!
|
||||
* \class QxtMailMessage
|
||||
* \inmodule QxtNetwork
|
||||
* \brief The QxtMailMessage class encapsulates an e-mail according to RFC 2822 and related specifications
|
||||
* TODO: {implicitshared}
|
||||
*/
|
||||
|
||||
|
||||
#include "qxtmailmessage.h"
|
||||
#include "qxtmail_p.h"
|
||||
#include <QTextCodec>
|
||||
#include <QUuid>
|
||||
#include <QDir>
|
||||
#include <QtDebug>
|
||||
|
||||
|
||||
struct QxtMailMessagePrivate : public QSharedData
|
||||
{
|
||||
QxtMailMessagePrivate() {}
|
||||
QxtMailMessagePrivate(const QxtMailMessagePrivate& other)
|
||||
: QSharedData(other), rcptTo(other.rcptTo), rcptCc(other.rcptCc), rcptBcc(other.rcptBcc),
|
||||
subject(other.subject), body(other.body), sender(other.sender),
|
||||
extraHeaders(other.extraHeaders), attachments(other.attachments) {}
|
||||
QStringList rcptTo, rcptCc, rcptBcc;
|
||||
QString subject, body, sender;
|
||||
QHash<QString, QString> extraHeaders;
|
||||
QHash<QString, QxtMailAttachment> attachments;
|
||||
mutable QByteArray boundary;
|
||||
};
|
||||
|
||||
QxtMailMessage::QxtMailMessage()
|
||||
{
|
||||
qxt_d = new QxtMailMessagePrivate;
|
||||
}
|
||||
|
||||
QxtMailMessage::QxtMailMessage(const QxtMailMessage& other) : qxt_d(other.qxt_d)
|
||||
{
|
||||
// trivial copy constructor
|
||||
}
|
||||
|
||||
QxtMailMessage::QxtMailMessage(const QString& sender, const QString& recipient)
|
||||
{
|
||||
qxt_d = new QxtMailMessagePrivate;
|
||||
setSender(sender);
|
||||
addRecipient(recipient);
|
||||
}
|
||||
|
||||
QxtMailMessage::~QxtMailMessage()
|
||||
{
|
||||
// trivial destructor
|
||||
}
|
||||
|
||||
QxtMailMessage& QxtMailMessage::operator=(const QxtMailMessage & other)
|
||||
{
|
||||
qxt_d = other.qxt_d;
|
||||
return *this;
|
||||
}
|
||||
|
||||
QString QxtMailMessage::sender() const
|
||||
{
|
||||
return qxt_d->sender;
|
||||
}
|
||||
|
||||
void QxtMailMessage::setSender(const QString& a)
|
||||
{
|
||||
qxt_d->sender = a;
|
||||
}
|
||||
|
||||
QString QxtMailMessage::subject() const
|
||||
{
|
||||
return qxt_d->subject;
|
||||
}
|
||||
|
||||
void QxtMailMessage::setSubject(const QString& a)
|
||||
{
|
||||
qxt_d->subject = a;
|
||||
}
|
||||
|
||||
QString QxtMailMessage::body() const
|
||||
{
|
||||
return qxt_d->body;
|
||||
}
|
||||
|
||||
void QxtMailMessage::setBody(const QString& a)
|
||||
{
|
||||
qxt_d->body = a;
|
||||
}
|
||||
|
||||
QStringList QxtMailMessage::recipients(QxtMailMessage::RecipientType type) const
|
||||
{
|
||||
if (type == Bcc)
|
||||
return qxt_d->rcptBcc;
|
||||
if (type == Cc)
|
||||
return qxt_d->rcptCc;
|
||||
return qxt_d->rcptTo;
|
||||
}
|
||||
|
||||
void QxtMailMessage::addRecipient(const QString& a, QxtMailMessage::RecipientType type)
|
||||
{
|
||||
if (type == Bcc)
|
||||
qxt_d->rcptBcc.append(a);
|
||||
else if (type == Cc)
|
||||
qxt_d->rcptCc.append(a);
|
||||
else
|
||||
qxt_d->rcptTo.append(a);
|
||||
}
|
||||
|
||||
void QxtMailMessage::removeRecipient(const QString& a)
|
||||
{
|
||||
qxt_d->rcptTo.removeAll(a);
|
||||
qxt_d->rcptCc.removeAll(a);
|
||||
qxt_d->rcptBcc.removeAll(a);
|
||||
}
|
||||
|
||||
QHash<QString, QString> QxtMailMessage::extraHeaders() const
|
||||
{
|
||||
return qxt_d->extraHeaders;
|
||||
}
|
||||
|
||||
QString QxtMailMessage::extraHeader(const QString& key) const
|
||||
{
|
||||
return qxt_d->extraHeaders[key.toLower()];
|
||||
}
|
||||
|
||||
bool QxtMailMessage::hasExtraHeader(const QString& key) const
|
||||
{
|
||||
return qxt_d->extraHeaders.contains(key.toLower());
|
||||
}
|
||||
|
||||
void QxtMailMessage::setExtraHeader(const QString& key, const QString& value)
|
||||
{
|
||||
qxt_d->extraHeaders[key.toLower()] = value;
|
||||
}
|
||||
|
||||
void QxtMailMessage::setExtraHeaders(const QHash<QString, QString>& a)
|
||||
{
|
||||
QHash<QString, QString>& headers = qxt_d->extraHeaders;
|
||||
headers.clear();
|
||||
foreach(const QString& key, a.keys())
|
||||
{
|
||||
headers[key.toLower()] = a[key];
|
||||
}
|
||||
}
|
||||
|
||||
void QxtMailMessage::removeExtraHeader(const QString& key)
|
||||
{
|
||||
qxt_d->extraHeaders.remove(key.toLower());
|
||||
}
|
||||
|
||||
QHash<QString, QxtMailAttachment> QxtMailMessage::attachments() const
|
||||
{
|
||||
return qxt_d->attachments;
|
||||
}
|
||||
|
||||
QxtMailAttachment QxtMailMessage::attachment(const QString& filename) const
|
||||
{
|
||||
return qxt_d->attachments[filename];
|
||||
}
|
||||
|
||||
void QxtMailMessage::addAttachment(const QString& filename, const QxtMailAttachment& attach)
|
||||
{
|
||||
if (qxt_d->attachments.contains(filename))
|
||||
{
|
||||
qWarning() << "QxtMailMessage::addAttachment: " << filename << " already in use";
|
||||
int i = 1;
|
||||
while (qxt_d->attachments.contains(filename + "." + QString::number(i)))
|
||||
{
|
||||
i++;
|
||||
}
|
||||
qxt_d->attachments[filename+"."+QString::number(i)] = attach;
|
||||
}
|
||||
else
|
||||
{
|
||||
qxt_d->attachments[filename] = attach;
|
||||
}
|
||||
}
|
||||
|
||||
void QxtMailMessage::removeAttachment(const QString& filename)
|
||||
{
|
||||
qxt_d->attachments.remove(filename);
|
||||
}
|
||||
|
||||
QByteArray qxt_fold_mime_header(const QString& key, const QString& value, QTextCodec* latin1, const QByteArray& prefix)
|
||||
{
|
||||
QByteArray rv = "";
|
||||
QByteArray line = key.toLatin1() + ": ";
|
||||
if (!prefix.isEmpty()) line += prefix;
|
||||
if (!value.contains("=?") && latin1->canEncode(value))
|
||||
{
|
||||
bool firstWord = true;
|
||||
foreach(const QByteArray& word, value.toLatin1().split(' '))
|
||||
{
|
||||
if (line.size() > 78)
|
||||
{
|
||||
rv = rv + line + "\r\n";
|
||||
line.clear();
|
||||
}
|
||||
if (firstWord)
|
||||
line += word;
|
||||
else
|
||||
line += " " + word;
|
||||
firstWord = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// The text cannot be losslessly encoded as Latin-1. Therefore, we
|
||||
// must use quoted-printable or base64 encoding. This is a quick
|
||||
// heuristic based on the first 100 characters to see which
|
||||
// encoding to use.
|
||||
QByteArray utf8 = value.toUtf8();
|
||||
int ct = utf8.length();
|
||||
int nonAscii = 0;
|
||||
for (int i = 0; i < ct && i < 100; i++)
|
||||
{
|
||||
if (QXT_MUST_QP(utf8[i])) nonAscii++;
|
||||
}
|
||||
if (nonAscii > 20)
|
||||
{
|
||||
// more than 20%-ish non-ASCII characters: use base64
|
||||
QByteArray base64 = utf8.toBase64();
|
||||
ct = base64.length();
|
||||
line += "=?utf-8?b?";
|
||||
for (int i = 0; i < ct; i += 4)
|
||||
{
|
||||
if (line.length() > 72)
|
||||
{
|
||||
rv += line + "?\r\n";
|
||||
line = " =?utf-8?b?";
|
||||
}
|
||||
line = line + base64.mid(i, 4);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// otherwise use Q-encoding
|
||||
line += "=?utf-8?q?";
|
||||
for (int i = 0; i < ct; i++)
|
||||
{
|
||||
if (line.length() > 73)
|
||||
{
|
||||
rv += line + "?\r\n";
|
||||
line = " =?utf-8?q?";
|
||||
}
|
||||
if (QXT_MUST_QP(utf8[i]) || utf8[i] == ' ')
|
||||
{
|
||||
line += "=" + utf8.mid(i, 1).toHex().toUpper();
|
||||
}
|
||||
else
|
||||
{
|
||||
line += utf8[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
line += "?="; // end encoded-word atom
|
||||
}
|
||||
return rv + line + "\r\n";
|
||||
}
|
||||
|
||||
QByteArray QxtMailMessage::rfc2822() const
|
||||
{
|
||||
// Use quoted-printable if requested
|
||||
bool useQuotedPrintable = (extraHeader("Content-Transfer-Encoding").toLower() == "quoted-printable");
|
||||
// Use base64 if requested
|
||||
bool useBase64 = (extraHeader("Content-Transfer-Encoding").toLower() == "base64");
|
||||
// Check to see if plain text is ASCII-clean; assume it isn't if QP or base64 was requested
|
||||
QTextCodec* latin1 = QTextCodec::codecForName("latin1");
|
||||
bool bodyIsAscii = latin1->canEncode(body()) && !useQuotedPrintable && !useBase64;
|
||||
|
||||
QHash<QString, QxtMailAttachment> attach = attachments();
|
||||
QByteArray rv;
|
||||
|
||||
if (!sender().isEmpty() && !hasExtraHeader("From"))
|
||||
{
|
||||
rv += qxt_fold_mime_header("From", sender(), latin1);
|
||||
}
|
||||
|
||||
if (!qxt_d->rcptTo.isEmpty())
|
||||
{
|
||||
rv += qxt_fold_mime_header("To", qxt_d->rcptTo.join(", "), latin1);
|
||||
}
|
||||
|
||||
if (!qxt_d->rcptCc.isEmpty())
|
||||
{
|
||||
rv += qxt_fold_mime_header("Cc", qxt_d->rcptCc.join(", "), latin1);
|
||||
}
|
||||
|
||||
if (!subject().isEmpty())
|
||||
{
|
||||
rv += qxt_fold_mime_header("Subject", subject(), latin1);
|
||||
}
|
||||
|
||||
if (!bodyIsAscii)
|
||||
{
|
||||
if (!hasExtraHeader("MIME-Version") && !attach.count())
|
||||
rv += "MIME-Version: 1.0\r\n";
|
||||
|
||||
// If no transfer encoding has been requested, guess.
|
||||
// Heuristic: If >20% of the first 100 characters aren't
|
||||
// 7-bit clean, use base64, otherwise use Q-P.
|
||||
if(!bodyIsAscii && !useQuotedPrintable && !useBase64)
|
||||
{
|
||||
QString b = body();
|
||||
int nonAscii = 0;
|
||||
int ct = b.length();
|
||||
for (int i = 0; i < ct && i < 100; i++)
|
||||
{
|
||||
if (QXT_MUST_QP(b[i])) nonAscii++;
|
||||
}
|
||||
useQuotedPrintable = !(nonAscii > 20);
|
||||
useBase64 = !useQuotedPrintable;
|
||||
}
|
||||
}
|
||||
|
||||
if (attach.count())
|
||||
{
|
||||
if (qxt_d->boundary.isEmpty())
|
||||
qxt_d->boundary = QUuid::createUuid().toString().toLatin1().replace("{", "").replace("}", "");
|
||||
if (!hasExtraHeader("MIME-Version"))
|
||||
rv += "MIME-Version: 1.0\r\n";
|
||||
if (!hasExtraHeader("Content-Type"))
|
||||
rv += "Content-Type: multipart/mixed; boundary=" + qxt_d->boundary + "\r\n";
|
||||
}
|
||||
else if (!bodyIsAscii && !hasExtraHeader("Content-Transfer-Encoding"))
|
||||
{
|
||||
if (!useQuotedPrintable)
|
||||
{
|
||||
// base64
|
||||
rv += "Content-Transfer-Encoding: base64\r\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
// quoted-printable
|
||||
rv += "Content-Transfer-Encoding: quoted-printable\r\n";
|
||||
}
|
||||
}
|
||||
|
||||
foreach(const QString& r, qxt_d->extraHeaders.keys())
|
||||
{
|
||||
if ((r.toLower() == "content-type" || r.toLower() == "content-transfer-encoding") && attach.count())
|
||||
{
|
||||
// Since we're in multipart mode, we'll be outputting this later
|
||||
continue;
|
||||
}
|
||||
rv += qxt_fold_mime_header(r.toLatin1(), extraHeader(r), latin1);
|
||||
}
|
||||
|
||||
rv += "\r\n";
|
||||
|
||||
if (attach.count())
|
||||
{
|
||||
// we're going to have attachments, so output the lead-in for the message body
|
||||
rv += "This is a message with multiple parts in MIME format.\r\n";
|
||||
rv += "--" + qxt_d->boundary + "\r\nContent-Type: ";
|
||||
if (hasExtraHeader("Content-Type"))
|
||||
rv += extraHeader("Content-Type") + "\r\n";
|
||||
else
|
||||
rv += "text/plain; charset=UTF-8\r\n";
|
||||
if (hasExtraHeader("Content-Transfer-Encoding"))
|
||||
{
|
||||
rv += "Content-Transfer-Encoding: " + extraHeader("Content-Transfer-Encoding") + "\r\n";
|
||||
}
|
||||
else if (!bodyIsAscii)
|
||||
{
|
||||
if (!useQuotedPrintable)
|
||||
{
|
||||
// base64
|
||||
rv += "Content-Transfer-Encoding: base64\r\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
// quoted-printable
|
||||
rv += "Content-Transfer-Encoding: quoted-printable\r\n";
|
||||
}
|
||||
}
|
||||
rv += "\r\n";
|
||||
}
|
||||
|
||||
if (bodyIsAscii)
|
||||
{
|
||||
QByteArray b = latin1->fromUnicode(body());
|
||||
int len = b.length();
|
||||
QByteArray line = "";
|
||||
QByteArray word = "";
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
if (b[i] == '\n' || b[i] == '\r')
|
||||
{
|
||||
if (line.isEmpty())
|
||||
{
|
||||
line = word;
|
||||
word = "";
|
||||
}
|
||||
else if (line.length() + word.length() + 1 <= 78)
|
||||
{
|
||||
line = line + ' ' + word;
|
||||
word = "";
|
||||
}
|
||||
if(line[0] == '.')
|
||||
rv += ".";
|
||||
rv += line + "\r\n";
|
||||
if ((b[i+1] == '\n' || b[i+1] == '\r') && b[i] != b[i+1])
|
||||
{
|
||||
// If we're looking at a CRLF pair, skip the second half
|
||||
i++;
|
||||
}
|
||||
line = word;
|
||||
}
|
||||
else if (b[i] == ' ')
|
||||
{
|
||||
if (line.length() + word.length() + 1 > 78)
|
||||
{
|
||||
if(line[0] == '.')
|
||||
rv += ".";
|
||||
rv += line + "\r\n";
|
||||
line = word;
|
||||
}
|
||||
else if (line.isEmpty())
|
||||
{
|
||||
line = word;
|
||||
}
|
||||
else
|
||||
{
|
||||
line = line + ' ' + word;
|
||||
}
|
||||
word = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
word += b[i];
|
||||
}
|
||||
}
|
||||
if (line.length() + word.length() + 1 > 78)
|
||||
{
|
||||
if(line[0] == '.')
|
||||
rv += ".";
|
||||
rv += line + "\r\n";
|
||||
line = word;
|
||||
}
|
||||
else if (!word.isEmpty())
|
||||
{
|
||||
line += ' ' + word;
|
||||
}
|
||||
if(!line.isEmpty()) {
|
||||
if(line[0] == '.')
|
||||
rv += ".";
|
||||
rv += line + "\r\n";
|
||||
}
|
||||
}
|
||||
else if (useQuotedPrintable)
|
||||
{
|
||||
QByteArray b = body().toUtf8();
|
||||
int ct = b.length();
|
||||
QByteArray line;
|
||||
for (int i = 0; i < ct; i++)
|
||||
{
|
||||
if(b[i] == '\n' || b[i] == '\r')
|
||||
{
|
||||
if(line[0] == '.')
|
||||
rv += ".";
|
||||
rv += line + "\r\n";
|
||||
line = "";
|
||||
if ((b[i+1] == '\n' || b[i+1] == '\r') && b[i] != b[i+1])
|
||||
{
|
||||
// If we're looking at a CRLF pair, skip the second half
|
||||
i++;
|
||||
}
|
||||
}
|
||||
else if (line.length() > 74)
|
||||
{
|
||||
rv += line + "=\r\n";
|
||||
line = "";
|
||||
}
|
||||
if (QXT_MUST_QP(b[i]))
|
||||
{
|
||||
line += "=" + b.mid(i, 1).toHex().toUpper();
|
||||
}
|
||||
else
|
||||
{
|
||||
line += b[i];
|
||||
}
|
||||
}
|
||||
if(!line.isEmpty()) {
|
||||
if(line[0] == '.')
|
||||
rv += ".";
|
||||
rv += line + "\r\n";
|
||||
}
|
||||
}
|
||||
else /* base64 */
|
||||
{
|
||||
QByteArray b = body().toUtf8().toBase64();
|
||||
int ct = b.length();
|
||||
for (int i = 0; i < ct; i += 78)
|
||||
{
|
||||
rv += b.mid(i, 78) + "\r\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (attach.count())
|
||||
{
|
||||
foreach(const QString& filename, attach.keys())
|
||||
{
|
||||
rv += "--" + qxt_d->boundary + "\r\n";
|
||||
rv += qxt_fold_mime_header("Content-Disposition", QDir(filename).dirName(), latin1, "attachment; filename=");
|
||||
rv += attach[filename].mimeData();
|
||||
}
|
||||
rv += "--" + qxt_d->boundary + "--\r\n";
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
85
servatrice/src/smtp/qxtmailmessage.h
Normal file
85
servatrice/src/smtp/qxtmailmessage.h
Normal file
|
@ -0,0 +1,85 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) Qxt Foundation. Some rights reserved.
|
||||
**
|
||||
** This file is part of the QxtWeb module of the Qxt library.
|
||||
**
|
||||
** This library is free software; you can redistribute it and/or modify it
|
||||
** under the terms of the Common Public License, version 1.0, as published
|
||||
** by IBM, and/or under the terms of the GNU Lesser General Public License,
|
||||
** version 2.1, as published by the Free Software Foundation.
|
||||
**
|
||||
** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
|
||||
** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
|
||||
** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
|
||||
** FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
** You should have received a copy of the CPL and the LGPL along with this
|
||||
** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files
|
||||
** included with the source distribution for more information.
|
||||
** If you did not receive a copy of the licenses, contact the Qxt Foundation.
|
||||
**
|
||||
** <http://libqxt.org> <foundation@libqxt.org>
|
||||
**
|
||||
****************************************************************************/
|
||||
#ifndef QXTMAILMESSAGE_H
|
||||
#define QXTMAILMESSAGE_H
|
||||
|
||||
#include "qxtglobal.h"
|
||||
#include "qxtmailattachment.h"
|
||||
|
||||
#include <QStringList>
|
||||
#include <QHash>
|
||||
#include <QMetaType>
|
||||
#include <QSharedDataPointer>
|
||||
|
||||
struct QxtMailMessagePrivate;
|
||||
class QXT_NETWORK_EXPORT QxtMailMessage
|
||||
{
|
||||
public:
|
||||
enum RecipientType
|
||||
{
|
||||
To,
|
||||
Cc,
|
||||
Bcc
|
||||
};
|
||||
|
||||
QxtMailMessage();
|
||||
QxtMailMessage(const QxtMailMessage& other);
|
||||
QxtMailMessage(const QString& sender, const QString& recipient);
|
||||
QxtMailMessage& operator=(const QxtMailMessage& other);
|
||||
~QxtMailMessage();
|
||||
|
||||
QString sender() const;
|
||||
void setSender(const QString&);
|
||||
|
||||
QString subject() const;
|
||||
void setSubject(const QString&);
|
||||
|
||||
QString body() const;
|
||||
void setBody(const QString&);
|
||||
|
||||
QStringList recipients(RecipientType type = To) const;
|
||||
void addRecipient(const QString&, RecipientType type = To);
|
||||
void removeRecipient(const QString&);
|
||||
|
||||
QHash<QString, QString> extraHeaders() const;
|
||||
QString extraHeader(const QString&) const;
|
||||
bool hasExtraHeader(const QString&) const;
|
||||
void setExtraHeader(const QString& key, const QString& value);
|
||||
void setExtraHeaders(const QHash<QString, QString>&);
|
||||
void removeExtraHeader(const QString& key);
|
||||
|
||||
QHash<QString, QxtMailAttachment> attachments() const;
|
||||
QxtMailAttachment attachment(const QString& filename) const;
|
||||
void addAttachment(const QString& filename, const QxtMailAttachment& attach);
|
||||
void removeAttachment(const QString& filename);
|
||||
|
||||
QByteArray rfc2822() const;
|
||||
|
||||
private:
|
||||
QSharedDataPointer<QxtMailMessagePrivate> qxt_d;
|
||||
};
|
||||
Q_DECLARE_TYPEINFO(QxtMailMessage, Q_MOVABLE_TYPE);
|
||||
|
||||
#endif // QXTMAIL_H
|
617
servatrice/src/smtp/qxtsmtp.cpp
Normal file
617
servatrice/src/smtp/qxtsmtp.cpp
Normal file
|
@ -0,0 +1,617 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) Qxt Foundation. Some rights reserved.
|
||||
**
|
||||
** This file is part of the QxtWeb module of the Qxt library.
|
||||
**
|
||||
** This library is free software; you can redistribute it and/or modify it
|
||||
** under the terms of the Common Public License, version 1.0, as published
|
||||
** by IBM, and/or under the terms of the GNU Lesser General Public License,
|
||||
** version 2.1, as published by the Free Software Foundation.
|
||||
**
|
||||
** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
|
||||
** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
|
||||
** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
|
||||
** FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
** You should have received a copy of the CPL and the LGPL along with this
|
||||
** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files
|
||||
** included with the source distribution for more information.
|
||||
** If you did not receive a copy of the licenses, contact the Qxt Foundation.
|
||||
**
|
||||
** <http://libqxt.org> <foundation@libqxt.org>
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
/*!
|
||||
* \class QxtSmtp
|
||||
* \inmodule QxtNetwork
|
||||
* \brief The QxtSmtp class implements the SMTP protocol for sending email
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "qxtsmtp.h"
|
||||
#include "qxtsmtp_p.h"
|
||||
#include "qxthmac.h"
|
||||
#include <QStringList>
|
||||
#include <QTcpSocket>
|
||||
#include <QNetworkInterface>
|
||||
#include <QSslSocket>
|
||||
|
||||
QxtSmtpPrivate::QxtSmtpPrivate() : QObject(0)
|
||||
{
|
||||
// empty ctor
|
||||
}
|
||||
|
||||
QxtSmtp::QxtSmtp(QObject* parent) : QObject(parent)
|
||||
{
|
||||
QXT_INIT_PRIVATE(QxtSmtp);
|
||||
qxt_d().state = QxtSmtpPrivate::Disconnected;
|
||||
qxt_d().nextID = 0;
|
||||
qxt_d().socket = new QSslSocket(this);
|
||||
QObject::connect(socket(), SIGNAL(encrypted()), this, SIGNAL(encrypted()));
|
||||
//QObject::connect(socket(), SIGNAL(encrypted()), &qxt_d(), SLOT(ehlo()));
|
||||
QObject::connect(socket(), SIGNAL(connected()), this, SIGNAL(connected()));
|
||||
QObject::connect(socket(), SIGNAL(disconnected()), this, SIGNAL(disconnected()));
|
||||
QObject::connect(socket(), SIGNAL(error(QAbstractSocket::SocketError)), &qxt_d(), SLOT(socketError(QAbstractSocket::SocketError)));
|
||||
QObject::connect(this, SIGNAL(authenticated()), &qxt_d(), SLOT(sendNext()));
|
||||
QObject::connect(socket(), SIGNAL(readyRead()), &qxt_d(), SLOT(socketRead()));
|
||||
}
|
||||
|
||||
QByteArray QxtSmtp::username() const
|
||||
{
|
||||
return qxt_d().username;
|
||||
}
|
||||
|
||||
void QxtSmtp::setUsername(const QByteArray& username)
|
||||
{
|
||||
qxt_d().username = username;
|
||||
}
|
||||
|
||||
QByteArray QxtSmtp::password() const
|
||||
{
|
||||
return qxt_d().password;
|
||||
}
|
||||
|
||||
void QxtSmtp::setPassword(const QByteArray& password)
|
||||
{
|
||||
qxt_d().password = password;
|
||||
}
|
||||
|
||||
int QxtSmtp::send(const QxtMailMessage& message)
|
||||
{
|
||||
int messageID = ++qxt_d().nextID;
|
||||
qxt_d().pending.append(qMakePair(messageID, message));
|
||||
if (qxt_d().state == QxtSmtpPrivate::Waiting)
|
||||
qxt_d().sendNext();
|
||||
return messageID;
|
||||
}
|
||||
|
||||
int QxtSmtp::pendingMessages() const
|
||||
{
|
||||
return qxt_d().pending.count();
|
||||
}
|
||||
|
||||
QTcpSocket* QxtSmtp::socket() const
|
||||
{
|
||||
return qxt_d().socket;
|
||||
}
|
||||
|
||||
void QxtSmtp::connectToHost(const QString& hostName, quint16 port)
|
||||
{
|
||||
qxt_d().useSecure = false;
|
||||
qxt_d().state = QxtSmtpPrivate::StartState;
|
||||
socket()->connectToHost(hostName, port);
|
||||
}
|
||||
|
||||
void QxtSmtp::connectToHost(const QHostAddress& address, quint16 port)
|
||||
{
|
||||
connectToHost(address.toString(), port);
|
||||
}
|
||||
|
||||
void QxtSmtp::disconnectFromHost()
|
||||
{
|
||||
socket()->disconnectFromHost();
|
||||
}
|
||||
|
||||
bool QxtSmtp::startTlsDisabled() const
|
||||
{
|
||||
return qxt_d().disableStartTLS;
|
||||
}
|
||||
|
||||
void QxtSmtp::setStartTlsDisabled(bool disable)
|
||||
{
|
||||
qxt_d().disableStartTLS = disable;
|
||||
}
|
||||
|
||||
QSslSocket* QxtSmtp::sslSocket() const
|
||||
{
|
||||
return qxt_d().socket;
|
||||
}
|
||||
|
||||
void QxtSmtp::connectToSecureHost(const QString& hostName, quint16 port)
|
||||
{
|
||||
qxt_d().useSecure = true;
|
||||
qxt_d().state = QxtSmtpPrivate::StartState;
|
||||
sslSocket()->connectToHostEncrypted(hostName, port);
|
||||
}
|
||||
|
||||
void QxtSmtp::connectToSecureHost(const QHostAddress& address, quint16 port)
|
||||
{
|
||||
connectToSecureHost(address.toString(), port);
|
||||
}
|
||||
|
||||
bool QxtSmtp::hasExtension(const QString& extension)
|
||||
{
|
||||
return qxt_d().extensions.contains(extension);
|
||||
}
|
||||
|
||||
QString QxtSmtp::extensionData(const QString& extension)
|
||||
{
|
||||
return qxt_d().extensions[extension];
|
||||
}
|
||||
|
||||
void QxtSmtpPrivate::socketError(QAbstractSocket::SocketError err)
|
||||
{
|
||||
if (err == QAbstractSocket::SslHandshakeFailedError)
|
||||
{
|
||||
emit qxt_p().encryptionFailed();
|
||||
emit qxt_p().encryptionFailed( socket->errorString().toLatin1() );
|
||||
}
|
||||
else if (state == StartState)
|
||||
{
|
||||
emit qxt_p().connectionFailed();
|
||||
emit qxt_p().connectionFailed( socket->errorString().toLatin1() );
|
||||
}
|
||||
}
|
||||
|
||||
void QxtSmtpPrivate::socketRead()
|
||||
{
|
||||
buffer += socket->readAll();
|
||||
while (true)
|
||||
{
|
||||
int pos = buffer.indexOf("\r\n");
|
||||
if (pos < 0) return;
|
||||
QByteArray line = buffer.left(pos);
|
||||
buffer = buffer.mid(pos + 2);
|
||||
QByteArray code = line.left(3);
|
||||
switch (state)
|
||||
{
|
||||
case StartState:
|
||||
if (code[0] != '2')
|
||||
{
|
||||
socket->disconnectFromHost();
|
||||
}
|
||||
else
|
||||
{
|
||||
ehlo();
|
||||
}
|
||||
break;
|
||||
case HeloSent:
|
||||
case EhloSent:
|
||||
case EhloGreetReceived:
|
||||
parseEhlo(code, (line[3] != ' '), line.mid(4));
|
||||
break;
|
||||
case StartTLSSent:
|
||||
if (code == "220")
|
||||
{
|
||||
socket->startClientEncryption();
|
||||
ehlo();
|
||||
}
|
||||
else
|
||||
{
|
||||
authenticate();
|
||||
}
|
||||
break;
|
||||
case AuthRequestSent:
|
||||
case AuthUsernameSent:
|
||||
if (authType == AuthPlain) authPlain();
|
||||
else if (authType == AuthLogin) authLogin();
|
||||
else authCramMD5(line.mid(4));
|
||||
break;
|
||||
case AuthSent:
|
||||
if (code[0] == '2')
|
||||
{
|
||||
state = Authenticated;
|
||||
emit qxt_p().authenticated();
|
||||
}
|
||||
else
|
||||
{
|
||||
state = Disconnected;
|
||||
emit qxt_p().authenticationFailed();
|
||||
emit qxt_p().authenticationFailed( line );
|
||||
emit socket->disconnectFromHost();
|
||||
}
|
||||
break;
|
||||
case MailToSent:
|
||||
case RcptAckPending:
|
||||
if (code[0] != '2') {
|
||||
emit qxt_p().mailFailed( pending.first().first, code.toInt() );
|
||||
emit qxt_p().mailFailed(pending.first().first, code.toInt(), line);
|
||||
// pending.removeFirst();
|
||||
// DO NOT remove it, the body sent state needs this message to assigned the next mail failed message that will
|
||||
// the sendNext
|
||||
// a reset will be sent to clear things out
|
||||
sendNext();
|
||||
state = BodySent;
|
||||
}
|
||||
else
|
||||
sendNextRcpt(code, line);
|
||||
break;
|
||||
case SendingBody:
|
||||
sendBody(code, line);
|
||||
break;
|
||||
case BodySent:
|
||||
if ( pending.count() )
|
||||
{
|
||||
// if you removeFirst in RcpActpending/MailToSent on an error, and the queue is now empty,
|
||||
// you will get into this state and then crash because no check is done. CHeck added but shouldnt
|
||||
// be necessary since I commented out the removeFirst
|
||||
if (code[0] != '2')
|
||||
{
|
||||
emit qxt_p().mailFailed(pending.first().first, code.toInt() );
|
||||
emit qxt_p().mailFailed(pending.first().first, code.toInt(), line);
|
||||
}
|
||||
else
|
||||
emit qxt_p().mailSent(pending.first().first);
|
||||
pending.removeFirst();
|
||||
}
|
||||
sendNext();
|
||||
break;
|
||||
case Resetting:
|
||||
if (code[0] != '2') {
|
||||
emit qxt_p().connectionFailed();
|
||||
emit qxt_p().connectionFailed( line );
|
||||
}
|
||||
else {
|
||||
state = Waiting;
|
||||
sendNext();
|
||||
}
|
||||
break;
|
||||
case Disconnected:
|
||||
case EhloExtensionsReceived:
|
||||
case EhloDone:
|
||||
case Authenticated:
|
||||
case Waiting:
|
||||
// only to make compiler happy
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QxtSmtpPrivate::ehlo()
|
||||
{
|
||||
QByteArray address = "127.0.0.1";
|
||||
foreach(const QHostAddress& addr, QNetworkInterface::allAddresses())
|
||||
{
|
||||
if (addr == QHostAddress::LocalHost || addr == QHostAddress::LocalHostIPv6)
|
||||
continue;
|
||||
address = addr.toString().toLatin1();
|
||||
break;
|
||||
}
|
||||
socket->write("ehlo " + address + "\r\n");
|
||||
extensions.clear();
|
||||
state = EhloSent;
|
||||
}
|
||||
|
||||
void QxtSmtpPrivate::parseEhlo(const QByteArray& code, bool cont, const QString& line)
|
||||
{
|
||||
if (code != "250")
|
||||
{
|
||||
// error!
|
||||
if (state != HeloSent)
|
||||
{
|
||||
// maybe let's try HELO
|
||||
socket->write("helo\r\n");
|
||||
state = HeloSent;
|
||||
}
|
||||
else
|
||||
{
|
||||
// nope
|
||||
socket->write("QUIT\r\n");
|
||||
socket->flush();
|
||||
socket->disconnectFromHost();
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (state != EhloGreetReceived)
|
||||
{
|
||||
if (!cont)
|
||||
{
|
||||
// greeting only, no extensions
|
||||
state = EhloDone;
|
||||
}
|
||||
else
|
||||
{
|
||||
// greeting followed by extensions
|
||||
state = EhloGreetReceived;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
extensions[line.section(' ', 0, 0).toUpper()] = line.section(' ', 1);
|
||||
if (!cont)
|
||||
state = EhloDone;
|
||||
}
|
||||
if (state != EhloDone) return;
|
||||
if (extensions.contains("STARTTLS") && !disableStartTLS)
|
||||
{
|
||||
startTLS();
|
||||
}
|
||||
else
|
||||
{
|
||||
authenticate();
|
||||
}
|
||||
}
|
||||
|
||||
void QxtSmtpPrivate::startTLS()
|
||||
{
|
||||
socket->write("starttls\r\n");
|
||||
state = StartTLSSent;
|
||||
}
|
||||
|
||||
void QxtSmtpPrivate::authenticate()
|
||||
{
|
||||
if (!extensions.contains("AUTH") || username.isEmpty() || password.isEmpty())
|
||||
{
|
||||
state = Authenticated;
|
||||
emit qxt_p().authenticated();
|
||||
}
|
||||
else
|
||||
{
|
||||
QStringList auth = extensions["AUTH"].toUpper().split(' ', QString::SkipEmptyParts);
|
||||
if (auth.contains("CRAM-MD5"))
|
||||
{
|
||||
authCramMD5();
|
||||
}
|
||||
else if (auth.contains("PLAIN"))
|
||||
{
|
||||
authPlain();
|
||||
}
|
||||
else if (auth.contains("LOGIN"))
|
||||
{
|
||||
authLogin();
|
||||
}
|
||||
else
|
||||
{
|
||||
state = Authenticated;
|
||||
emit qxt_p().authenticated();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QxtSmtpPrivate::authCramMD5(const QByteArray& challenge)
|
||||
{
|
||||
if (state != AuthRequestSent)
|
||||
{
|
||||
socket->write("auth cram-md5\r\n");
|
||||
authType = AuthCramMD5;
|
||||
state = AuthRequestSent;
|
||||
}
|
||||
else
|
||||
{
|
||||
QxtHmac hmac(QCryptographicHash::Md5);
|
||||
hmac.setKey(password);
|
||||
hmac.addData(QByteArray::fromBase64(challenge));
|
||||
QByteArray response = username + ' ' + hmac.result().toHex();
|
||||
socket->write(response.toBase64() + "\r\n");
|
||||
state = AuthSent;
|
||||
}
|
||||
}
|
||||
|
||||
void QxtSmtpPrivate::authPlain()
|
||||
{
|
||||
if (state != AuthRequestSent)
|
||||
{
|
||||
socket->write("auth plain\r\n");
|
||||
authType = AuthPlain;
|
||||
state = AuthRequestSent;
|
||||
}
|
||||
else
|
||||
{
|
||||
QByteArray auth;
|
||||
auth += '\0';
|
||||
auth += username;
|
||||
auth += '\0';
|
||||
auth += password;
|
||||
socket->write(auth.toBase64() + "\r\n");
|
||||
state = AuthSent;
|
||||
}
|
||||
}
|
||||
|
||||
void QxtSmtpPrivate::authLogin()
|
||||
{
|
||||
if (state != AuthRequestSent && state != AuthUsernameSent)
|
||||
{
|
||||
socket->write("auth login\r\n");
|
||||
authType = AuthLogin;
|
||||
state = AuthRequestSent;
|
||||
}
|
||||
else if (state == AuthRequestSent)
|
||||
{
|
||||
socket->write(username.toBase64() + "\r\n");
|
||||
state = AuthUsernameSent;
|
||||
}
|
||||
else
|
||||
{
|
||||
socket->write(password.toBase64() + "\r\n");
|
||||
state = AuthSent;
|
||||
}
|
||||
}
|
||||
|
||||
static QByteArray qxt_extract_address(const QString& address)
|
||||
{
|
||||
int parenDepth = 0;
|
||||
int addrStart = -1;
|
||||
bool inQuote = false;
|
||||
int ct = address.length();
|
||||
|
||||
for (int i = 0; i < ct; i++)
|
||||
{
|
||||
QChar ch = address[i];
|
||||
if (inQuote)
|
||||
{
|
||||
if (ch == '"')
|
||||
inQuote = false;
|
||||
}
|
||||
else if (addrStart != -1)
|
||||
{
|
||||
if (ch == '>')
|
||||
return address.mid(addrStart, (i - addrStart)).toLatin1();
|
||||
}
|
||||
else if (ch == '(')
|
||||
{
|
||||
parenDepth++;
|
||||
}
|
||||
else if (ch == ')')
|
||||
{
|
||||
parenDepth--;
|
||||
if (parenDepth < 0) parenDepth = 0;
|
||||
}
|
||||
else if (ch == '"')
|
||||
{
|
||||
if (parenDepth == 0)
|
||||
inQuote = true;
|
||||
}
|
||||
else if (ch == '<')
|
||||
{
|
||||
if (!inQuote && parenDepth == 0)
|
||||
addrStart = i + 1;
|
||||
}
|
||||
}
|
||||
return address.toLatin1();
|
||||
}
|
||||
|
||||
void QxtSmtpPrivate::sendNext()
|
||||
{
|
||||
if (state == Disconnected)
|
||||
{
|
||||
// leave the mail in the queue if not ready to send
|
||||
return;
|
||||
}
|
||||
|
||||
if (pending.isEmpty())
|
||||
{
|
||||
// if there are no additional mails to send, finish up
|
||||
state = Waiting;
|
||||
emit qxt_p().finished();
|
||||
return;
|
||||
}
|
||||
|
||||
if(state != Waiting) {
|
||||
state = Resetting;
|
||||
socket->write("rset\r\n");
|
||||
return;
|
||||
}
|
||||
const QxtMailMessage& msg = pending.first().second;
|
||||
rcptNumber = rcptAck = mailAck = 0;
|
||||
recipients = msg.recipients(QxtMailMessage::To) +
|
||||
msg.recipients(QxtMailMessage::Cc) +
|
||||
msg.recipients(QxtMailMessage::Bcc);
|
||||
if (recipients.count() == 0)
|
||||
{
|
||||
// can't send an e-mail with no recipients
|
||||
emit qxt_p().mailFailed(pending.first().first, QxtSmtp::NoRecipients );
|
||||
emit qxt_p().mailFailed(pending.first().first, QxtSmtp::NoRecipients, QByteArray( "e-mail has no recipients" ) );
|
||||
pending.removeFirst();
|
||||
sendNext();
|
||||
return;
|
||||
}
|
||||
// We explicitly use lowercase keywords because for some reason gmail
|
||||
// interprets any string starting with an uppercase R as a request
|
||||
// to renegotiate the SSL connection.
|
||||
socket->write("mail from:<" + qxt_extract_address(msg.sender()) + ">\r\n");
|
||||
if (extensions.contains("PIPELINING")) // almost all do nowadays
|
||||
{
|
||||
foreach(const QString& rcpt, recipients)
|
||||
{
|
||||
socket->write("rcpt to:<" + qxt_extract_address(rcpt) + ">\r\n");
|
||||
}
|
||||
state = RcptAckPending;
|
||||
}
|
||||
else
|
||||
{
|
||||
state = MailToSent;
|
||||
}
|
||||
}
|
||||
|
||||
void QxtSmtpPrivate::sendNextRcpt(const QByteArray& code, const QByteArray&line)
|
||||
{
|
||||
int messageID = pending.first().first;
|
||||
const QxtMailMessage& msg = pending.first().second;
|
||||
|
||||
if (code[0] != '2')
|
||||
{
|
||||
// on failure, emit a warning signal
|
||||
if (!mailAck)
|
||||
{
|
||||
emit qxt_p().senderRejected(messageID, msg.sender());
|
||||
emit qxt_p().senderRejected(messageID, msg.sender(), line );
|
||||
}
|
||||
else
|
||||
{
|
||||
emit qxt_p().recipientRejected(messageID, msg.sender());
|
||||
emit qxt_p().recipientRejected(messageID, msg.sender(), line);
|
||||
}
|
||||
}
|
||||
else if (!mailAck)
|
||||
{
|
||||
mailAck = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
rcptAck++;
|
||||
}
|
||||
|
||||
if (rcptNumber == recipients.count())
|
||||
{
|
||||
// all recipients have been sent
|
||||
if (rcptAck == 0)
|
||||
{
|
||||
// no recipients were considered valid
|
||||
emit qxt_p().mailFailed(messageID, code.toInt() );
|
||||
emit qxt_p().mailFailed(messageID, code.toInt(), line);
|
||||
pending.removeFirst();
|
||||
sendNext();
|
||||
}
|
||||
else
|
||||
{
|
||||
// at least one recipient was acknowledged, send mail body
|
||||
socket->write("data\r\n");
|
||||
state = SendingBody;
|
||||
}
|
||||
}
|
||||
else if (state != RcptAckPending)
|
||||
{
|
||||
// send the next recipient unless we're only waiting on acks
|
||||
socket->write("rcpt to:<" + qxt_extract_address(recipients[rcptNumber]) + ">\r\n");
|
||||
rcptNumber++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we're only waiting on acks, just count them
|
||||
rcptNumber++;
|
||||
}
|
||||
}
|
||||
|
||||
void QxtSmtpPrivate::sendBody(const QByteArray& code, const QByteArray & line)
|
||||
{
|
||||
int messageID = pending.first().first;
|
||||
const QxtMailMessage& msg = pending.first().second;
|
||||
|
||||
if (code[0] != '3')
|
||||
{
|
||||
emit qxt_p().mailFailed(messageID, code.toInt() );
|
||||
emit qxt_p().mailFailed(messageID, code.toInt(), line);
|
||||
pending.removeFirst();
|
||||
sendNext();
|
||||
return;
|
||||
}
|
||||
|
||||
socket->write(msg.rfc2822());
|
||||
socket->write(".\r\n");
|
||||
state = BodySent;
|
||||
}
|
111
servatrice/src/smtp/qxtsmtp.h
Normal file
111
servatrice/src/smtp/qxtsmtp.h
Normal file
|
@ -0,0 +1,111 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) Qxt Foundation. Some rights reserved.
|
||||
**
|
||||
** This file is part of the QxtWeb module of the Qxt library.
|
||||
**
|
||||
** This library is free software; you can redistribute it and/or modify it
|
||||
** under the terms of the Common Public License, version 1.0, as published
|
||||
** by IBM, and/or under the terms of the GNU Lesser General Public License,
|
||||
** version 2.1, as published by the Free Software Foundation.
|
||||
**
|
||||
** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
|
||||
** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
|
||||
** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
|
||||
** FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
** You should have received a copy of the CPL and the LGPL along with this
|
||||
** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files
|
||||
** included with the source distribution for more information.
|
||||
** If you did not receive a copy of the licenses, contact the Qxt Foundation.
|
||||
**
|
||||
** <http://libqxt.org> <foundation@libqxt.org>
|
||||
**
|
||||
****************************************************************************/
|
||||
#ifndef QXTSMTP_H
|
||||
#define QXTSMTP_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QHostAddress>
|
||||
#include <QString>
|
||||
|
||||
#include "qxtglobal.h"
|
||||
#include "qxtmailmessage.h"
|
||||
|
||||
class QTcpSocket;
|
||||
class QSslSocket;
|
||||
|
||||
class QxtSmtpPrivate;
|
||||
class QXT_NETWORK_EXPORT QxtSmtp : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum SmtpError
|
||||
{
|
||||
NoError,
|
||||
NoRecipients,
|
||||
CommandUnrecognized = 500,
|
||||
SyntaxError,
|
||||
CommandNotImplemented,
|
||||
BadSequence,
|
||||
ParameterNotImplemented,
|
||||
MailboxUnavailable = 550,
|
||||
UserNotLocal,
|
||||
MessageTooLarge,
|
||||
InvalidMailboxName,
|
||||
TransactionFailed
|
||||
};
|
||||
|
||||
QxtSmtp(QObject* parent = 0);
|
||||
|
||||
QByteArray username() const;
|
||||
void setUsername(const QByteArray& name);
|
||||
|
||||
QByteArray password() const;
|
||||
void setPassword(const QByteArray& password);
|
||||
|
||||
int send(const QxtMailMessage& message);
|
||||
int pendingMessages() const;
|
||||
|
||||
QTcpSocket* socket() const;
|
||||
void connectToHost(const QString& hostName, quint16 port = 25);
|
||||
void connectToHost(const QHostAddress& address, quint16 port = 25);
|
||||
void disconnectFromHost();
|
||||
|
||||
bool startTlsDisabled() const;
|
||||
void setStartTlsDisabled(bool disable);
|
||||
|
||||
QSslSocket* sslSocket() const;
|
||||
void connectToSecureHost(const QString& hostName, quint16 port = 465);
|
||||
void connectToSecureHost(const QHostAddress& address, quint16 port = 465);
|
||||
|
||||
bool hasExtension(const QString& extension);
|
||||
QString extensionData(const QString& extension);
|
||||
|
||||
Q_SIGNALS:
|
||||
void connected();
|
||||
void connectionFailed();
|
||||
void connectionFailed( const QByteArray & msg );
|
||||
void encrypted();
|
||||
void encryptionFailed();
|
||||
void encryptionFailed( const QByteArray & msg );
|
||||
void authenticated();
|
||||
void authenticationFailed();
|
||||
void authenticationFailed( const QByteArray & msg );
|
||||
|
||||
void senderRejected(int mailID, const QString& address );
|
||||
void senderRejected(int mailID, const QString& address, const QByteArray & msg );
|
||||
void recipientRejected(int mailID, const QString& address );
|
||||
void recipientRejected(int mailID, const QString& address, const QByteArray & msg );
|
||||
void mailFailed(int mailID, int errorCode);
|
||||
void mailFailed(int mailID, int errorCode, const QByteArray & msg);
|
||||
void mailSent(int mailID);
|
||||
|
||||
void finished();
|
||||
void disconnected();
|
||||
|
||||
private:
|
||||
QXT_DECLARE_PRIVATE(QxtSmtp)
|
||||
};
|
||||
|
||||
#endif // QXTSMTP_H
|
102
servatrice/src/smtp/qxtsmtp_p.h
Normal file
102
servatrice/src/smtp/qxtsmtp_p.h
Normal file
|
@ -0,0 +1,102 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) Qxt Foundation. Some rights reserved.
|
||||
**
|
||||
** This file is part of the QxtWeb module of the Qxt library.
|
||||
**
|
||||
** This library is free software; you can redistribute it and/or modify it
|
||||
** under the terms of the Common Public License, version 1.0, as published
|
||||
** by IBM, and/or under the terms of the GNU Lesser General Public License,
|
||||
** version 2.1, as published by the Free Software Foundation.
|
||||
**
|
||||
** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
|
||||
** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
|
||||
** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
|
||||
** FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
** You should have received a copy of the CPL and the LGPL along with this
|
||||
** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files
|
||||
** included with the source distribution for more information.
|
||||
** If you did not receive a copy of the licenses, contact the Qxt Foundation.
|
||||
**
|
||||
** <http://libqxt.org> <foundation@libqxt.org>
|
||||
**
|
||||
****************************************************************************/
|
||||
#ifndef QXTSMTP_P_H
|
||||
#define QXTSMTP_P_H
|
||||
|
||||
#include "qxtsmtp.h"
|
||||
#include <QHash>
|
||||
#include <QString>
|
||||
#include <QList>
|
||||
#include <QPair>
|
||||
|
||||
class QxtSmtpPrivate : public QObject, public QxtPrivate<QxtSmtp>
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
QxtSmtpPrivate();
|
||||
|
||||
QXT_DECLARE_PUBLIC(QxtSmtp)
|
||||
|
||||
enum SmtpState
|
||||
{
|
||||
Disconnected,
|
||||
StartState,
|
||||
EhloSent,
|
||||
EhloGreetReceived,
|
||||
EhloExtensionsReceived,
|
||||
EhloDone,
|
||||
HeloSent,
|
||||
StartTLSSent,
|
||||
AuthRequestSent,
|
||||
AuthUsernameSent,
|
||||
AuthSent,
|
||||
Authenticated,
|
||||
MailToSent,
|
||||
RcptAckPending,
|
||||
SendingBody,
|
||||
BodySent,
|
||||
Waiting,
|
||||
Resetting
|
||||
};
|
||||
|
||||
enum AuthType
|
||||
{
|
||||
AuthPlain,
|
||||
AuthLogin,
|
||||
AuthCramMD5
|
||||
};
|
||||
|
||||
bool useSecure, disableStartTLS;
|
||||
SmtpState state;// rather then an int use the enum. makes sure invalid states are entered at compile time, and makes debugging easier
|
||||
AuthType authType;
|
||||
QByteArray buffer, username, password;
|
||||
QHash<QString, QString> extensions;
|
||||
QList<QPair<int, QxtMailMessage> > pending;
|
||||
QStringList recipients;
|
||||
int nextID, rcptNumber, rcptAck;
|
||||
bool mailAck;
|
||||
|
||||
QSslSocket* socket;
|
||||
|
||||
void parseEhlo(const QByteArray& code, bool cont, const QString& line);
|
||||
void startTLS();
|
||||
void authenticate();
|
||||
|
||||
void authCramMD5(const QByteArray& challenge = QByteArray());
|
||||
void authPlain();
|
||||
void authLogin();
|
||||
|
||||
void sendNextRcpt(const QByteArray& code, const QByteArray & line);
|
||||
void sendBody(const QByteArray& code, const QByteArray & line);
|
||||
|
||||
public slots:
|
||||
void socketError(QAbstractSocket::SocketError err);
|
||||
void socketRead();
|
||||
|
||||
void ehlo();
|
||||
void sendNext();
|
||||
};
|
||||
|
||||
#endif // QXTSMTP_P_H
|
|
@ -1,489 +0,0 @@
|
|||
/*
|
||||
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 "smtpclient.h"
|
||||
|
||||
#include <QFileInfo>
|
||||
#include <QByteArray>
|
||||
|
||||
|
||||
/* [1] Constructors and destructors */
|
||||
|
||||
SmtpClient::SmtpClient(const QString & host, int port, ConnectionType connectionType) :
|
||||
socket(NULL),
|
||||
name("localhost"),
|
||||
authMethod(AuthPlain),
|
||||
connectionTimeout(5000),
|
||||
responseTimeout(5000),
|
||||
sendMessageTimeout(60000)
|
||||
{
|
||||
setConnectionType(connectionType);
|
||||
|
||||
this->host = host;
|
||||
this->port = port;
|
||||
|
||||
connect(socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
|
||||
this, SLOT(socketStateChanged(QAbstractSocket::SocketState)));
|
||||
connect(socket, SIGNAL(error(QAbstractSocket::SocketError)),
|
||||
this, SLOT(socketError(QAbstractSocket::SocketError)));
|
||||
connect(socket, SIGNAL(readyRead()),
|
||||
this, SLOT(socketReadyRead()));
|
||||
}
|
||||
|
||||
SmtpClient::~SmtpClient() {
|
||||
if (socket)
|
||||
delete socket;
|
||||
}
|
||||
|
||||
/* [1] --- */
|
||||
|
||||
|
||||
/* [2] Getters and Setters */
|
||||
|
||||
void SmtpClient::setUser(const QString &user)
|
||||
{
|
||||
this->user = user;
|
||||
}
|
||||
|
||||
void SmtpClient::setPassword(const QString &password)
|
||||
{
|
||||
this->password = password;
|
||||
}
|
||||
|
||||
void SmtpClient::setAuthMethod(AuthMethod method)
|
||||
{
|
||||
this->authMethod = method;
|
||||
}
|
||||
|
||||
void SmtpClient::setHost(const QString &host)
|
||||
{
|
||||
this->host = host;
|
||||
}
|
||||
|
||||
void SmtpClient::setPort(int port)
|
||||
{
|
||||
this->port = port;
|
||||
}
|
||||
|
||||
void SmtpClient::setConnectionType(ConnectionType ct)
|
||||
{
|
||||
this->connectionType = ct;
|
||||
|
||||
if (socket)
|
||||
delete socket;
|
||||
|
||||
switch (connectionType)
|
||||
{
|
||||
case TcpConnection:
|
||||
socket = new QTcpSocket(this);
|
||||
break;
|
||||
case SslConnection:
|
||||
case TlsConnection:
|
||||
socket = new QSslSocket(this);
|
||||
}
|
||||
}
|
||||
|
||||
const QString& SmtpClient::getHost() const
|
||||
{
|
||||
return this->host;
|
||||
}
|
||||
|
||||
const QString& SmtpClient::getUser() const
|
||||
{
|
||||
return this->user;
|
||||
}
|
||||
|
||||
const QString& SmtpClient::getPassword() const
|
||||
{
|
||||
return this->password;
|
||||
}
|
||||
|
||||
SmtpClient::AuthMethod SmtpClient::getAuthMethod() const
|
||||
{
|
||||
return this->authMethod;
|
||||
}
|
||||
|
||||
int SmtpClient::getPort() const
|
||||
{
|
||||
return this->port;
|
||||
}
|
||||
|
||||
SmtpClient::ConnectionType SmtpClient::getConnectionType() const
|
||||
{
|
||||
return connectionType;
|
||||
}
|
||||
|
||||
const QString& SmtpClient::getName() const
|
||||
{
|
||||
return this->name;
|
||||
}
|
||||
|
||||
void SmtpClient::setName(const QString &name)
|
||||
{
|
||||
this->name = name;
|
||||
}
|
||||
|
||||
const QString & SmtpClient::getResponseText() const
|
||||
{
|
||||
return responseText;
|
||||
}
|
||||
|
||||
int SmtpClient::getResponseCode() const
|
||||
{
|
||||
return responseCode;
|
||||
}
|
||||
|
||||
QTcpSocket* SmtpClient::getSocket() {
|
||||
return socket;
|
||||
}
|
||||
|
||||
int SmtpClient::getConnectionTimeout() const
|
||||
{
|
||||
return connectionTimeout;
|
||||
}
|
||||
|
||||
void SmtpClient::setConnectionTimeout(int msec)
|
||||
{
|
||||
connectionTimeout = msec;
|
||||
}
|
||||
|
||||
int SmtpClient::getResponseTimeout() const
|
||||
{
|
||||
return responseTimeout;
|
||||
}
|
||||
|
||||
void SmtpClient::setResponseTimeout(int msec)
|
||||
{
|
||||
responseTimeout = msec;
|
||||
}
|
||||
int SmtpClient::getSendMessageTimeout() const
|
||||
{
|
||||
return sendMessageTimeout;
|
||||
}
|
||||
void SmtpClient::setSendMessageTimeout(int msec)
|
||||
{
|
||||
sendMessageTimeout = msec;
|
||||
}
|
||||
|
||||
/* [2] --- */
|
||||
|
||||
|
||||
/* [3] Public methods */
|
||||
|
||||
bool SmtpClient::connectToHost()
|
||||
{
|
||||
switch (connectionType)
|
||||
{
|
||||
case TlsConnection:
|
||||
case TcpConnection:
|
||||
socket->connectToHost(host, port);
|
||||
break;
|
||||
case SslConnection:
|
||||
((QSslSocket*) socket)->connectToHostEncrypted(host, port);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
// Tries to connect to server
|
||||
if (!socket->waitForConnected(connectionTimeout))
|
||||
{
|
||||
emit smtpError(ConnectionTimeoutError);
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Wait for the server's response
|
||||
waitForResponse();
|
||||
|
||||
// If the response code is not 220 (Service ready)
|
||||
// means that is something wrong with the server
|
||||
if (responseCode != 220)
|
||||
{
|
||||
emit smtpError(ServerError);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Send a EHLO/HELO message to the server
|
||||
// The client's first command must be EHLO/HELO
|
||||
sendMessage("EHLO " + name);
|
||||
|
||||
// Wait for the server's response
|
||||
waitForResponse();
|
||||
|
||||
// The response code needs to be 250.
|
||||
if (responseCode != 250) {
|
||||
emit smtpError(ServerError);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (connectionType == TlsConnection) {
|
||||
// send a request to start TLS handshake
|
||||
sendMessage("STARTTLS");
|
||||
|
||||
// Wait for the server's response
|
||||
waitForResponse();
|
||||
|
||||
// The response code needs to be 220.
|
||||
if (responseCode != 220) {
|
||||
emit smtpError(ServerError);
|
||||
return false;
|
||||
};
|
||||
|
||||
((QSslSocket*) socket)->startClientEncryption();
|
||||
|
||||
if (!((QSslSocket*) socket)->waitForEncrypted(connectionTimeout)) {
|
||||
qDebug() << ((QSslSocket*) socket)->errorString();
|
||||
emit smtpError(ConnectionTimeoutError);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Send ELHO one more time
|
||||
sendMessage("EHLO " + name);
|
||||
|
||||
// Wait for the server's response
|
||||
waitForResponse();
|
||||
|
||||
// The response code needs to be 250.
|
||||
if (responseCode != 250) {
|
||||
emit smtpError(ServerError);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ResponseTimeoutException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
catch (SendMessageTimeoutException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// If no errors occured the function returns true.
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SmtpClient::login()
|
||||
{
|
||||
return login(user, password, authMethod);
|
||||
}
|
||||
|
||||
bool SmtpClient::login(const QString &user, const QString &password, AuthMethod method)
|
||||
{
|
||||
try {
|
||||
if (method == AuthPlain)
|
||||
{
|
||||
// Sending command: AUTH PLAIN base64('\0' + username + '\0' + password)
|
||||
sendMessage("AUTH PLAIN " + QByteArray().append((char) 0).append(user).append((char) 0).append(password).toBase64());
|
||||
|
||||
// Wait for the server's response
|
||||
waitForResponse();
|
||||
|
||||
// If the response is not 235 then the authentication was faild
|
||||
if (responseCode != 235)
|
||||
{
|
||||
emit smtpError(AuthenticationFailedError);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (method == AuthLogin)
|
||||
{
|
||||
// Sending command: AUTH LOGIN
|
||||
sendMessage("AUTH LOGIN");
|
||||
|
||||
// Wait for 334 response code
|
||||
waitForResponse();
|
||||
if (responseCode != 334) { emit smtpError(AuthenticationFailedError); return false; }
|
||||
|
||||
// Send the username in base64
|
||||
sendMessage(QByteArray().append(user).toBase64());
|
||||
|
||||
// Wait for 334
|
||||
waitForResponse();
|
||||
if (responseCode != 334) { emit smtpError(AuthenticationFailedError); return false; }
|
||||
|
||||
// Send the password in base64
|
||||
sendMessage(QByteArray().append(password).toBase64());
|
||||
|
||||
// Wait for the server's responce
|
||||
waitForResponse();
|
||||
|
||||
// If the response is not 235 then the authentication was faild
|
||||
if (responseCode != 235)
|
||||
{
|
||||
emit smtpError(AuthenticationFailedError);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ResponseTimeoutException e)
|
||||
{
|
||||
// Responce Timeout exceeded
|
||||
emit smtpError(AuthenticationFailedError);
|
||||
return false;
|
||||
}
|
||||
catch (SendMessageTimeoutException)
|
||||
{
|
||||
// Send Timeout exceeded
|
||||
emit smtpError(AuthenticationFailedError);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SmtpClient::sendMail(MimeMessage& email)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Send the MAIL command with the sender
|
||||
sendMessage("MAIL FROM: <" + email.getSender().getAddress() + ">");
|
||||
|
||||
waitForResponse();
|
||||
|
||||
if (responseCode != 250) return false;
|
||||
|
||||
// Send RCPT command for each recipient
|
||||
QList<EmailAddress*>::const_iterator it, itEnd;
|
||||
// To (primary recipients)
|
||||
for (it = email.getRecipients().begin(), itEnd = email.getRecipients().end();
|
||||
it != itEnd; ++it)
|
||||
{
|
||||
sendMessage("RCPT TO: <" + (*it)->getAddress() + ">");
|
||||
waitForResponse();
|
||||
|
||||
if (responseCode != 250) return false;
|
||||
}
|
||||
|
||||
// Cc (carbon copy)
|
||||
for (it = email.getRecipients(MimeMessage::Cc).begin(), itEnd = email.getRecipients(MimeMessage::Cc).end();
|
||||
it != itEnd; ++it)
|
||||
{
|
||||
sendMessage("RCPT TO: <" + (*it)->getAddress() + ">");
|
||||
waitForResponse();
|
||||
|
||||
if (responseCode != 250) return false;
|
||||
}
|
||||
|
||||
// Bcc (blind carbon copy)
|
||||
for (it = email.getRecipients(MimeMessage::Bcc).begin(), itEnd = email.getRecipients(MimeMessage::Bcc).end();
|
||||
it != itEnd; ++it)
|
||||
{
|
||||
sendMessage("RCPT TO: <" + (*it)->getAddress() + ">");
|
||||
waitForResponse();
|
||||
|
||||
if (responseCode != 250) return false;
|
||||
}
|
||||
|
||||
// Send DATA command
|
||||
sendMessage("DATA");
|
||||
waitForResponse();
|
||||
|
||||
if (responseCode != 354) return false;
|
||||
|
||||
sendMessage(email.toString());
|
||||
|
||||
// Send \r\n.\r\n to end the mail data
|
||||
sendMessage(".");
|
||||
|
||||
waitForResponse();
|
||||
|
||||
if (responseCode != 250) return false;
|
||||
}
|
||||
catch (ResponseTimeoutException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
catch (SendMessageTimeoutException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SmtpClient::quit()
|
||||
{
|
||||
sendMessage("QUIT");
|
||||
}
|
||||
|
||||
/* [3] --- */
|
||||
|
||||
|
||||
/* [4] Protected methods */
|
||||
|
||||
void SmtpClient::waitForResponse() throw (ResponseTimeoutException)
|
||||
{
|
||||
do {
|
||||
if (!socket->waitForReadyRead(responseTimeout))
|
||||
{
|
||||
emit smtpError(ResponseTimeoutError);
|
||||
throw ResponseTimeoutException();
|
||||
}
|
||||
|
||||
while (socket->canReadLine()) {
|
||||
// Save the server's response
|
||||
responseText = socket->readLine();
|
||||
|
||||
// Extract the respose code from the server's responce (first 3 digits)
|
||||
responseCode = responseText.left(3).toInt();
|
||||
|
||||
if (responseCode / 100 == 4)
|
||||
emit smtpError(ServerError);
|
||||
|
||||
if (responseCode / 100 == 5)
|
||||
emit smtpError(ClientError);
|
||||
|
||||
if (responseText[3] == ' ') { return; }
|
||||
}
|
||||
} while (true);
|
||||
}
|
||||
|
||||
void SmtpClient::sendMessage(const QString &text) throw (SendMessageTimeoutException)
|
||||
{
|
||||
socket->write(text.toUtf8() + "\r\n");
|
||||
if (! socket->waitForBytesWritten(sendMessageTimeout))
|
||||
{
|
||||
emit smtpError(SendDataTimeoutError);
|
||||
throw SendMessageTimeoutException();
|
||||
}
|
||||
}
|
||||
|
||||
/* [4] --- */
|
||||
|
||||
|
||||
/* [5] Slots for the socket's signals */
|
||||
|
||||
void SmtpClient::socketStateChanged(QAbstractSocket::SocketState /* state */)
|
||||
{
|
||||
}
|
||||
|
||||
void SmtpClient::socketError(QAbstractSocket::SocketError /* socketError */)
|
||||
{
|
||||
}
|
||||
|
||||
void SmtpClient::socketReadyRead()
|
||||
{
|
||||
}
|
||||
|
||||
/* [5] --- */
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,184 +0,0 @@
|
|||
/*
|
||||
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 SMTPCLIENT_H
|
||||
#define SMTPCLIENT_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QtNetwork/QSslSocket>
|
||||
|
||||
#include "mimemessage.h"
|
||||
#include "smtpexports.h"
|
||||
|
||||
class SMTP_EXPORT SmtpClient : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
/* [0] Enumerations */
|
||||
|
||||
enum AuthMethod
|
||||
{
|
||||
AuthPlain,
|
||||
AuthLogin
|
||||
};
|
||||
|
||||
enum SmtpError
|
||||
{
|
||||
ConnectionTimeoutError,
|
||||
ResponseTimeoutError,
|
||||
SendDataTimeoutError,
|
||||
AuthenticationFailedError,
|
||||
ServerError, // 4xx smtp error
|
||||
ClientError // 5xx smtp error
|
||||
};
|
||||
|
||||
enum ConnectionType
|
||||
{
|
||||
TcpConnection,
|
||||
SslConnection,
|
||||
TlsConnection // STARTTLS
|
||||
};
|
||||
|
||||
/* [0] --- */
|
||||
|
||||
|
||||
/* [1] Constructors and Destructors */
|
||||
|
||||
SmtpClient(const QString & host = "localhost", int port = 25, ConnectionType ct = TcpConnection);
|
||||
|
||||
~SmtpClient();
|
||||
|
||||
/* [1] --- */
|
||||
|
||||
|
||||
/* [2] Getters and Setters */
|
||||
|
||||
const QString& getHost() const;
|
||||
void setHost(const QString &host);
|
||||
|
||||
int getPort() const;
|
||||
void setPort(int port);
|
||||
|
||||
const QString& getName() const;
|
||||
void setName(const QString &name);
|
||||
|
||||
ConnectionType getConnectionType() const;
|
||||
void setConnectionType(ConnectionType ct);
|
||||
|
||||
const QString & getUser() const;
|
||||
void setUser(const QString &user);
|
||||
|
||||
const QString & getPassword() const;
|
||||
void setPassword(const QString &password);
|
||||
|
||||
SmtpClient::AuthMethod getAuthMethod() const;
|
||||
void setAuthMethod(AuthMethod method);
|
||||
|
||||
const QString & getResponseText() const;
|
||||
int getResponseCode() const;
|
||||
|
||||
int getConnectionTimeout() const;
|
||||
void setConnectionTimeout(int msec);
|
||||
|
||||
int getResponseTimeout() const;
|
||||
void setResponseTimeout(int msec);
|
||||
|
||||
int getSendMessageTimeout() const;
|
||||
void setSendMessageTimeout(int msec);
|
||||
|
||||
QTcpSocket* getSocket();
|
||||
|
||||
|
||||
/* [2] --- */
|
||||
|
||||
|
||||
/* [3] Public methods */
|
||||
|
||||
bool connectToHost();
|
||||
|
||||
bool login();
|
||||
bool login(const QString &user, const QString &password, AuthMethod method = AuthLogin);
|
||||
|
||||
bool sendMail(MimeMessage& email);
|
||||
|
||||
void quit();
|
||||
|
||||
|
||||
/* [3] --- */
|
||||
|
||||
protected:
|
||||
|
||||
/* [4] Protected members */
|
||||
|
||||
QTcpSocket *socket;
|
||||
|
||||
QString host;
|
||||
int port;
|
||||
ConnectionType connectionType;
|
||||
QString name;
|
||||
|
||||
QString user;
|
||||
QString password;
|
||||
AuthMethod authMethod;
|
||||
|
||||
int connectionTimeout;
|
||||
int responseTimeout;
|
||||
int sendMessageTimeout;
|
||||
|
||||
|
||||
QString responseText;
|
||||
int responseCode;
|
||||
|
||||
|
||||
class ResponseTimeoutException {};
|
||||
class SendMessageTimeoutException {};
|
||||
|
||||
/* [4] --- */
|
||||
|
||||
|
||||
/* [5] Protected methods */
|
||||
|
||||
void waitForResponse() throw (ResponseTimeoutException);
|
||||
|
||||
void sendMessage(const QString &text) throw (SendMessageTimeoutException);
|
||||
|
||||
/* [5] --- */
|
||||
|
||||
protected slots:
|
||||
|
||||
/* [6] Protected slots */
|
||||
|
||||
void socketStateChanged(QAbstractSocket::SocketState state);
|
||||
void socketError(QAbstractSocket::SocketError error);
|
||||
void socketReadyRead();
|
||||
|
||||
/* [6] --- */
|
||||
|
||||
|
||||
signals:
|
||||
|
||||
/* [7] Signals */
|
||||
|
||||
void smtpError(SmtpClient::SmtpError e);
|
||||
|
||||
/* [7] --- */
|
||||
|
||||
};
|
||||
|
||||
#endif // SMTPCLIENT_H
|
|
@ -1,15 +0,0 @@
|
|||
#ifndef SMTPEXPORTS_H
|
||||
#define SMTPEXPORTS_H
|
||||
|
||||
/*
|
||||
#ifdef SMTP_BUILD
|
||||
#define SMTP_EXPORT Q_DECL_EXPORT
|
||||
#else
|
||||
#define SMTP_EXPORT Q_DECL_IMPORT
|
||||
#endif
|
||||
*/
|
||||
|
||||
// Servatrice compiles this statically in, so there's no need to declare exports
|
||||
#define SMTP_EXPORT
|
||||
|
||||
#endif // SMTPEXPORTS_H
|
175
servatrice/src/smtpclient.cpp
Normal file
175
servatrice/src/smtpclient.cpp
Normal file
|
@ -0,0 +1,175 @@
|
|||
#include "smtpclient.h"
|
||||
#include "settingscache.h"
|
||||
#include "smtp/qxtsmtp.h"
|
||||
|
||||
#include <QTcpSocket>
|
||||
#include <QSslSocket>
|
||||
|
||||
SmtpClient::SmtpClient(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
smtp = new QxtSmtp(this);
|
||||
|
||||
connect(smtp, SIGNAL(authenticated()), this, SLOT(authenticated()));
|
||||
connect(smtp, SIGNAL(authenticationFailed(const QByteArray &)), this, SLOT(authenticationFailed(const QByteArray &)));
|
||||
connect(smtp, SIGNAL(connected()), this, SLOT(connected()));
|
||||
connect(smtp, SIGNAL(connectionFailed(const QByteArray &)), this, SLOT(connectionFailed(const QByteArray &)));
|
||||
connect(smtp, SIGNAL(disconnected()), this, SLOT(disconnected()));
|
||||
connect(smtp, SIGNAL(encrypted()), this, SLOT(encrypted()));
|
||||
connect(smtp, SIGNAL(encryptionFailed(const QByteArray &)), this, SLOT(encryptionFailed(const QByteArray &)));
|
||||
connect(smtp, SIGNAL(finished()), this, SLOT(finished()));
|
||||
connect(smtp, SIGNAL(mailFailed(int, int, const QByteArray &)), this, SLOT(mailFailed(int, int, const QByteArray &)));
|
||||
connect(smtp, SIGNAL(mailSent(int)), this, SLOT(mailSent(int)));
|
||||
connect(smtp, SIGNAL(recipientRejected(int, const QString &, const QByteArray &)), this, SLOT(recipientRejected(int, const QString &, const QByteArray &)));
|
||||
connect(smtp, SIGNAL(senderRejected(int, const QString &, const QByteArray &)), this, SLOT(senderRejected(int, const QString &, const QByteArray &)));
|
||||
}
|
||||
|
||||
SmtpClient::~SmtpClient()
|
||||
{
|
||||
if(smtp)
|
||||
{
|
||||
delete smtp;
|
||||
smtp = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool SmtpClient::enqueueActivationTokenMail(const QString &nickname, const QString &recipient, const QString &token)
|
||||
{
|
||||
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 sender email in configuration";
|
||||
return false;
|
||||
}
|
||||
|
||||
if(subject.isEmpty())
|
||||
{
|
||||
qDebug() << "[MAIL] Missing subject field in configuration";
|
||||
return false;
|
||||
}
|
||||
|
||||
if(body.isEmpty())
|
||||
{
|
||||
qDebug() << "[MAIL] Missing body field in configuration";
|
||||
return false;
|
||||
}
|
||||
|
||||
if(recipient.isEmpty())
|
||||
{
|
||||
qDebug() << "[MAIL] Missing recipient field for user " << nickname;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(token.isEmpty())
|
||||
{
|
||||
qDebug() << "[MAIL] Missing token field for user " << nickname;
|
||||
return false;
|
||||
}
|
||||
|
||||
QxtMailMessage message;
|
||||
message.setSender(name + " <" + email + ">");
|
||||
message.addRecipient(recipient);
|
||||
message.setSubject(subject);
|
||||
message.setBody(body.replace("%username", nickname).replace("%token", token));
|
||||
|
||||
int id = smtp->send(message);
|
||||
qDebug() << "[MAIL] Enqueued mail to" << recipient << "as" << id;
|
||||
return true;
|
||||
}
|
||||
|
||||
void SmtpClient::sendAllEmails()
|
||||
{
|
||||
// still connected from the previous round
|
||||
if(smtp->socket()->state() == QAbstractSocket::ConnectedState)
|
||||
return;
|
||||
|
||||
if(smtp->pendingMessages() == 0)
|
||||
return;
|
||||
|
||||
QString connectionType = settingsCache->value("smtp/connection", "tcp").toString();
|
||||
QString host = settingsCache->value("smtp/host", "localhost").toString();
|
||||
int port = settingsCache->value("smtp/port", 25).toInt();
|
||||
QByteArray username = settingsCache->value("smtp/username", "").toByteArray();
|
||||
QByteArray password = settingsCache->value("smtp/password", "").toByteArray();
|
||||
bool acceptAllCerts = settingsCache->value("smtp/acceptallcerts", false).toBool();
|
||||
|
||||
smtp->setUsername(username);
|
||||
smtp->setPassword(password);
|
||||
|
||||
// Connect
|
||||
if(connectionType == "ssl")
|
||||
{
|
||||
if(acceptAllCerts)
|
||||
smtp->sslSocket()->setPeerVerifyMode(QSslSocket::QueryPeer);
|
||||
smtp->connectToSecureHost(host, port);
|
||||
} else {
|
||||
smtp->connectToHost(host, port);
|
||||
}
|
||||
}
|
||||
|
||||
void SmtpClient::authenticated()
|
||||
{
|
||||
qDebug() << "[MAIL] authenticated";
|
||||
}
|
||||
|
||||
void SmtpClient::authenticationFailed(const QByteArray & msg)
|
||||
{
|
||||
qDebug() << "[MAIL] authenticationFailed" << QString(msg);
|
||||
}
|
||||
|
||||
void SmtpClient::connected()
|
||||
{
|
||||
qDebug() << "[MAIL] connected";
|
||||
}
|
||||
|
||||
void SmtpClient::connectionFailed(const QByteArray & msg)
|
||||
{
|
||||
qDebug() << "[MAIL] connectionFailed" << QString(msg);
|
||||
}
|
||||
|
||||
void SmtpClient::disconnected()
|
||||
{
|
||||
qDebug() << "[MAIL] disconnected";
|
||||
}
|
||||
|
||||
void SmtpClient::encrypted()
|
||||
{
|
||||
qDebug() << "[MAIL] encrypted";
|
||||
}
|
||||
|
||||
void SmtpClient::encryptionFailed(const QByteArray & msg)
|
||||
{
|
||||
qDebug() << "[MAIL] encryptionFailed" << QString(msg);
|
||||
qDebug() << "[MAIL] Try enabling the \"acceptallcerts\" option in servatrice.ini";
|
||||
}
|
||||
|
||||
void SmtpClient::finished()
|
||||
{
|
||||
qDebug() << "[MAIL] finished";
|
||||
smtp->disconnectFromHost();
|
||||
}
|
||||
|
||||
void SmtpClient::mailFailed(int mailID, int errorCode, const QByteArray & msg)
|
||||
{
|
||||
qDebug() << "[MAIL] mailFailed id=" << mailID << " errorCode=" << errorCode << "msg=" << QString(msg);
|
||||
}
|
||||
|
||||
void SmtpClient::mailSent(int mailID)
|
||||
{
|
||||
qDebug() << "[MAIL] mailSent" << mailID;
|
||||
}
|
||||
|
||||
void SmtpClient::recipientRejected(int mailID, const QString & address, const QByteArray & msg)
|
||||
{
|
||||
qDebug() << "[MAIL] recipientRejected id=" << mailID << " address=" << address << "msg=" << QString(msg);
|
||||
}
|
||||
|
||||
void SmtpClient::senderRejected(int mailID, const QString & address, const QByteArray & msg)
|
||||
{
|
||||
qDebug() << "[MAIL] senderRejected id=" << mailID << " address=" << address << "msg=" << QString(msg);
|
||||
}
|
34
servatrice/src/smtpclient.h
Normal file
34
servatrice/src/smtpclient.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
#ifndef SMTPCLIENT_H
|
||||
#define SMTPCLIENT_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class QxtSmtp;
|
||||
class QxtMailMessage;
|
||||
|
||||
class SmtpClient : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
SmtpClient(QObject *parent = 0);
|
||||
~SmtpClient();
|
||||
protected:
|
||||
QxtSmtp *smtp;
|
||||
public slots:
|
||||
bool enqueueActivationTokenMail(const QString &nickname, const QString &recipient, const QString &token);
|
||||
void sendAllEmails();
|
||||
protected slots:
|
||||
void authenticated();
|
||||
void authenticationFailed(const QByteArray & msg);
|
||||
void connected();
|
||||
void connectionFailed(const QByteArray & msg);
|
||||
void disconnected();
|
||||
void encrypted();
|
||||
void encryptionFailed(const QByteArray & msg);
|
||||
void finished();
|
||||
void mailFailed(int mailID, int errorCode, const QByteArray & msg);
|
||||
void mailSent(int mailID);
|
||||
void recipientRejected(int mailID, const QString & address, const QByteArray & msg);
|
||||
void senderRejected(int mailID, const QString & address, const QByteArray & msg);
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue