Version 1.1 beta
This commit is contained in:
parent
560eb49344
commit
538c068278
@ -19,7 +19,11 @@ SOURCES += \
|
||||
src/mimemessage.cpp \
|
||||
src/mimepart.cpp \
|
||||
src/mimetext.cpp \
|
||||
src/smtpclient.cpp
|
||||
src/smtpclient.cpp \
|
||||
src/quotedprintable.cpp \
|
||||
src/mimemultipart.cpp \
|
||||
test.cpp \
|
||||
src/mimecontentformatter.cpp
|
||||
|
||||
HEADERS += \
|
||||
src/emailaddress.h \
|
||||
@ -31,7 +35,10 @@ HEADERS += \
|
||||
src/mimepart.h \
|
||||
src/mimetext.h \
|
||||
src/smtpclient.h \
|
||||
src/SmtpMime
|
||||
src/SmtpMime \
|
||||
src/quotedprintable.h \
|
||||
src/mimemultipart.h \
|
||||
src/mimecontentformatter.h
|
||||
|
||||
OTHER_FILES += \
|
||||
LICENSE \
|
||||
|
44
src/mimecontentformatter.cpp
Normal file
44
src/mimecontentformatter.cpp
Normal file
@ -0,0 +1,44 @@
|
||||
#include "mimecontentformatter.h"
|
||||
|
||||
MimeContentFormatter::MimeContentFormatter(int max_length) :
|
||||
max_length(max_length)
|
||||
{}
|
||||
|
||||
QString MimeContentFormatter::format(const QString &content, bool quotedPrintable) {
|
||||
|
||||
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;
|
||||
}
|
22
src/mimecontentformatter.h
Normal file
22
src/mimecontentformatter.h
Normal file
@ -0,0 +1,22 @@
|
||||
#ifndef MIMECONTENTFORMATTER_H
|
||||
#define MIMECONTENTFORMATTER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QByteArray>
|
||||
|
||||
class MimeContentFormatter : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
MimeContentFormatter (int max_length = 76);
|
||||
|
||||
void setMaxLength(int l);
|
||||
|
||||
QString format(const QString &content, bool quotedPrintable = false);
|
||||
|
||||
protected:
|
||||
int max_length;
|
||||
|
||||
};
|
||||
|
||||
#endif // MIMECONTENTFORMATTER_H
|
@ -18,12 +18,15 @@
|
||||
|
||||
#include <QDateTime>
|
||||
#include "quotedprintable.h"
|
||||
#include <typeinfo>
|
||||
|
||||
/* [1] Constructors and Destructors */
|
||||
|
||||
MimeMessage::MimeMessage() :
|
||||
MimeMessage::MimeMessage(bool createAutoMimeContent) :
|
||||
hEncoding(MimePart::_8Bit)
|
||||
{
|
||||
if (createAutoMimeContent)
|
||||
this->content = new MimeMultiPart();
|
||||
}
|
||||
|
||||
MimeMessage::~MimeMessage()
|
||||
@ -41,9 +44,32 @@ void MimeMessage::setSender(EmailAddress* e)
|
||||
this->sender = e;
|
||||
}
|
||||
|
||||
void MimeMessage::addRecipient(EmailAddress* rcpt)
|
||||
void MimeMessage::addRecipient(EmailAddress* rcpt, RecipientType type)
|
||||
{
|
||||
this->recipients << rcpt;
|
||||
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)
|
||||
@ -53,7 +79,9 @@ void MimeMessage::setSubject(const QString & subject)
|
||||
|
||||
void MimeMessage::addPart(MimePart *part)
|
||||
{
|
||||
this->parts << part;
|
||||
if (typeid(*content) == typeid(MimeMultiPart)) {
|
||||
((MimeMultiPart*) content)->addPart(part);
|
||||
};
|
||||
}
|
||||
|
||||
void MimeMessage::setHeaderEncoding(MimePart::Encoding hEnc)
|
||||
@ -66,9 +94,18 @@ const EmailAddress & MimeMessage::getSender() const
|
||||
return *sender;
|
||||
}
|
||||
|
||||
const QList<EmailAddress*> & MimeMessage::getRecipients() const
|
||||
const QList<EmailAddress*> & MimeMessage::getRecipients(RecipientType type) const
|
||||
{
|
||||
return recipients;
|
||||
switch (type)
|
||||
{
|
||||
default:
|
||||
case To:
|
||||
return recipientsTo;
|
||||
case Cc:
|
||||
return recipientsCc;
|
||||
case Bcc:
|
||||
return recipientsBcc;
|
||||
}
|
||||
}
|
||||
|
||||
const QString & MimeMessage::getSubject() const
|
||||
@ -78,7 +115,15 @@ const QString & MimeMessage::getSubject() const
|
||||
|
||||
const QList<MimePart*> & MimeMessage::getParts() const
|
||||
{
|
||||
return parts;
|
||||
if (typeid(content) == typeid(MimeMultiPart)) {
|
||||
return static_cast<MimeMultiPart*>(content)->getParts();
|
||||
}
|
||||
else {
|
||||
QList<MimePart*> *res = new QList<MimePart*>();
|
||||
res->append(content);
|
||||
return *res;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* [2] --- */
|
||||
@ -113,10 +158,11 @@ QString MimeMessage::toString()
|
||||
|
||||
|
||||
/* ------- Recipients / To ---------- */
|
||||
QList<EmailAddress*>::iterator it;
|
||||
for (it = recipients.begin(); it != recipients.end(); ++it)
|
||||
mime += "To:";
|
||||
QList<EmailAddress*>::iterator it; int i;
|
||||
for (i = 0, it = recipientsTo.begin(); it != recipientsTo.end(); ++it, ++i)
|
||||
{
|
||||
mime += "To:";
|
||||
if (i != 0) { mime += ","; }
|
||||
|
||||
if ((*it)->getName() != "")
|
||||
{
|
||||
@ -132,13 +178,40 @@ QString MimeMessage::toString()
|
||||
mime += " " + (*it)->getName();
|
||||
}
|
||||
}
|
||||
mime += " <" + (*it)->getAddress() + ">\r\n";
|
||||
mime += " <" + (*it)->getAddress() + ">";
|
||||
}
|
||||
mime += "\r\n";
|
||||
/* ---------------------------------- */
|
||||
|
||||
/* ------- Recipients / Cc ---------- */
|
||||
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() + ">";
|
||||
}
|
||||
mime += "\r\n";
|
||||
/* ---------------------------------- */
|
||||
|
||||
/* ------------ Subject ------------- */
|
||||
mime += "Subject: ";
|
||||
|
||||
|
||||
switch (hEncoding)
|
||||
{
|
||||
case MimePart::Base64:
|
||||
@ -153,26 +226,9 @@ QString MimeMessage::toString()
|
||||
/* ---------------------------------- */
|
||||
|
||||
mime += "\r\n";
|
||||
|
||||
QString boundary = "----MIME-part-boundary=" + QByteArray().append(QDateTime::currentDateTime().toString()).toBase64() + "-end";
|
||||
|
||||
mime += "MIME-Version: 1.0\r\n";
|
||||
mime += "Content-type: multipart/mixed; boundary=\"" + boundary + "\"\r\n\r\n";
|
||||
|
||||
/* ====== END OF MIME HEADER ======== */
|
||||
|
||||
boundary = "--" + boundary;
|
||||
|
||||
/* ========== MIME BODY ============= */
|
||||
|
||||
QList<MimePart*>::iterator i;
|
||||
for (i = parts.begin(); i != parts.end(); ++i)
|
||||
mime += boundary + "\r\n" + (*i)->toString();
|
||||
|
||||
mime += boundary + "--\r\n";
|
||||
|
||||
/* ====== END OF MIME BODY ========= */
|
||||
|
||||
mime += content->toString();
|
||||
return mime;
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
#define MIMEMESSAGE_H
|
||||
|
||||
#include "mimepart.h"
|
||||
#include "mimemultipart.h"
|
||||
#include "emailaddress.h"
|
||||
#include <QList>
|
||||
|
||||
@ -25,9 +26,15 @@ class MimeMessage : public QObject
|
||||
{
|
||||
public:
|
||||
|
||||
enum RecipientType {
|
||||
To, // primary
|
||||
Cc, // carbon copy
|
||||
Bcc // blind carbon copy
|
||||
};
|
||||
|
||||
/* [1] Constructors and Destructors */
|
||||
|
||||
MimeMessage();
|
||||
MimeMessage(bool createAutoMimeConent = true);
|
||||
~MimeMessage();
|
||||
|
||||
/* [1] --- */
|
||||
@ -36,14 +43,17 @@ public:
|
||||
/* [2] Getters and Setters */
|
||||
|
||||
void setSender(EmailAddress* e);
|
||||
void addRecipient(EmailAddress* rcpt);
|
||||
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() const;
|
||||
const QList<EmailAddress*> & getRecipients(RecipientType type = To) const;
|
||||
const QString & getSubject() const;
|
||||
const QList<MimePart*> & getParts() const;
|
||||
|
||||
@ -61,9 +71,9 @@ protected:
|
||||
/* [4] Protected members */
|
||||
|
||||
EmailAddress* sender;
|
||||
QList<EmailAddress*> recipients;
|
||||
QList<EmailAddress*> recipientsTo, recipientsCc, recipientsBcc;
|
||||
QString subject;
|
||||
QList<MimePart*> parts;
|
||||
MimePart *content;
|
||||
|
||||
MimePart::Encoding hEncoding;
|
||||
|
||||
|
52
src/mimemultipart.cpp
Normal file
52
src/mimemultipart.cpp
Normal file
@ -0,0 +1,52 @@
|
||||
#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;
|
||||
|
||||
qsrand(QTime::currentTime().msec());
|
||||
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();
|
||||
}
|
69
src/mimemultipart.h
Normal file
69
src/mimemultipart.h
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
Copyright (c) 2012 - Tőkés Attila (tokes_atti@yahoo.com)
|
||||
|
||||
This file is part of SmtpClient for Qt.
|
||||
|
||||
SmtpClient for Qt is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
SmtpClient for Qt is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY.
|
||||
|
||||
See the LICENSE file for more details.
|
||||
*/
|
||||
|
||||
#ifndef MIMEMULTIPART_H
|
||||
#define MIMEMULTIPART_H
|
||||
|
||||
#include "mimepart.h"
|
||||
|
||||
class 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 */
|
||||
|
||||
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
|
@ -23,6 +23,7 @@ MimePart::MimePart()
|
||||
{
|
||||
cEncoding = _7Bit;
|
||||
prepared = false;
|
||||
cBoundary = "";
|
||||
}
|
||||
|
||||
MimePart::~MimePart()
|
||||
@ -47,7 +48,7 @@ void MimePart::setHeader(const QString & header)
|
||||
|
||||
void MimePart::addHeaderLine(const QString & line)
|
||||
{
|
||||
this->header += line;
|
||||
this->header += line + "\r\n";
|
||||
}
|
||||
|
||||
const QString& MimePart::getHeader() const
|
||||
@ -143,6 +144,9 @@ void MimePart::prepare()
|
||||
if (cCharset != "")
|
||||
mimeString.append("; charset=").append(cCharset);
|
||||
|
||||
if (cBoundary != "")
|
||||
mimeString.append("; boundary=").append(cBoundary);
|
||||
|
||||
mimeString.append("\r\n");
|
||||
/* ------------ */
|
||||
|
||||
@ -170,14 +174,15 @@ void MimePart::prepare()
|
||||
mimeString.append("Content-ID: <").append(cId).append(">\r\n");
|
||||
/* ---------- */
|
||||
|
||||
|
||||
/* ------------------------- */
|
||||
/* Addition header lines */
|
||||
|
||||
mimeString.append(header).append("\r\n");
|
||||
|
||||
/* ------------------------- */
|
||||
|
||||
/* === End of Header Prepare === */
|
||||
|
||||
/* === Content Encoding === */
|
||||
/* === Content === */
|
||||
switch (cEncoding)
|
||||
{
|
||||
case _7Bit:
|
||||
@ -187,14 +192,14 @@ void MimePart::prepare()
|
||||
mimeString.append(content);
|
||||
break;
|
||||
case Base64:
|
||||
mimeString.append(content.toBase64());
|
||||
mimeString.append(formatter.format(content.toBase64()));
|
||||
break;
|
||||
case QuotedPrintable:
|
||||
mimeString.append(QuotedPrintable::encode(content));
|
||||
mimeString.append(formatter.format(QuotedPrintable::encode(content), true));
|
||||
break;
|
||||
}
|
||||
mimeString.append("\r\n");
|
||||
/* === End of Content Encoding === */
|
||||
/* === End of Content === */
|
||||
|
||||
prepared = true;
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
||||
#define MIMEPART_H
|
||||
|
||||
#include <QObject>
|
||||
#include "mimecontentformatter.h"
|
||||
|
||||
class MimePart : public QObject
|
||||
{
|
||||
@ -93,11 +94,14 @@ protected:
|
||||
QString cName;
|
||||
QString cType;
|
||||
QString cCharset;
|
||||
QString cBoundary;
|
||||
Encoding cEncoding;
|
||||
|
||||
QString mimeString;
|
||||
bool prepared;
|
||||
|
||||
MimeContentFormatter formatter;
|
||||
|
||||
/* [4] --- */
|
||||
};
|
||||
|
||||
|
@ -267,9 +267,32 @@ bool SmtpClient::sendMail(MimeMessage& email)
|
||||
if (responseCode != 250) return false;
|
||||
|
||||
// Send RCPT command for each recipient
|
||||
for (int i = 0; i < email.getRecipients().size(); ++i)
|
||||
QList<EmailAddress*>::const_iterator it, itEnd;
|
||||
// To (primary recipients)
|
||||
for (it = email.getRecipients().begin(), itEnd = email.getRecipients().end();
|
||||
it != itEnd; ++it)
|
||||
{
|
||||
sendMessage("RCPT TO: <" + email.getRecipients().at(i)->getAddress() + ">");
|
||||
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;
|
||||
|
Loading…
Reference in New Issue
Block a user