1
0

Repair and adjust the SMTP library.

This commit is contained in:
Saturneric 2021-07-15 01:23:44 +08:00
parent a0b5b56e8f
commit 39acbb05c1
25 changed files with 858 additions and 817 deletions

View File

@ -23,27 +23,29 @@
#include "smtpexports.h" #include "smtpexports.h"
class SMTP_EXPORT EmailAddress : public QObject class SMTP_EXPORT EmailAddress : public QObject {
{ Q_OBJECT
Q_OBJECT
public: public:
/* [1] Constructors and Destructors */ /* [1] Constructors and Destructors */
EmailAddress(); EmailAddress() = default;
EmailAddress(const QString & address, const QString & name="");
~EmailAddress(); explicit EmailAddress(const QString &address, const QString &name = "");
~EmailAddress() override;
/* [1] --- */ /* [1] --- */
/* [2] Getters and Setters */ /* [2] Getters and Setters */
void setName(const QString & name); void setName(const QString &name);
void setAddress(const QString & address);
const QString & getName() const; void setAddress(const QString &address);
const QString & getAddress() const;
[[nodiscard]] const QString &getName() const;
[[nodiscard]] const QString &getAddress() const;
/* [2] --- */ /* [2] --- */

View File

@ -25,17 +25,17 @@
#include "smtpexports.h" #include "smtpexports.h"
class SMTP_EXPORT MimeAttachment : public MimeFile class SMTP_EXPORT MimeAttachment : public MimeFile {
{ Q_OBJECT
Q_OBJECT
public: public:
/* [1] Constructors and Destructors */ /* [1] Constructors and Destructors */
MimeAttachment(QFile* file); explicit MimeAttachment(QFile *file);
MimeAttachment(const QByteArray& stream, const QString& fileName);
~MimeAttachment(); MimeAttachment(const QByteArray &stream, const QString &fileName);
~MimeAttachment() override;
/* [1] --- */ /* [1] --- */
@ -43,7 +43,7 @@ protected:
/* [2] Protected methods */ /* [2] Protected methods */
virtual void prepare(); void prepare() override;
/* [2] --- */ /* [2] --- */
}; };

View File

@ -24,16 +24,16 @@
#include "smtpexports.h" #include "smtpexports.h"
class SMTP_EXPORT MimeContentFormatter : public QObject class SMTP_EXPORT MimeContentFormatter : public QObject {
{ Q_OBJECT
Q_OBJECT
public: public:
MimeContentFormatter (int max_length = 76); explicit MimeContentFormatter(int max_length = 76);
void setMaxLength(int l); void setMaxLength(int l);
int getMaxLength() const;
QString format(const QString &content, bool quotedPrintable = false) const; [[nodiscard]] int getMaxLength() const;
[[nodiscard]] QString format(const QString &content, bool quotedPrintable = false) const;
protected: protected:
int max_length; int max_length;

View File

@ -24,16 +24,17 @@
#include "smtpexports.h" #include "smtpexports.h"
class SMTP_EXPORT MimeFile : public MimePart class SMTP_EXPORT MimeFile : public MimePart {
{ Q_OBJECT
Q_OBJECT
public: public:
/* [1] Constructors and Destructors */ /* [1] Constructors and Destructors */
MimeFile(const QByteArray& stream, const QString& fileName); MimeFile(const QByteArray &stream, const QString &fileName);
MimeFile(QFile *f);
~MimeFile(); explicit MimeFile(QFile *f);
~MimeFile() override;
/* [1] --- */ /* [1] --- */
@ -46,14 +47,14 @@ protected:
/* [3] Protected members */ /* [3] Protected members */
QFile* file; QFile *file;
/* [3] --- */ /* [3] --- */
/* [4] Protected methods */ /* [4] Protected methods */
virtual void prepare(); void prepare() override;
/* [4] --- */ /* [4] --- */

View File

@ -23,24 +23,24 @@
#include "smtpexports.h" #include "smtpexports.h"
class SMTP_EXPORT MimeHtml : public MimeText class SMTP_EXPORT MimeHtml : public MimeText {
{ Q_OBJECT
Q_OBJECT
public: public:
/* [1] Constructors and Destructors */ /* [1] Constructors and Destructors */
MimeHtml(const QString &html = ""); explicit MimeHtml(const QString &html = "");
~MimeHtml();
~MimeHtml() override;
/* [1] --- */ /* [1] --- */
/* [2] Getters and Setters */ /* [2] Getters and Setters */
void setHtml(const QString & html); void setHtml(const QString &html);
const QString& getHtml() const; [[nodiscard]] const QString &getHtml() const;
/* [2] --- */ /* [2] --- */
@ -53,7 +53,7 @@ protected:
/* [4] Protected methods */ /* [4] Protected methods */
virtual void prepare(); void prepare() override;
/* [4] --- */ /* [4] --- */
}; };

View File

@ -23,14 +23,14 @@
#include "smtpexports.h" #include "smtpexports.h"
class SMTP_EXPORT MimeInlineFile : public MimeFile class SMTP_EXPORT MimeInlineFile : public MimeFile {
{
public: public:
/* [1] Constructors and Destructors */ /* [1] Constructors and Destructors */
MimeInlineFile(QFile *f); explicit MimeInlineFile(QFile *f);
~MimeInlineFile();
~MimeInlineFile() override;
/* [1] --- */ /* [1] --- */
@ -48,7 +48,7 @@ protected:
/* [4] Protected methods */ /* [4] Protected methods */
virtual void prepare(); void prepare() override;
/* [4] --- */ /* [4] --- */
}; };

View File

@ -26,8 +26,7 @@
#include "smtpexports.h" #include "smtpexports.h"
class SMTP_EXPORT MimeMessage : public QObject class SMTP_EXPORT MimeMessage : public QObject {
{
public: public:
enum RecipientType { enum RecipientType {
@ -38,34 +37,47 @@ public:
/* [1] Constructors and Destructors */ /* [1] Constructors and Destructors */
MimeMessage(bool createAutoMimeConent = true); explicit MimeMessage(bool createAutoMimeConent = true);
~MimeMessage();
~MimeMessage() override;
/* [1] --- */ /* [1] --- */
/* [2] Getters and Setters */ /* [2] Getters and Setters */
void setSender(EmailAddress* e); 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 setReplyTo(EmailAddress* rto);
void setInReplyTo(const QString& inReplyTo); 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 setReplyTo(EmailAddress *rto);
void setInReplyTo(const QString &inReplyTo);
void setHeaderEncoding(MimePart::Encoding); void setHeaderEncoding(MimePart::Encoding);
const EmailAddress & getSender() const; [[nodiscard]] const EmailAddress &getSender() const;
const QList<EmailAddress*> & getRecipients(RecipientType type = To) const;
const QString & getSubject() const; [[nodiscard]] const QList<EmailAddress *> &getRecipients(RecipientType type = To) const;
const QList<MimePart*> & getParts() const;
const EmailAddress* getReplyTo() const; [[nodiscard]] const QString &getSubject() const;
[[nodiscard]] const QList<MimePart *> &getParts() const;
[[nodiscard]] const EmailAddress *getReplyTo() const;
MimePart &getContent();
MimePart& getContent();
void setContent(MimePart *content); void setContent(MimePart *content);
/* [2] --- */ /* [2] --- */
@ -80,9 +92,9 @@ protected:
/* [4] Protected members */ /* [4] Protected members */
EmailAddress* sender; EmailAddress *sender{};
EmailAddress* replyTo; EmailAddress *replyTo;
QList<EmailAddress*> recipientsTo, recipientsCc, recipientsBcc; QList<EmailAddress *> recipientsTo, recipientsCc, recipientsBcc;
QString subject; QString subject;
QString mInReplyTo; QString mInReplyTo;
MimePart *content; MimePart *content;

View File

@ -24,49 +24,50 @@
#include "smtpexports.h" #include "smtpexports.h"
class SMTP_EXPORT MimeMultiPart : public MimePart { class SMTP_EXPORT MimeMultiPart : public MimePart {
Q_OBJECT Q_OBJECT
public: public:
/* [0] Enums */ /* [0] Enums */
enum MultiPartType { enum MultiPartType {
Mixed = 0, // RFC 2046, section 5.1.3 Mixed = 0, // RFC 2046, section 5.1.3
Digest = 1, // RFC 2046, section 5.1.5 Digest = 1, // RFC 2046, section 5.1.5
Alternative = 2, // RFC 2046, section 5.1.4 Alternative = 2, // RFC 2046, section 5.1.4
Related = 3, // RFC 2387 Related = 3, // RFC 2387
Report = 4, // RFC 6522 Report = 4, // RFC 6522
Signed = 5, // RFC 1847, section 2.1 Signed = 5, // RFC 1847, section 2.1
Encrypted = 6 // RFC 1847, section 2.2 Encrypted = 6 // RFC 1847, section 2.2
}; };
/* [0] --- */ /* [0] --- */
/* [1] Constructors and Destructors */ /* [1] Constructors and Destructors */
MimeMultiPart(const MultiPartType type = Related); explicit MimeMultiPart(MultiPartType type = Related);
~MimeMultiPart(); ~MimeMultiPart() override;
/* [1] --- */ /* [1] --- */
/* [2] Getters and Setters */ /* [2] Getters and Setters */
void setMimeType(const MultiPartType type); void setMimeType(MultiPartType type);
MultiPartType getMimeType() const;
const QList<MimePart *> &getParts() const; [[nodiscard]] MultiPartType getMimeType() const;
/* [2] --- */ [[nodiscard]] const QList<MimePart *> &getParts() const;
/* [3] Public methods */ /* [2] --- */
void addPart(MimePart *part); /* [3] Public methods */
virtual void prepare(); void addPart(MimePart *part);
/* [3] --- */ void prepare() override;
/* [3] --- */
protected: protected:
QList<MimePart *> parts; QList<MimePart *> parts;
MultiPartType type; MultiPartType type;
}; };
#endif // MIMEMULTIPART_H #endif // MIMEMULTIPART_H

View File

@ -25,76 +25,86 @@
#include "smtpexports.h" #include "smtpexports.h"
class SMTP_EXPORT MimePart : public QObject { class SMTP_EXPORT MimePart : public QObject {
Q_OBJECT Q_OBJECT
public: public:
/* [0] Enumerations */ /* [0] Enumerations */
enum Encoding { _7Bit, _8Bit, Base64, QuotedPrintable }; enum Encoding {
_7Bit, _8Bit, Base64, QuotedPrintable
};
/* [0] --- */ /* [0] --- */
/* [1] Constructors and Destructors */ /* [1] Constructors and Destructors */
MimePart(); MimePart();
~MimePart();
/* [1] --- */ ~MimePart() override;
/* [2] Getters and Setters */ /* [1] --- */
const QString &getHeader() const; /* [2] Getters and Setters */
const QByteArray &getContent() const;
void setContent(const QByteArray &content); [[nodiscard]] const QString &getHeader() const;
void setHeader(const QString &header);
void addHeaderLine(const QString &line); [[nodiscard]] const QByteArray &getContent() const;
void setContentId(const QString &cId); void setContent(const QByteArray &content);
const QString &getContentId() const;
void setContentName(const QString &cName); void setHeader(const QString &header);
const QString &getContentName() const;
void setContentType(const QString &cType); void addHeaderLine(const QString &line);
const QString &getContentType() const;
void setCharset(const QString &charset); void setContentId(const QString &cId);
const QString &getCharset() const;
void setEncoding(Encoding enc); [[nodiscard]] const QString &getContentId() const;
Encoding getEncoding() const;
MimeContentFormatter &getContentFormatter(); void setContentName(const QString &cName);
/* [2] --- */ [[nodiscard]] const QString &getContentName() const;
/* [3] Public methods */ void setContentType(const QString &cType);
virtual QString toString(); [[nodiscard]] const QString &getContentType() const;
virtual void prepare(); void setCharset(const QString &charset);
/* [3] --- */ [[nodiscard]] const QString &getCharset() const;
void setEncoding(Encoding enc);
[[nodiscard]] Encoding getEncoding() const;
MimeContentFormatter &getContentFormatter();
/* [2] --- */
/* [3] Public methods */
virtual QString toString();
virtual void prepare();
/* [3] --- */
protected: protected:
/* [4] Protected members */ /* [4] Protected members */
QString header; QString header;
QByteArray content; QByteArray content;
QString cId; QString cId;
QString cName; QString cName;
QString cType; QString cType;
QString cCharset; QString cCharset;
QString cBoundary; QString cBoundary;
Encoding cEncoding; Encoding cEncoding;
QString mimeString; QString mimeString;
bool prepared; bool prepared;
MimeContentFormatter formatter; MimeContentFormatter formatter;
/* [4] --- */ /* [4] --- */
}; };
#endif // MIMEPART_H #endif // MIMEPART_H

View File

@ -23,23 +23,23 @@
#include "smtpexports.h" #include "smtpexports.h"
class SMTP_EXPORT MimeText : public MimePart class SMTP_EXPORT MimeText : public MimePart {
{
public: public:
/* [1] Constructors and Destructors */ /* [1] Constructors and Destructors */
MimeText(const QString &text = ""); explicit MimeText(const QString &text = "");
~MimeText();
~MimeText() override;
/* [1] --- */ /* [1] --- */
/* [2] Getters and Setters*/ /* [2] Getters and Setters*/
void setText(const QString & text); void setText(const QString &text);
const QString & getText() const; [[nodiscard]] const QString &getText() const;
/* [2] --- */ /* [2] --- */
@ -53,7 +53,7 @@ protected:
/* [4] Protected methods */ /* [4] Protected methods */
void prepare(); void prepare() override;
/* [4] --- */ /* [4] --- */

View File

@ -24,12 +24,12 @@
#include "smtpexports.h" #include "smtpexports.h"
class SMTP_EXPORT QuotedPrintable : public QObject class SMTP_EXPORT QuotedPrintable : public QObject {
{ Q_OBJECT
Q_OBJECT
public: public:
static QString encode(const QByteArray &input); static QString encode(const QByteArray &input);
static QByteArray decode(const QString &input); static QByteArray decode(const QString &input);
private: private:

View File

@ -25,21 +25,18 @@
#include "mimemessage.h" #include "mimemessage.h"
#include "smtpexports.h" #include "smtpexports.h"
class SMTP_EXPORT SmtpClient : public QObject class SMTP_EXPORT SmtpClient : public QObject {
{ Q_OBJECT
Q_OBJECT
public: public:
/* [0] Enumerations */ /* [0] Enumerations */
enum AuthMethod enum AuthMethod {
{
AuthPlain, AuthPlain,
AuthLogin AuthLogin
}; };
enum SmtpError enum SmtpError {
{
ConnectionTimeoutError, ConnectionTimeoutError,
ResponseTimeoutError, ResponseTimeoutError,
SendDataTimeoutError, SendDataTimeoutError,
@ -48,8 +45,7 @@ public:
ClientError // 5xx smtp error ClientError // 5xx smtp error
}; };
enum ConnectionType enum ConnectionType {
{
TcpConnection, TcpConnection,
SslConnection, SslConnection,
TlsConnection // STARTTLS TlsConnection // STARTTLS
@ -60,49 +56,60 @@ public:
/* [1] Constructors and Destructors */ /* [1] Constructors and Destructors */
SmtpClient(const QString & host = "localhost", int port = 25, ConnectionType ct = TcpConnection); explicit SmtpClient(const QString &host = "localhost", int port = 25, ConnectionType ct = TcpConnection);
~SmtpClient(); ~SmtpClient() override;
/* [1] --- */ /* [1] --- */
/* [2] Getters and Setters */ /* [2] Getters and Setters */
const QString& getHost() const; [[nodiscard]] const QString &getHost() const;
void setHost(const QString &host); void setHost(const QString &host);
int getPort() const; [[nodiscard]] int getPort() const;
void setPort(int port); void setPort(int port);
const QString& getName() const; [[nodiscard]] const QString &getName() const;
void setName(const QString &name); void setName(const QString &name);
ConnectionType getConnectionType() const; [[nodiscard]] ConnectionType getConnectionType() const;
void setConnectionType(ConnectionType ct); void setConnectionType(ConnectionType ct);
const QString & getUser() const; [[nodiscard]] const QString &getUser() const;
void setUser(const QString &user); void setUser(const QString &user);
const QString & getPassword() const; [[nodiscard]] const QString &getPassword() const;
void setPassword(const QString &password); void setPassword(const QString &password);
SmtpClient::AuthMethod getAuthMethod() const; [[nodiscard]] SmtpClient::AuthMethod getAuthMethod() const;
void setAuthMethod(AuthMethod method); void setAuthMethod(AuthMethod method);
const QString & getResponseText() const; [[nodiscard]] const QString &getResponseText() const;
int getResponseCode() const;
[[nodiscard]] int getResponseCode() const;
[[nodiscard]] int getConnectionTimeout() const;
int getConnectionTimeout() const;
void setConnectionTimeout(int msec); void setConnectionTimeout(int msec);
int getResponseTimeout() const; [[nodiscard]] int getResponseTimeout() const;
void setResponseTimeout(int msec); void setResponseTimeout(int msec);
int getSendMessageTimeout() const; [[nodiscard]] int getSendMessageTimeout() const;
void setSendMessageTimeout(int msec); void setSendMessageTimeout(int msec);
QTcpSocket* getSocket(); QTcpSocket *getSocket();
/* [2] --- */ /* [2] --- */
@ -113,9 +120,10 @@ public:
bool connectToHost(); bool connectToHost();
bool login(); bool login();
bool login(const QString &user, const QString &password, AuthMethod method = AuthLogin); bool login(const QString &user, const QString &password, AuthMethod method = AuthLogin);
bool sendMail(MimeMessage& email); bool sendMail(MimeMessage &email);
void quit(); void quit();
@ -146,8 +154,11 @@ protected:
int responseCode; int responseCode;
class ResponseTimeoutException {}; class ResponseTimeoutException : public std::exception {
class SendMessageTimeoutException {}; };
class SendMessageTimeoutException : public std::exception {
};
/* [4] --- */ /* [4] --- */
@ -165,7 +176,9 @@ protected slots:
/* [6] Protected slots */ /* [6] Protected slots */
void socketStateChanged(QAbstractSocket::SocketState state); void socketStateChanged(QAbstractSocket::SocketState state);
void socketError(QAbstractSocket::SocketError error); void socketError(QAbstractSocket::SocketError error);
void socketReadyRead(); void socketReadyRead();
/* [6] --- */ /* [6] --- */

View File

@ -2,9 +2,9 @@
#define SMTPEXPORTS_H #define SMTPEXPORTS_H
#ifdef SMTP_BUILD #ifdef SMTP_BUILD
#define SMTP_EXPORT Q_DECL_EXPORT #define SMTP_EXPORT
#else #else
#define SMTP_EXPORT Q_DECL_IMPORT #define SMTP_EXPORT
#endif #endif
#endif // SMTPEXPORTS_H #endif // SMTPEXPORTS_H

View File

@ -21,8 +21,8 @@
/* [1] Constructors and Destructors */ /* [1] Constructors and Destructors */
EmailAddress::EmailAddress(const QString &address, const QString &name) { EmailAddress::EmailAddress(const QString &address, const QString &name) {
this->address = address; this->address = address;
this->name = name; this->name = name;
} }
EmailAddress::~EmailAddress() {} EmailAddress::~EmailAddress() {}
@ -34,7 +34,7 @@ EmailAddress::~EmailAddress() {}
void EmailAddress::setName(const QString &name) { this->name = name; } void EmailAddress::setName(const QString &name) { this->name = name; }
void EmailAddress::setAddress(const QString &address) { void EmailAddress::setAddress(const QString &address) {
this->address = address; this->address = address;
} }
const QString &EmailAddress::getName() const { return name; } const QString &EmailAddress::getName() const { return name; }

View File

@ -22,21 +22,22 @@
/* [1] Constructors and Destructors */ /* [1] Constructors and Destructors */
MimeAttachment::MimeAttachment(QFile *file) : MimeFile(file) {} MimeAttachment::MimeAttachment(QFile *file) : MimeFile(file) {}
MimeAttachment::MimeAttachment(const QByteArray &stream, MimeAttachment::MimeAttachment(const QByteArray &stream,
const QString &fileName) const QString &fileName)
: MimeFile(stream, fileName) {} : MimeFile(stream, fileName) {}
MimeAttachment::~MimeAttachment() {} MimeAttachment::~MimeAttachment() = default;
/* [1] --- */ /* [1] --- */
/* [2] Protected methods */ /* [2] Protected methods */
void MimeAttachment::prepare() { void MimeAttachment::prepare() {
this->header += "Content-disposition: attachment\r\n"; this->header += "Content-disposition: attachment\r\n";
/* !!! IMPORTANT !!! */ /* !!! IMPORTANT !!! */
MimeFile::prepare(); MimeFile::prepare();
} }
/* [2] --- */ /* [2] --- */

View File

@ -19,39 +19,39 @@
#include "smtp/mimecontentformatter.h" #include "smtp/mimecontentformatter.h"
MimeContentFormatter::MimeContentFormatter(int max_length) MimeContentFormatter::MimeContentFormatter(int max_length)
: max_length(max_length) {} : max_length(max_length) {}
QString MimeContentFormatter::format(const QString &content, QString MimeContentFormatter::format(const QString &content,
bool quotedPrintable) const { bool quotedPrintable) const {
QString out; QString out;
int chars = 0; int chars = 0;
for (int i = 0; i < content.length(); ++i) { for (auto i : content) {
chars++; chars++;
if (!quotedPrintable) { if (!quotedPrintable) {
if (chars > max_length) { if (chars > max_length) {
out.append("\r\n"); out.append("\r\n");
chars = 1; chars = 1;
} }
} else { } else {
if (content[i] == '\n') { // new line if (i == '\n') { // new line
out.append(content[i]); out.append(i);
chars = 0; chars = 0;
continue; continue;
} }
if ((chars > max_length - 1) || if ((chars > max_length - 1) ||
((content[i] == '=') && (chars > max_length - 3))) { ((i == '=') && (chars > max_length - 3))) {
out.append('='); out.append('=');
out.append("\r\n"); out.append("\r\n");
chars = 1; chars = 1;
} }
}
out.append(i);
} }
out.append(content[i]);
}
return out; return out;
} }
void MimeContentFormatter::setMaxLength(int l) { max_length = l; } void MimeContentFormatter::setMaxLength(int l) { max_length = l; }

View File

@ -22,22 +22,21 @@
/* [1] Constructors and Destructors */ /* [1] Constructors and Destructors */
MimeFile::MimeFile(QFile *file) { MimeFile::MimeFile(QFile *file) {
this->file = file; this->file = file;
this->cType = "application/octet-stream"; this->cType = "application/octet-stream";
this->cName = QFileInfo(*file).fileName(); this->cName = QFileInfo(*file).fileName();
this->cEncoding = Base64; this->cEncoding = Base64;
} }
MimeFile::MimeFile(const QByteArray &stream, const QString &fileName) { MimeFile::MimeFile(const QByteArray &stream, const QString &fileName) {
this->cEncoding = Base64; this->cEncoding = Base64;
this->cType = "application/octet-stream"; this->cType = "application/octet-stream";
this->file = 0; this->file = nullptr;
this->cName = fileName; this->cName = fileName;
this->content = stream; this->content = stream;
} }
MimeFile::~MimeFile() { MimeFile::~MimeFile() {
if (file)
delete file; delete file;
} }
@ -50,13 +49,13 @@ MimeFile::~MimeFile() {
/* [3] Protected methods */ /* [3] Protected methods */
void MimeFile::prepare() { void MimeFile::prepare() {
if (this->file) { if (this->file) {
file->open(QIODevice::ReadOnly); file->open(QIODevice::ReadOnly);
this->content = file->readAll(); this->content = file->readAll();
file->close(); file->close();
} }
/* !!! IMPORTANT !!!! */ /* !!! IMPORTANT !!!! */
MimePart::prepare(); MimePart::prepare();
} }
/* [3] --- */ /* [3] --- */

View File

@ -21,10 +21,10 @@
/* [1] Constructors and Destructors */ /* [1] Constructors and Destructors */
MimeHtml::MimeHtml(const QString &html) : MimeText(html) { MimeHtml::MimeHtml(const QString &html) : MimeText(html) {
this->cType = "text/html"; this->cType = "text/html";
} }
MimeHtml::~MimeHtml() {} MimeHtml::~MimeHtml() = default;
/* [1] --- */ /* [1] --- */
@ -39,8 +39,8 @@ const QString &MimeHtml::getHtml() const { return text; }
/* [3] Protected methods */ /* [3] Protected methods */
void MimeHtml::prepare() { void MimeHtml::prepare() {
/* !!! IMPORTANT !!! */ /* !!! IMPORTANT !!! */
MimeText::prepare(); MimeText::prepare();
} }
/* [3] --- */ /* [3] --- */

View File

@ -22,7 +22,7 @@
MimeInlineFile::MimeInlineFile(QFile *f) : MimeFile(f) {} MimeInlineFile::MimeInlineFile(QFile *f) : MimeFile(f) {}
MimeInlineFile::~MimeInlineFile() {} MimeInlineFile::~MimeInlineFile() = default;
/* [1] --- */ /* [1] --- */
@ -33,10 +33,10 @@ MimeInlineFile::~MimeInlineFile() {}
/* [3] Protected methods */ /* [3] Protected methods */
void MimeInlineFile::prepare() { void MimeInlineFile::prepare() {
this->header += "Content-Disposition: inline\r\n"; this->header += "Content-Disposition: inline\r\n";
/* !!! IMPORTANT !!! */ /* !!! IMPORTANT !!! */
MimeFile::prepare(); MimeFile::prepare();
} }
/* [3] --- */ /* [3] --- */

View File

@ -25,18 +25,18 @@
/* [1] Constructors and Destructors */ /* [1] Constructors and Destructors */
MimeMessage::MimeMessage(bool createAutoMimeContent) MimeMessage::MimeMessage(bool createAutoMimeContent)
: replyTo(nullptr), hEncoding(MimePart::_8Bit) { : replyTo(nullptr), hEncoding(MimePart::_8Bit) {
if (createAutoMimeContent) if (createAutoMimeContent)
this->content = new MimeMultiPart(); this->content = new MimeMultiPart();
autoMimeContentCreated = createAutoMimeContent; autoMimeContentCreated = createAutoMimeContent;
} }
MimeMessage::~MimeMessage() { MimeMessage::~MimeMessage() {
if (this->autoMimeContentCreated) { if (this->autoMimeContentCreated) {
this->autoMimeContentCreated = false; this->autoMimeContentCreated = false;
delete (this->content); delete (this->content);
} }
} }
/* [1] --- */ /* [1] --- */
@ -45,34 +45,34 @@ MimeMessage::~MimeMessage() {
MimePart &MimeMessage::getContent() { return *content; } MimePart &MimeMessage::getContent() { return *content; }
void MimeMessage::setContent(MimePart *content) { void MimeMessage::setContent(MimePart *content) {
if (this->autoMimeContentCreated) { if (this->autoMimeContentCreated) {
this->autoMimeContentCreated = false; this->autoMimeContentCreated = false;
delete (this->content); delete (this->content);
} }
this->content = content; this->content = content;
} }
void MimeMessage::setReplyTo(EmailAddress *rto) { replyTo = rto; } void MimeMessage::setReplyTo(EmailAddress *rto) { replyTo = rto; }
void MimeMessage::setSender(EmailAddress *e) { void MimeMessage::setSender(EmailAddress *e) {
this->sender = e; this->sender = e;
e->setParent(this); e->setParent(this);
} }
void MimeMessage::addRecipient(EmailAddress *rcpt, RecipientType type) { void MimeMessage::addRecipient(EmailAddress *rcpt, RecipientType type) {
switch (type) { switch (type) {
case To: case To:
recipientsTo << rcpt; recipientsTo << rcpt;
break; break;
case Cc: case Cc:
recipientsCc << rcpt; recipientsCc << rcpt;
break; break;
case Bcc: case Bcc:
recipientsBcc << rcpt; recipientsBcc << rcpt;
break; break;
} }
rcpt->setParent(this); rcpt->setParent(this);
} }
void MimeMessage::addTo(EmailAddress *rcpt) { this->recipientsTo << rcpt; } void MimeMessage::addTo(EmailAddress *rcpt) { this->recipientsTo << rcpt; }
@ -82,36 +82,36 @@ void MimeMessage::addCc(EmailAddress *rcpt) { this->recipientsCc << rcpt; }
void MimeMessage::addBcc(EmailAddress *rcpt) { this->recipientsBcc << rcpt; } void MimeMessage::addBcc(EmailAddress *rcpt) { this->recipientsBcc << rcpt; }
void MimeMessage::setSubject(const QString &subject) { void MimeMessage::setSubject(const QString &subject) {
this->subject = subject; this->subject = subject;
} }
void MimeMessage::addPart(MimePart *part) { void MimeMessage::addPart(MimePart *part) {
if (typeid(*content) == typeid(MimeMultiPart)) { if (typeid(*content) == typeid(MimeMultiPart)) {
((MimeMultiPart *)content)->addPart(part); ((MimeMultiPart *) content)->addPart(part);
}; };
} }
void MimeMessage::setInReplyTo(const QString &inReplyTo) { void MimeMessage::setInReplyTo(const QString &inReplyTo) {
mInReplyTo = inReplyTo; mInReplyTo = inReplyTo;
} }
void MimeMessage::setHeaderEncoding(MimePart::Encoding hEnc) { void MimeMessage::setHeaderEncoding(MimePart::Encoding hEnc) {
this->hEncoding = hEnc; this->hEncoding = hEnc;
} }
const EmailAddress &MimeMessage::getSender() const { return *sender; } const EmailAddress &MimeMessage::getSender() const { return *sender; }
const QList<EmailAddress *> & const QList<EmailAddress *> &
MimeMessage::getRecipients(RecipientType type) const { MimeMessage::getRecipients(RecipientType type) const {
switch (type) { switch (type) {
default: default:
case To: case To:
return recipientsTo; return recipientsTo;
case Cc: case Cc:
return recipientsCc; return recipientsCc;
case Bcc: case Bcc:
return recipientsBcc; return recipientsBcc;
} }
} }
const EmailAddress *MimeMessage::getReplyTo() const { return replyTo; } const EmailAddress *MimeMessage::getReplyTo() const { return replyTo; }
@ -119,13 +119,13 @@ const EmailAddress *MimeMessage::getReplyTo() const { return replyTo; }
const QString &MimeMessage::getSubject() const { return subject; } const QString &MimeMessage::getSubject() const { return subject; }
const QList<MimePart *> &MimeMessage::getParts() const { const QList<MimePart *> &MimeMessage::getParts() const {
if (typeid(*content) == typeid(MimeMultiPart)) { if (typeid(*content) == typeid(MimeMultiPart)) {
return ((MimeMultiPart *)content)->getParts(); return ((MimeMultiPart *) content)->getParts();
} else { } else {
QList<MimePart *> *res = new QList<MimePart *>(); auto *res = new QList<MimePart *>();
res->append(content); res->append(content);
return *res; return *res;
} }
} }
/* [2] --- */ /* [2] --- */
@ -133,176 +133,176 @@ const QList<MimePart *> &MimeMessage::getParts() const {
/* [3] Public Methods */ /* [3] Public Methods */
QString MimeMessage::toString() { QString MimeMessage::toString() {
QString mime; QString mime;
/* =========== MIME HEADER ============ */ /* =========== MIME HEADER ============ */
/* ---------- Sender / From ----------- */ /* ---------- Sender / From ----------- */
mime = "From:"; mime = "From:";
if (sender->getName() != "") { if (sender->getName() != "") {
switch (hEncoding) { switch (hEncoding) {
case MimePart::Base64: case MimePart::Base64:
mime += " =?utf-8?B?" + mime += " =?utf-8?B?" +
QByteArray().append(sender->getName().toUtf8()).toBase64() + "?="; QByteArray().append(sender->getName().toUtf8()).toBase64() + "?=";
break; break;
case MimePart::QuotedPrintable: case MimePart::QuotedPrintable:
mime += " =?utf-8?Q?" + mime += " =?utf-8?Q?" +
QuotedPrintable::encode( QuotedPrintable::encode(
QByteArray().append(sender->getName().toUtf8())) QByteArray().append(sender->getName().toUtf8()))
.replace(' ', "_") .replace(' ', "_")
.replace(':', "=3A") + .replace(':', "=3A") +
"?="; "?=";
break; break;
default: default:
mime += " " + sender->getName(); mime += " " + sender->getName();
}
} }
} mime += " <" + sender->getAddress() + ">\r\n";
mime += " <" + sender->getAddress() + ">\r\n"; /* ---------------------------------- */
/* ---------------------------------- */
/* ------- Recipients / To ---------- */ /* ------- Recipients / To ---------- */
mime += "To:"; mime += "To:";
QList<EmailAddress *>::iterator it; QList<EmailAddress *>::iterator it;
int i; int i;
for (i = 0, it = recipientsTo.begin(); it != recipientsTo.end(); ++it, ++i) { for (i = 0, it = recipientsTo.begin(); it != recipientsTo.end(); ++it, ++i) {
if (i != 0) { if (i != 0) {
mime += ","; mime += ",";
} }
if ((*it)->getName() != "") { if ((*it)->getName() != "") {
switch (hEncoding) { switch (hEncoding) {
case MimePart::Base64: case MimePart::Base64:
mime += " =?utf-8?B?" + mime += " =?utf-8?B?" +
QByteArray().append((*it)->getName().toUtf8()).toBase64() + QByteArray().append((*it)->getName().toUtf8()).toBase64() +
"?="; "?=";
break; break;
case MimePart::QuotedPrintable: case MimePart::QuotedPrintable:
mime += " =?utf-8?Q?" + mime += " =?utf-8?Q?" +
QuotedPrintable::encode( QuotedPrintable::encode(
QByteArray().append((*it)->getName().toUtf8())) QByteArray().append((*it)->getName().toUtf8()))
.replace(' ', "_") .replace(' ', "_")
.replace(':', "=3A") + .replace(':', "=3A") +
"?="; "?=";
break; break;
default: default:
mime += " " + (*it)->getName(); mime += " " + (*it)->getName();
} }
}
mime += " <" + (*it)->getAddress() + ">";
} }
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().toUtf8()).toBase64() +
"?=";
break;
case MimePart::QuotedPrintable:
mime += " =?utf-8?Q?" +
QuotedPrintable::encode(
QByteArray().append((*it)->getName().toUtf8()))
.replace(' ', "_")
.replace(':', "=3A") +
"?=";
break;
default:
mime += " " + (*it)->getName();
}
}
mime += " <" + (*it)->getAddress() + ">";
}
if (recipientsCc.size() != 0) {
mime += "\r\n"; mime += "\r\n";
} /* ---------------------------------- */
/* ---------------------------------- */
/* ------------ Subject ------------- */ /* ------- Recipients / Cc ---------- */
mime += "Subject: "; if (!recipientsCc.empty()) {
mime += "Cc:";
switch (hEncoding) {
case MimePart::Base64:
mime += "=?utf-8?B?" + QByteArray().append(subject.toUtf8()).toBase64() + "?=";
break;
case MimePart::QuotedPrintable:
mime += "=?utf-8?Q?" +
QuotedPrintable::encode(QByteArray().append(subject.toUtf8()))
.replace(' ', "_")
.replace(':', "=3A") +
"?=";
break;
default:
mime += subject;
}
mime += "\r\n";
/* ---------------------------------- */
/* ---------- Reply-To -------------- */
if (replyTo) {
mime += "Reply-To: ";
if (replyTo->getName() != "") {
switch (hEncoding) {
case MimePart::Base64:
mime += " =?utf-8?B?" +
QByteArray().append(replyTo->getName().toUtf8()).toBase64() + "?=";
break;
case MimePart::QuotedPrintable:
mime += " =?utf-8?Q?" +
QuotedPrintable::encode(QByteArray().append(replyTo->getName().toUtf8()))
.replace(' ', "_")
.replace(':', "=3A") +
"?=";
break;
default:
mime += " " + replyTo->getName();
}
} }
mime += " <" + replyTo->getAddress() + ">\r\n"; 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().toUtf8()).toBase64() +
"?=";
break;
case MimePart::QuotedPrintable:
mime += " =?utf-8?Q?" +
QuotedPrintable::encode(
QByteArray().append((*it)->getName().toUtf8()))
.replace(' ', "_")
.replace(':', "=3A") +
"?=";
break;
default:
mime += " " + (*it)->getName();
}
}
mime += " <" + (*it)->getAddress() + ">";
}
if (!recipientsCc.empty()) {
mime += "\r\n";
}
/* ---------------------------------- */
mime += "MIME-Version: 1.0\r\n"; /* ------------ Subject ------------- */
if (!mInReplyTo.isEmpty()) { mime += "Subject: ";
mime += "In-Reply-To: <" + mInReplyTo + ">\r\n";
mime += "References: <" + mInReplyTo + ">\r\n";
}
QDateTime now = QDateTime::currentDateTime(); switch (hEncoding) {
case MimePart::Base64:
mime += "=?utf-8?B?" + QByteArray().append(subject.toUtf8()).toBase64() + "?=";
break;
case MimePart::QuotedPrintable:
mime += "=?utf-8?Q?" +
QuotedPrintable::encode(QByteArray().append(subject.toUtf8()))
.replace(' ', "_")
.replace(':', "=3A") +
"?=";
break;
default:
mime += subject;
}
mime += "\r\n";
/* ---------------------------------- */
/* ---------- Reply-To -------------- */
if (replyTo) {
mime += "Reply-To: ";
if (replyTo->getName() != "") {
switch (hEncoding) {
case MimePart::Base64:
mime += " =?utf-8?B?" +
QByteArray().append(replyTo->getName().toUtf8()).toBase64() + "?=";
break;
case MimePart::QuotedPrintable:
mime += " =?utf-8?Q?" +
QuotedPrintable::encode(QByteArray().append(replyTo->getName().toUtf8()))
.replace(' ', "_")
.replace(':', "=3A") +
"?=";
break;
default:
mime += " " + replyTo->getName();
}
}
mime += " <" + replyTo->getAddress() + ">\r\n";
}
/* ---------------------------------- */
mime += "MIME-Version: 1.0\r\n";
if (!mInReplyTo.isEmpty()) {
mime += "In-Reply-To: <" + mInReplyTo + ">\r\n";
mime += "References: <" + mInReplyTo + ">\r\n";
}
QDateTime now = QDateTime::currentDateTime();
#if QT_VERSION_MAJOR < 5 // Qt4 workaround since RFC2822Date isn't defined #if QT_VERSION_MAJOR < 5 // Qt4 workaround since RFC2822Date isn't defined
QString shortDayName = QString shortDayName =
QLocale::c().dayName(now.date().dayOfWeek(), QLocale::ShortFormat); QLocale::c().dayName(now.date().dayOfWeek(), QLocale::ShortFormat);
QString shortMonthName = QString shortMonthName =
QLocale::c().monthName(now.date().month(), QLocale::ShortFormat); QLocale::c().monthName(now.date().month(), QLocale::ShortFormat);
int utcOffset = now.secsTo(QDateTime(now.date(), now.time(), Qt::UTC)) / 60; int utcOffset = now.secsTo(QDateTime(now.date(), now.time(), Qt::UTC)) / 60;
char timezoneSign = utcOffset >= 0 ? '+' : '-'; char timezoneSign = utcOffset >= 0 ? '+' : '-';
utcOffset = utcOffset >= 0 ? utcOffset : -utcOffset; utcOffset = utcOffset >= 0 ? utcOffset : -utcOffset;
QString timezone = QString("%1%2%3") QString timezone = QString("%1%2%3")
.arg(timezoneSign) .arg(timezoneSign)
.arg(utcOffset / 60, 2, 10, QChar('0')) .arg(utcOffset / 60, 2, 10, QChar('0'))
.arg(utcOffset % 60, 2, 10, QChar('0')); .arg(utcOffset % 60, 2, 10, QChar('0'));
mime += QString("Date: %1\r\n") mime += QString("Date: %1\r\n")
.arg(now.toString("%1, dd %2 yyyy hh:mm:ss %3") .arg(now.toString("%1, dd %2 yyyy hh:mm:ss %3")
.arg(shortDayName) .arg(shortDayName)
.arg(shortMonthName) .arg(shortMonthName)
.arg(timezone)); .arg(timezone));
#else // Qt5 supported #else // Qt5 supported
mime += QString("Date: %1\r\n").arg(now.toString(Qt::RFC2822Date)); mime += QString("Date: %1\r\n").arg(now.toString(Qt::RFC2822Date));
#endif // support RFC2822Date #endif // support RFC2822Date
mime += content->toString(); mime += content->toString();
return mime; return mime;
} }
/* [3] --- */ /* [3] --- */

View File

@ -22,51 +22,51 @@
#include <QTime> #include <QTime>
const QString MULTI_PART_NAMES[] = { const QString MULTI_PART_NAMES[] = {
"multipart/mixed", // Mixed "multipart/mixed", // Mixed
"multipart/digest", // Digest "multipart/digest", // Digest
"multipart/alternative", // Alternative "multipart/alternative", // Alternative
"multipart/related", // Related "multipart/related", // Related
"multipart/report", // Report "multipart/report", // Report
"multipart/signed", // Signed "multipart/signed", // Signed
"multipart/encrypted" // Encrypted "multipart/encrypted" // Encrypted
}; };
MimeMultiPart::MimeMultiPart(MultiPartType type) { MimeMultiPart::MimeMultiPart(MultiPartType type) {
this->type = type; this->type = type;
this->cType = MULTI_PART_NAMES[this->type]; this->cType = MULTI_PART_NAMES[this->type];
this->cEncoding = _8Bit; this->cEncoding = _8Bit;
QRandomGenerator generator; QRandomGenerator generator;
QCryptographicHash md5(QCryptographicHash::Md5); QCryptographicHash md5(QCryptographicHash::Md5);
md5.addData(QByteArray().append(generator.generate())); md5.addData(QByteArray().append((char) generator.generate()));
cBoundary = md5.result().toHex(); cBoundary = md5.result().toHex();
} }
MimeMultiPart::~MimeMultiPart() {} MimeMultiPart::~MimeMultiPart() = default;
void MimeMultiPart::addPart(MimePart *part) { parts.append(part); } void MimeMultiPart::addPart(MimePart *part) { parts.append(part); }
const QList<MimePart *> &MimeMultiPart::getParts() const { return parts; } const QList<MimePart *> &MimeMultiPart::getParts() const { return parts; }
void MimeMultiPart::prepare() { void MimeMultiPart::prepare() {
QList<MimePart *>::iterator it; QList<MimePart *>::iterator it;
content = ""; content = "";
for (it = parts.begin(); it != parts.end(); it++) { for (it = parts.begin(); it != parts.end(); it++) {
content += QString("--" + cBoundary + "\r\n").toUtf8(); content += QString("--" + cBoundary + "\r\n").toUtf8();
(*it)->prepare(); (*it)->prepare();
content += (*it)->toString().toUtf8(); content += (*it)->toString().toUtf8();
}; };
content += QString("--" + cBoundary + "--\r\n").toUtf8(); content += QString("--" + cBoundary + "--\r\n").toUtf8();
MimePart::prepare(); MimePart::prepare();
} }
void MimeMultiPart::setMimeType(const MultiPartType type) { void MimeMultiPart::setMimeType(const MultiPartType type) {
this->type = type; this->type = type;
this->cType = MULTI_PART_NAMES[type]; this->cType = MULTI_PART_NAMES[type];
} }
MimeMultiPart::MultiPartType MimeMultiPart::getMimeType() const { return type; } MimeMultiPart::MultiPartType MimeMultiPart::getMimeType() const { return type; }

View File

@ -22,25 +22,25 @@
/* [1] Constructors and Destructors */ /* [1] Constructors and Destructors */
MimePart::MimePart() { MimePart::MimePart() {
cEncoding = _7Bit; cEncoding = _7Bit;
prepared = false; prepared = false;
cBoundary = ""; cBoundary = "";
} }
MimePart::~MimePart() { return; } MimePart::~MimePart() = default;
/* [1] --- */ /* [1] --- */
/* [2] Getters and Setters */ /* [2] Getters and Setters */
void MimePart::setContent(const QByteArray &content) { void MimePart::setContent(const QByteArray &content) {
this->content = content; this->content = content;
} }
void MimePart::setHeader(const QString &header) { this->header = header; } void MimePart::setHeader(const QString &header) { this->header = header; }
void MimePart::addHeaderLine(const QString &line) { void MimePart::addHeaderLine(const QString &line) {
this->header += line + "\r\n"; this->header += line + "\r\n";
} }
const QString &MimePart::getHeader() const { return header; } const QString &MimePart::getHeader() const { return header; }
@ -68,7 +68,7 @@ void MimePart::setEncoding(Encoding enc) { this->cEncoding = enc; }
MimePart::Encoding MimePart::getEncoding() const { return this->cEncoding; } MimePart::Encoding MimePart::getEncoding() const { return this->cEncoding; }
MimeContentFormatter &MimePart::getContentFormatter() { MimeContentFormatter &MimePart::getContentFormatter() {
return this->formatter; return this->formatter;
} }
/* [2] --- */ /* [2] --- */
@ -76,10 +76,10 @@ MimeContentFormatter &MimePart::getContentFormatter() {
/* [3] Public methods */ /* [3] Public methods */
QString MimePart::toString() { QString MimePart::toString() {
if (!prepared) if (!prepared)
prepare(); prepare();
return mimeString; return mimeString;
} }
/* [3] --- */ /* [3] --- */
@ -87,75 +87,75 @@ QString MimePart::toString() {
/* [4] Protected methods */ /* [4] Protected methods */
void MimePart::prepare() { void MimePart::prepare() {
mimeString = QString(); mimeString = QString();
/* === Header Prepare === */ /* === Header Prepare === */
/* Content-Type */ /* Content-Type */
mimeString.append("Content-Type: ").append(cType); mimeString.append("Content-Type: ").append(cType);
if (cName != "") if (cName != "")
mimeString.append("; name=\"").append(cName).append("\""); mimeString.append("; name=\"").append(cName).append("\"");
if (cCharset != "") if (cCharset != "")
mimeString.append("; charset=").append(cCharset); mimeString.append("; charset=").append(cCharset);
if (cBoundary != "") if (cBoundary != "")
mimeString.append("; boundary=").append(cBoundary); mimeString.append("; boundary=").append(cBoundary);
mimeString.append("\r\n"); mimeString.append("\r\n");
/* ------------ */ /* ------------ */
/* Content-Transfer-Encoding */ /* Content-Transfer-Encoding */
mimeString.append("Content-Transfer-Encoding: "); mimeString.append("Content-Transfer-Encoding: ");
switch (cEncoding) { switch (cEncoding) {
case _7Bit: case _7Bit:
mimeString.append("7bit\r\n"); mimeString.append("7bit\r\n");
break; break;
case _8Bit: case _8Bit:
mimeString.append("8bit\r\n"); mimeString.append("8bit\r\n");
break; break;
case Base64: case Base64:
mimeString.append("base64\r\n"); mimeString.append("base64\r\n");
break; break;
case QuotedPrintable: case QuotedPrintable:
mimeString.append("quoted-printable\r\n"); mimeString.append("quoted-printable\r\n");
break; break;
} }
/* ------------------------ */ /* ------------------------ */
/* Content-Id */ /* Content-Id */
if (cId != NULL) if (cId != NULL)
mimeString.append("Content-ID: <").append(cId).append(">\r\n"); mimeString.append("Content-ID: <").append(cId).append(">\r\n");
/* ---------- */ /* ---------- */
/* Addition header lines */ /* Addition header lines */
mimeString.append(header).append("\r\n"); mimeString.append(header).append("\r\n");
/* ------------------------- */ /* ------------------------- */
/* === End of Header Prepare === */ /* === End of Header Prepare === */
/* === Content === */ /* === Content === */
switch (cEncoding) { switch (cEncoding) {
case _7Bit: case _7Bit:
mimeString.append(QString(content).toLatin1()); mimeString.append(QString(content).toLatin1());
break; break;
case _8Bit: case _8Bit:
mimeString.append(content); mimeString.append(content);
break; break;
case Base64: case Base64:
mimeString.append(formatter.format(content.toBase64())); mimeString.append(formatter.format(content.toBase64()));
break; break;
case QuotedPrintable: case QuotedPrintable:
mimeString.append(formatter.format(QuotedPrintable::encode(content), true)); mimeString.append(formatter.format(QuotedPrintable::encode(content), true));
break; break;
} }
mimeString.append("\r\n"); mimeString.append("\r\n");
/* === End of Content === */ /* === End of Content === */
prepared = true; prepared = true;
} }
/* [4] --- */ /* [4] --- */

View File

@ -21,13 +21,13 @@
/* [1] Constructors and Destructors */ /* [1] Constructors and Destructors */
MimeText::MimeText(const QString &txt) { MimeText::MimeText(const QString &txt) {
this->text = txt; this->text = txt;
this->cType = "text/plain"; this->cType = "text/plain";
this->cCharset = "utf-8"; this->cCharset = "utf-8";
this->cEncoding = _8Bit; this->cEncoding = _8Bit;
} }
MimeText::~MimeText() {} MimeText::~MimeText() = default;
/* [1] --- */ /* [1] --- */
@ -42,11 +42,11 @@ const QString &MimeText::getText() const { return text; }
/* [3] Protected Methods */ /* [3] Protected Methods */
void MimeText::prepare() { void MimeText::prepare() {
this->content.clear(); this->content.clear();
this->content.append(text.toUtf8()); this->content.append(text.toUtf8());
/* !!! IMPORTANT !!! */ /* !!! IMPORTANT !!! */
MimePart::prepare(); MimePart::prepare();
} }
/* [3] --- */ /* [3] --- */

View File

@ -19,44 +19,44 @@
#include "smtp/quotedprintable.h" #include "smtp/quotedprintable.h"
QString QuotedPrintable::encode(const QByteArray &input) { QString QuotedPrintable::encode(const QByteArray &input) {
QString output; QString output;
char byte; char byte;
const char hex[] = {'0', '1', '2', '3', '4', '5', '6', '7', const char hex[] = {'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
for (int i = 0; i < input.length(); ++i) { for (char i : input) {
byte = input[i]; byte = i;
if ((byte == 0x20) || ((byte >= 33) && (byte <= 126) && (byte != 61))) { if ((byte == 0x20) || ((byte >= 33) && (byte <= 126) && (byte != 61))) {
output.append(byte); output.append(byte);
} else { } else {
output.append('='); output.append('=');
output.append(hex[((byte >> 4) & 0x0F)]); output.append(hex[((byte >> 4) & 0x0F)]);
output.append(hex[(byte & 0x0F)]); output.append(hex[(byte & 0x0F)]);
}
} }
}
return output; return output;
} }
QByteArray QuotedPrintable::decode(const QString &input) { QByteArray QuotedPrintable::decode(const QString &input) {
// 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B // 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B
// C D E F // C D E F
const int hexVal[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 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}; 0, 0, 0, 0, 0, 10, 11, 12, 13, 14, 15};
QByteArray output; QByteArray output;
for (int i = 0; i < input.length(); ++i) { for (int i = 0; i < input.length(); ++i) {
if (input.at(i).toLatin1() == '=') { if (input.at(i).toLatin1() == '=') {
output.append((hexVal[input.at(i + 1).toLatin1() - '0'] << 4) + output.append((hexVal[input.at(i + 1).toLatin1() - '0'] << 4) +
hexVal[input.at(i + 2).toLatin1() - '0']); hexVal[input.at(i + 2).toLatin1() - '0']);
i += 2; i += 2;
} else { } else {
output.append(input.at(i).toLatin1()); output.append(input.at(i).toLatin1());
}
} }
}
return output; return output;
} }

View File

@ -25,24 +25,24 @@
SmtpClient::SmtpClient(const QString &host, int port, SmtpClient::SmtpClient(const QString &host, int port,
ConnectionType connectionType) ConnectionType connectionType)
: socket(NULL), name("localhost"), authMethod(AuthPlain), : socket(NULL), name("localhost"), authMethod(AuthPlain),
connectionTimeout(5000), responseTimeout(5000), connectionTimeout(5000), responseTimeout(5000),
sendMessageTimeout(60000) { sendMessageTimeout(60000) {
setConnectionType(connectionType); setConnectionType(connectionType);
this->host = host; this->host = host;
this->port = port; this->port = port;
connect(socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, connect(socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this,
SLOT(socketStateChanged(QAbstractSocket::SocketState))); SLOT(socketStateChanged(QAbstractSocket::SocketState)));
connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this,
SLOT(socketError(QAbstractSocket::SocketError))); SLOT(socketError(QAbstractSocket::SocketError)));
connect(socket, SIGNAL(readyRead()), this, SLOT(socketReadyRead())); connect(socket, SIGNAL(readyRead()), this, SLOT(socketReadyRead()));
} }
SmtpClient::~SmtpClient() { SmtpClient::~SmtpClient() {
if (socket) if (socket)
delete socket; delete socket;
} }
/* [1] --- */ /* [1] --- */
@ -52,7 +52,7 @@ SmtpClient::~SmtpClient() {
void SmtpClient::setUser(const QString &user) { this->user = user; } void SmtpClient::setUser(const QString &user) { this->user = user; }
void SmtpClient::setPassword(const QString &password) { void SmtpClient::setPassword(const QString &password) {
this->password = password; this->password = password;
} }
void SmtpClient::setAuthMethod(AuthMethod method) { this->authMethod = method; } void SmtpClient::setAuthMethod(AuthMethod method) { this->authMethod = method; }
@ -62,19 +62,19 @@ void SmtpClient::setHost(const QString &host) { this->host = host; }
void SmtpClient::setPort(int port) { this->port = port; } void SmtpClient::setPort(int port) { this->port = port; }
void SmtpClient::setConnectionType(ConnectionType ct) { void SmtpClient::setConnectionType(ConnectionType ct) {
this->connectionType = ct; this->connectionType = ct;
if (socket) if (socket)
delete socket; delete socket;
switch (connectionType) { switch (connectionType) {
case TcpConnection: case TcpConnection:
socket = new QTcpSocket(this); socket = new QTcpSocket(this);
break; break;
case SslConnection: case SslConnection:
case TlsConnection: case TlsConnection:
socket = new QSslSocket(this); socket = new QSslSocket(this);
} }
} }
const QString &SmtpClient::getHost() const { return this->host; } const QString &SmtpClient::getHost() const { return this->host; }
@ -84,13 +84,13 @@ const QString &SmtpClient::getUser() const { return this->user; }
const QString &SmtpClient::getPassword() const { return this->password; } const QString &SmtpClient::getPassword() const { return this->password; }
SmtpClient::AuthMethod SmtpClient::getAuthMethod() const { SmtpClient::AuthMethod SmtpClient::getAuthMethod() const {
return this->authMethod; return this->authMethod;
} }
int SmtpClient::getPort() const { return this->port; } int SmtpClient::getPort() const { return this->port; }
SmtpClient::ConnectionType SmtpClient::getConnectionType() const { SmtpClient::ConnectionType SmtpClient::getConnectionType() const {
return connectionType; return connectionType;
} }
const QString &SmtpClient::getName() const { return this->name; } const QString &SmtpClient::getName() const { return this->name; }
@ -110,7 +110,9 @@ void SmtpClient::setConnectionTimeout(int msec) { connectionTimeout = msec; }
int SmtpClient::getResponseTimeout() const { return responseTimeout; } int SmtpClient::getResponseTimeout() const { return responseTimeout; }
void SmtpClient::setResponseTimeout(int msec) { responseTimeout = msec; } void SmtpClient::setResponseTimeout(int msec) { responseTimeout = msec; }
int SmtpClient::getSendMessageTimeout() const { return sendMessageTimeout; } int SmtpClient::getSendMessageTimeout() const { return sendMessageTimeout; }
void SmtpClient::setSendMessageTimeout(int msec) { sendMessageTimeout = msec; } void SmtpClient::setSendMessageTimeout(int msec) { sendMessageTimeout = msec; }
/* [2] --- */ /* [2] --- */
@ -118,239 +120,239 @@ void SmtpClient::setSendMessageTimeout(int msec) { sendMessageTimeout = msec; }
/* [3] Public methods */ /* [3] Public methods */
bool SmtpClient::connectToHost() { bool SmtpClient::connectToHost() {
switch (connectionType) { switch (connectionType) {
case TlsConnection: case TlsConnection:
case TcpConnection: case TcpConnection:
socket->connectToHost(host, port); socket->connectToHost(host, port);
break; break;
case SslConnection: case SslConnection:
((QSslSocket *)socket)->connectToHostEncrypted(host, port); ((QSslSocket *) socket)->connectToHostEncrypted(host, port);
break; 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 // Tries to connect to server
// The client's first command must be EHLO/HELO if (!socket->waitForConnected(connectionTimeout)) {
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); emit smtpError(ConnectionTimeoutError);
return false; 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. try {
return true; // 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() { return login(user, password, authMethod); }
bool SmtpClient::login(const QString &user, const QString &password, bool SmtpClient::login(const QString &user, const QString &password,
AuthMethod method) { AuthMethod method) {
try { try {
if (method == AuthPlain) { if (method == AuthPlain) {
// Sending command: AUTH PLAIN base64('\0' + username + '\0' + password) // Sending command: AUTH PLAIN base64('\0' + username + '\0' + password)
sendMessage("AUTH PLAIN " + QByteArray() sendMessage("AUTH PLAIN " + QByteArray()
.append((char)0) .append((char) 0)
.append(user.toUtf8()) .append(user.toUtf8())
.append((char)0) .append((char) 0)
.append(password.toUtf8()) .append(password.toUtf8())
.toBase64()); .toBase64());
// Wait for the server's response // Wait for the server's response
waitForResponse(); waitForResponse();
// If the response is not 235 then the authentication was faild // If the response is not 235 then the authentication was faild
if (responseCode != 235) { 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.toUtf8()).toBase64());
// Wait for 334
waitForResponse();
if (responseCode != 334) {
emit smtpError(AuthenticationFailedError);
return false;
}
// Send the password in base64
sendMessage(QByteArray().append(password.toUtf8()).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) {
// Responce Timeout exceeded
emit smtpError(AuthenticationFailedError); emit smtpError(AuthenticationFailedError);
return false; return false;
} } catch (SendMessageTimeoutException) {
} else if (method == AuthLogin) { // Send Timeout exceeded
// Sending command: AUTH LOGIN
sendMessage("AUTH LOGIN");
// Wait for 334 response code
waitForResponse();
if (responseCode != 334) {
emit smtpError(AuthenticationFailedError); emit smtpError(AuthenticationFailedError);
return false; return false;
}
// Send the username in base64
sendMessage(QByteArray().append(user.toUtf8()).toBase64());
// Wait for 334
waitForResponse();
if (responseCode != 334) {
emit smtpError(AuthenticationFailedError);
return false;
}
// Send the password in base64
sendMessage(QByteArray().append(password.toUtf8()).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) {
// Responce Timeout exceeded
emit smtpError(AuthenticationFailedError);
return false;
} catch (SendMessageTimeoutException) {
// Send Timeout exceeded
emit smtpError(AuthenticationFailedError);
return false;
}
return true; return true;
} }
bool SmtpClient::sendMail(MimeMessage &email) { bool SmtpClient::sendMail(MimeMessage &email) {
try { try {
// Send the MAIL command with the sender // Send the MAIL command with the sender
sendMessage("MAIL FROM:<" + email.getSender().getAddress() + ">"); sendMessage("MAIL FROM:<" + email.getSender().getAddress() + ">");
waitForResponse(); waitForResponse();
if (responseCode != 250) if (responseCode != 250)
return false; return false;
// Send RCPT command for each recipient // Send RCPT command for each recipient
QList<EmailAddress *>::const_iterator it, itEnd; QList<EmailAddress *>::const_iterator it, itEnd;
// To (primary recipients) // To (primary recipients)
for (it = email.getRecipients().begin(), for (it = email.getRecipients().begin(),
itEnd = email.getRecipients().end(); itEnd = email.getRecipients().end();
it != itEnd; ++it) { it != itEnd; ++it) {
sendMessage("RCPT TO:<" + (*it)->getAddress() + ">"); sendMessage("RCPT TO:<" + (*it)->getAddress() + ">");
waitForResponse(); waitForResponse();
if (responseCode != 250) 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 false;
} }
// Cc (carbon copy) return true;
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() { void SmtpClient::quit() {
try { try {
sendMessage("QUIT"); sendMessage("QUIT");
} catch (SmtpClient::SendMessageTimeoutException) { } catch (SmtpClient::SendMessageTimeoutException) {
// Manually close the connection to the smtp server if message "QUIT" wasn't // Manually close the connection to the smtp server if message "QUIT" wasn't
// received by the smtp server // received by the smtp server
if (socket->state() == QAbstractSocket::ConnectedState || if (socket->state() == QAbstractSocket::ConnectedState ||
socket->state() == QAbstractSocket::ConnectingState || socket->state() == QAbstractSocket::ConnectingState ||
socket->state() == QAbstractSocket::HostLookupState) socket->state() == QAbstractSocket::HostLookupState)
socket->disconnectFromHost(); socket->disconnectFromHost();
} }
} }
/* [3] --- */ /* [3] --- */
@ -358,38 +360,38 @@ void SmtpClient::quit() {
/* [4] Protected methods */ /* [4] Protected methods */
void SmtpClient::waitForResponse() { void SmtpClient::waitForResponse() {
do { do {
if (!socket->waitForReadyRead(responseTimeout)) { if (!socket->waitForReadyRead(responseTimeout)) {
emit smtpError(ResponseTimeoutError); emit smtpError(ResponseTimeoutError);
throw ResponseTimeoutException(); throw ResponseTimeoutException();
} }
while (socket->canReadLine()) { while (socket->canReadLine()) {
// Save the server's response // Save the server's response
responseText = socket->readLine(); responseText = socket->readLine();
// Extract the respose code from the server's responce (first 3 digits) // Extract the respose code from the server's responce (first 3 digits)
responseCode = responseText.left(3).toInt(); responseCode = responseText.leftRef(3).toInt();
if (responseCode / 100 == 4) if (responseCode / 100 == 4)
emit smtpError(ServerError); emit smtpError(ServerError);
if (responseCode / 100 == 5) if (responseCode / 100 == 5)
emit smtpError(ClientError); emit smtpError(ClientError);
if (responseText[3] == ' ') { if (responseText[3] == ' ') {
return; return;
} }
} }
} while (true); } while (true);
} }
void SmtpClient::sendMessage(const QString &text) { void SmtpClient::sendMessage(const QString &text) {
socket->write(text.toUtf8() + "\r\n"); socket->write(text.toUtf8() + "\r\n");
if (!socket->waitForBytesWritten(sendMessageTimeout)) { if (!socket->waitForBytesWritten(sendMessageTimeout)) {
emit smtpError(SendDataTimeoutError); emit smtpError(SendDataTimeoutError);
throw SendMessageTimeoutException(); throw SendMessageTimeoutException();
} }
} }
/* [4] --- */ /* [4] --- */