aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/CMakeLists.txt7
-rw-r--r--src/Mime.cpp233
-rw-r--r--src/gpg/GpgContext.cpp55
-rw-r--r--src/smtp/CMakeLists.txt6
-rw-r--r--src/smtp/emailaddress.cpp44
-rw-r--r--src/smtp/mimeattachment.cpp43
-rw-r--r--src/smtp/mimecontentformatter.cpp59
-rw-r--r--src/smtp/mimefile.cpp61
-rw-r--r--src/smtp/mimehtml.cpp46
-rw-r--r--src/smtp/mimeinlinefile.cpp42
-rw-r--r--src/smtp/mimemessage.cpp308
-rw-r--r--src/smtp/mimemultipart.cpp70
-rw-r--r--src/smtp/mimepart.cpp159
-rw-r--r--src/smtp/mimetext.cpp52
-rw-r--r--src/smtp/quotedprintable.cpp62
-rw-r--r--src/smtp/smtpclient.cpp407
-rw-r--r--src/ui/AttachmentTableModel.cpp134
-rw-r--r--src/ui/main_window/MainWindowSlotUI.cpp7
-rw-r--r--src/ui/main_window/MainWindowUI.cpp22
-rw-r--r--src/ui/widgets/Attachments.cpp180
20 files changed, 1363 insertions, 634 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 243570e5..03eaac9e 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -2,6 +2,7 @@ set(ALL_SOURCE_FILE)
add_subdirectory(gpg)
add_subdirectory(ui)
+add_subdirectory(smtp)
aux_source_directory(. BASE_SOURCE)
@@ -121,19 +122,19 @@ endif()
IF (MINGW)
message(STATUS "Link Application Static Library For MINGW")
target_link_libraries(${AppName}
- gpgfrontend-ui gpg
+ smtp gpgfrontend-ui gpg
Qt5::Network Qt5::PrintSupport Qt5::Widgets Qt5::Test Qt5::Core
crypto ssl)
elseif(APPLE)
message(STATUS "Link Application Static Library For macOS")
target_link_libraries(${AppName}
- gpgfrontend-ui gpg
+ smtp gpgfrontend-ui gpg
Qt5::Network Qt5::PrintSupport Qt5::Widgets Qt5::Test Qt5::Core
crypto ssl)
else()
message(STATUS "Link Application Static Library For UNIX")
target_link_libraries(${AppName}
- gpgfrontend-ui gpg
+ smtp gpgfrontend-ui gpg
Qt5::Network Qt5::PrintSupport Qt5::Widgets Qt5::Test Qt5::Core
crypto ssl pthread)
endif()
diff --git a/src/Mime.cpp b/src/Mime.cpp
deleted file mode 100644
index 8e4c8d72..00000000
--- a/src/Mime.cpp
+++ /dev/null
@@ -1,233 +0,0 @@
-/**
- * This file is part of GPGFrontend.
- *
- * GPGFrontend 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 3 of the License, or
- * (at your option) any later version.
- *
- * Foobar 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Foobar. If not, see <https://www.gnu.org/licenses/>.
- *
- * The initial version of the source code is inherited from gpg4usb-team.
- * Their source code version also complies with GNU General Public License.
- *
- * The source code version of this software was modified and released
- * by Saturneric<[email protected]> starting on May 12, 2021.
- *
- */
-
-/* TODO: proper import / copyright statement
- *
- */
-
-#include "Mime.h"
-
-Mime::Mime(QByteArray *message) {
- splitParts(message);
- /*
- mMessage = message;
- int bStart = mMessage->indexOf("boundary=\"") + 10 ;
- int bEnd = mMessage->indexOf("\"\n", bStart );
-
- qDebug() << "bStart: " << bStart << " bEnd: " << bEnd;
- mBoundary = new QByteArray(mMessage->mid(bStart, bEnd - bStart));
- qDebug() << "boundary: " << *mBoundary;
-
- Part *p1 = new Part();
-
- int nb = mMessage->indexOf(*mBoundary, bEnd) + mBoundary->length() +1 ;
- qDebug() << "nb: " << nb;
- int eh = mMessage->indexOf("\n\n", nb);
- qDebug() << "eh: " << eh;
- QByteArray *header = new QByteArray(mMessage->mid(nb , eh - nb));
- qDebug() << "header:" << header;
-
- // split header at newlines
- foreach(QByteArray tmp , header->split(* "\n")) {
- // split lines at :
- QList<QByteArray> tmp2 = tmp.split(* ":");
- p1->header.insert(QString(tmp2[0].trimmed()), QString(tmp2[1].trimmed()));
- }
-
- QHashIterator<QString, QString> i(p1->header);
- while (i.hasNext()) {
- i.next();
- qDebug() << "found: " << i.key() << ":" << i.value() << endl;
- }
-
- int nb2 = mMessage->indexOf(*mBoundary, eh);
-
- p1->body = mMessage->mid(eh , nb2 - eh);
-
- QTextCodec *codec = QTextCodec::codecForName("ISO-8859-15");
- QString qs = codec->toUnicode(p1->body);
- qDebug() << "body: " << qs;
- */
-}
-
-Mime::~Mime()
-= default;
-
-void Mime::splitParts(QByteArray *message) {
- int pos1, pos2, headEnd;
- MimePart p_tmp;
-
- // find the boundary
- pos1 = message->indexOf("boundary=\"") + 10;
- pos2 = message->indexOf("\"\n", pos1);
- QByteArray boundary = message->mid(pos1, pos2 - pos1);
- //qDebug() << "boundary: " << boundary;
-
- while (pos2 > pos1) {
-
- pos1 = message->indexOf(boundary, pos2) + boundary.length() + 1;
- headEnd = message->indexOf("\n\n", pos1);
- if (headEnd < 0)
- break;
- QByteArray header = message->mid(pos1, headEnd - pos1);
-
- p_tmp.header = parseHeader(&header);
-
- pos2 = message->indexOf(boundary, headEnd);
- p_tmp.body = message->mid(headEnd, pos2 - headEnd);
-
- mPartList.append(p_tmp);
- }
-}
-
-Header Mime::parseHeader(QByteArray *header) {
-
- QList<HeadElem> ret;
-
- /** http://www.aspnetmime.com/help/welcome/overviewmimeii.html :
- * If a line starts with any white space, that line is said to be 'folded' and is actually
- * part of the header above it.
- */
- header->replace("\n ", " ");
-
- //split header at newlines
- foreach(QByteArray line, header->split(*"\n")) {
- HeadElem elem;
- //split lines at :
- QList<QByteArray> tmp2 = line.split(*":");
- elem.name = tmp2[0].trimmed();
- if (tmp2[1].contains(';')) {
- // split lines at ;
- // TODO: what if ; is inside ""
- QList<QByteArray> tmp3 = tmp2[1].split(*";");
- elem.value = QString(tmp3.takeFirst().trimmed());
- foreach(QByteArray tmp4, tmp3) {
- QList<QByteArray> tmp5 = tmp4.split(*"=");
- elem.params.insert(QString(tmp5[0].trimmed()), QString(tmp5[1].trimmed()));
- }
- } else {
- elem.value = tmp2[1].trimmed();
- }
- ret.append(elem);
- }
- return Header(ret);
-}
-
-Header Mime::getHeader(const QByteArray *message) {
- int headEnd = message->indexOf("\n\n");
- QByteArray header = message->mid(0, headEnd);
- return parseHeader(&header);
-}
-
-bool Mime::isMultipart(QByteArray *message) {
- return message->startsWith("Content-Type: multipart/mixed;");
-}
-
-/**
- * if Content-Type is specified, it should be mime
- *
- */
-bool Mime::isMime(const QByteArray *message) {
- return message->startsWith("Content-Type:");
-}
-
-/***
- * quotedPrintableDecode copied from KCodecs, where it is stated:
-
- The quoted-printable codec as described in RFC 2045, section 6.7. is by
- Rik Hemsley (C) 2001.
-
- */
-
-static const char hexChars[16] = {
- '0', '1', '2', '3', '4', '5', '6', '7',
- '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
-};
-
-/******************************** KCodecs ********************************/
-// strchr(3) for broken systems.
-static int rikFindChar(const char *_s, const char c) {
- const char *s = _s;
-
- while (true) {
- if ((0 == *s) || (c == *s)) break;
- ++s;
- if ((0 == *s) || (c == *s)) break;
- ++s;
- if ((0 == *s) || (c == *s)) break;
- ++s;
- if ((0 == *s) || (c == *s)) break;
- ++s;
- }
-
- return static_cast<int>(s - _s);
-}
-
-void Mime::quotedPrintableDecode(const QByteArray &in, QByteArray &out) {
- // clear out the output buffer
- out.resize(0);
- if (in.isEmpty())
- return;
-
- char *cursor;
- const char *data;
- const size_t length = in.size();
-
- data = in.data();
- out.resize(static_cast<int>(length));
- cursor = out.data();
-
- for (unsigned int i = 0; i < length; i++) {
- char c(in[i]);
-
- if ('=' == c) {
- if (i < length - 2) {
- char c1 = in[i + 1];
- char c2 = in[i + 2];
-
- if (('\n' == c1) || ('\r' == c1 && '\n' == c2)) {
- // Soft line break. No output.
- if ('\r' == c1)
- i += 2; // CRLF line breaks
- else
- i += 1;
- } else {
- // =XX encoded byte.
-
- int hexChar0 = rikFindChar(hexChars, c1);
- int hexChar1 = rikFindChar(hexChars, c2);
-
- if (hexChar0 < 16 && hexChar1 < 16) {
- *cursor++ = char((hexChar0 * 16) | hexChar1);
- i += 2;
- }
- }
- }
- } else {
- *cursor++ = c;
- }
- }
-
- out.truncate(static_cast<int>(cursor - out.data()));
-}
diff --git a/src/gpg/GpgContext.cpp b/src/gpg/GpgContext.cpp
index 028653b7..7ec521a7 100644
--- a/src/gpg/GpgContext.cpp
+++ b/src/gpg/GpgContext.cpp
@@ -25,7 +25,6 @@
#include "gpg/GpgContext.h"
#include <unistd.h> /* contains read/write */
-#include <Mime.h>
#ifdef _WIN32
@@ -430,38 +429,6 @@ namespace GpgME {
return err;
}
-
- /**
- * if this is mime, split text and attachments...
- * message contains only text afterwards
- */
- void parseMime(QByteArray *message) {
-
- QString pText;
- bool show_ma_dock = false;
-
- Mime *mime = new Mime(message);
- for (MimePart tmp : mime->parts()) {
- if (tmp.header.getValue("Content-Type") == "text/plain" &&
- tmp.header.getValue("Content-Transfer-Encoding") != "base64") {
- QByteArray body;
- if (tmp.header.getValue("Content-Transfer-Encoding") == "quoted-printable") {
- Mime::quotedPrintableDecode(tmp.body, body);
- } else {
- body = tmp.body;
- }
- pText.append(QString(body));
- } else {
- // TODO
- show_ma_dock = true;
- }
- }
- *message = pText.toUtf8();
- if (show_ma_dock) {
- // TODO
- }
- }
-
/** Decrypt QByteAarray, return QByteArray
* mainly from http://basket.kde.org/ (kgpgme.cpp)
*/
@@ -496,28 +463,6 @@ namespace GpgME {
gpgme_data_release(dataOut);
}
- /*
- * 1) is it mime (content-type:)
- * 2) parse header
- * 2) choose action depending on content-type
- */
- if (Mime::isMime(outBuffer)) {
- Header header = Mime::getHeader(outBuffer);
- // is it multipart, is multipart-parsing enabled
- if (header.getValue("Content-Type") == "multipart/mixed"
- && settings.value("mime/parseMime").toBool()) {
- parseMime(outBuffer);
- } else if (header.getValue("Content-Type") == "text/plain"
- && settings.value("mime/parseQP").toBool()) {
- if (header.getValue("Content-Transfer-Encoding") == "quoted-printable") {
- auto *decoded = new QByteArray();
- Mime::quotedPrintableDecode(*outBuffer, *decoded);
- //TODO: remove header
- outBuffer = decoded;
- }
- }
- }
-
if (result != nullptr) {
*result = m_result;
}
diff --git a/src/smtp/CMakeLists.txt b/src/smtp/CMakeLists.txt
new file mode 100644
index 00000000..8e341f98
--- /dev/null
+++ b/src/smtp/CMakeLists.txt
@@ -0,0 +1,6 @@
+aux_source_directory(. SMTP_MIME_SOURCE)
+
+add_library(smtp STATIC ${SMTP_MIME_SOURCE})
+
+target_link_libraries(smtp
+ Qt5::Network Qt5::Core)
diff --git a/src/smtp/emailaddress.cpp b/src/smtp/emailaddress.cpp
new file mode 100644
index 00000000..c0ecaa0d
--- /dev/null
+++ b/src/smtp/emailaddress.cpp
@@ -0,0 +1,44 @@
+/*
+ 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 "smtp/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] --- */
diff --git a/src/smtp/mimeattachment.cpp b/src/smtp/mimeattachment.cpp
new file mode 100644
index 00000000..033eecfb
--- /dev/null
+++ b/src/smtp/mimeattachment.cpp
@@ -0,0 +1,43 @@
+/*
+ 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 "smtp/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() = default;
+
+/* [1] --- */
+
+/* [2] Protected methods */
+
+void MimeAttachment::prepare() {
+ this->header += "Content-disposition: attachment\r\n";
+
+ /* !!! IMPORTANT !!! */
+ MimeFile::prepare();
+}
+
+/* [2] --- */
diff --git a/src/smtp/mimecontentformatter.cpp b/src/smtp/mimecontentformatter.cpp
new file mode 100644
index 00000000..8f538457
--- /dev/null
+++ b/src/smtp/mimecontentformatter.cpp
@@ -0,0 +1,59 @@
+/*
+ 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 "smtp/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 (auto i : content) {
+ chars++;
+ if (!quotedPrintable) {
+ if (chars > max_length) {
+ out.append("\r\n");
+ chars = 1;
+ }
+ } else {
+ if (i == '\n') { // new line
+ out.append(i);
+ chars = 0;
+ continue;
+ }
+
+ if ((chars > max_length - 1) ||
+ ((i == '=') && (chars > max_length - 3))) {
+ out.append('=');
+ out.append("\r\n");
+ chars = 1;
+ }
+ }
+ out.append(i);
+ }
+
+ return out;
+}
+
+void MimeContentFormatter::setMaxLength(int l) { max_length = l; }
+
+int MimeContentFormatter::getMaxLength() const { return max_length; }
diff --git a/src/smtp/mimefile.cpp b/src/smtp/mimefile.cpp
new file mode 100644
index 00000000..4f095b84
--- /dev/null
+++ b/src/smtp/mimefile.cpp
@@ -0,0 +1,61 @@
+/*
+ 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 "smtp/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 = nullptr;
+ this->cName = fileName;
+ this->content = stream;
+}
+
+MimeFile::~MimeFile() {
+ 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] --- */
diff --git a/src/smtp/mimehtml.cpp b/src/smtp/mimehtml.cpp
new file mode 100644
index 00000000..9f3a53c3
--- /dev/null
+++ b/src/smtp/mimehtml.cpp
@@ -0,0 +1,46 @@
+/*
+ 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 "smtp/mimehtml.h"
+
+/* [1] Constructors and Destructors */
+
+MimeHtml::MimeHtml(const QString &html) : MimeText(html) {
+ this->cType = "text/html";
+}
+
+MimeHtml::~MimeHtml() = default;
+
+/* [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] --- */
diff --git a/src/smtp/mimeinlinefile.cpp b/src/smtp/mimeinlinefile.cpp
new file mode 100644
index 00000000..a49167e8
--- /dev/null
+++ b/src/smtp/mimeinlinefile.cpp
@@ -0,0 +1,42 @@
+/*
+ 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 "smtp/mimeinlinefile.h"
+
+/* [1] Constructors and Destructors */
+
+MimeInlineFile::MimeInlineFile(QFile *f) : MimeFile(f) {}
+
+MimeInlineFile::~MimeInlineFile() = default;
+
+/* [1] --- */
+
+/* [2] Getters and Setters */
+
+/* [2] --- */
+
+/* [3] Protected methods */
+
+void MimeInlineFile::prepare() {
+ this->header += "Content-Disposition: inline\r\n";
+
+ /* !!! IMPORTANT !!! */
+ MimeFile::prepare();
+}
+
+/* [3] --- */
diff --git a/src/smtp/mimemessage.cpp b/src/smtp/mimemessage.cpp
new file mode 100644
index 00000000..cf653e0a
--- /dev/null
+++ b/src/smtp/mimemessage.cpp
@@ -0,0 +1,308 @@
+/*
+ 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 "smtp/mimemessage.h"
+#include "smtp/quotedprintable.h"
+
+#include <QDateTime>
+#include <QLocale>
+#include <typeinfo>
+
+/* [1] Constructors and Destructors */
+MimeMessage::MimeMessage(bool createAutoMimeContent)
+ : replyTo(nullptr), 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::setReplyTo(EmailAddress *rto) { replyTo = rto; }
+
+void MimeMessage::setSender(EmailAddress *e) {
+ this->sender = e;
+ e->setParent(this);
+}
+
+void MimeMessage::addRecipient(EmailAddress *rcpt, RecipientType type) {
+ switch (type) {
+ case To:
+ recipientsTo << rcpt;
+ break;
+ case Cc:
+ recipientsCc << rcpt;
+ break;
+ case Bcc:
+ recipientsBcc << rcpt;
+ break;
+ }
+
+ rcpt->setParent(this);
+}
+
+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::setInReplyTo(const QString &inReplyTo) {
+ mInReplyTo = inReplyTo;
+}
+
+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 EmailAddress *MimeMessage::getReplyTo() const { return replyTo; }
+
+const QString &MimeMessage::getSubject() const { return subject; }
+
+const QList<MimePart *> &MimeMessage::getParts() const {
+ if (typeid(*content) == typeid(MimeMultiPart)) {
+ return ((MimeMultiPart *) content)->getParts();
+ } else {
+ auto *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().toUtf8()).toBase64() + "?=";
+ break;
+ case MimePart::QuotedPrintable:
+ mime += " =?utf-8?Q?" +
+ QuotedPrintable::encode(
+ QByteArray().append(sender->getName().toUtf8()))
+ .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().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() + ">";
+ }
+ mime += "\r\n";
+ /* ---------------------------------- */
+
+ /* ------- Recipients / Cc ---------- */
+ if (!recipientsCc.empty()) {
+ 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.empty()) {
+ mime += "\r\n";
+ }
+ /* ---------------------------------- */
+
+ /* ------------ Subject ------------- */
+ mime += "Subject: ";
+
+ 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
+ QString shortDayName =
+ QLocale::c().dayName(now.date().dayOfWeek(), QLocale::ShortFormat);
+ QString shortMonthName =
+ QLocale::c().monthName(now.date().month(), QLocale::ShortFormat);
+ int utcOffset = now.secsTo(QDateTime(now.date(), now.time(), Qt::UTC)) / 60;
+ char timezoneSign = utcOffset >= 0 ? '+' : '-';
+ utcOffset = utcOffset >= 0 ? utcOffset : -utcOffset;
+ QString timezone = QString("%1%2%3")
+ .arg(timezoneSign)
+ .arg(utcOffset / 60, 2, 10, QChar('0'))
+ .arg(utcOffset % 60, 2, 10, QChar('0'));
+ mime += QString("Date: %1\r\n")
+ .arg(now.toString("%1, dd %2 yyyy hh:mm:ss %3")
+ .arg(shortDayName)
+ .arg(shortMonthName)
+ .arg(timezone));
+#else // Qt5 supported
+ mime += QString("Date: %1\r\n").arg(now.toString(Qt::RFC2822Date));
+#endif // support RFC2822Date
+
+ mime += content->toString();
+ return mime;
+}
+
+/* [3] --- */
diff --git a/src/smtp/mimemultipart.cpp b/src/smtp/mimemultipart.cpp
new file mode 100644
index 00000000..14a813c2
--- /dev/null
+++ b/src/smtp/mimemultipart.cpp
@@ -0,0 +1,70 @@
+/*
+ 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 "smtp/mimemultipart.h"
+#include <QCryptographicHash>
+#include <QRandomGenerator>
+#include <QTime>
+
+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;
+
+ QRandomGenerator generator;
+
+ QCryptographicHash md5(QCryptographicHash::Md5);
+ md5.addData(QByteArray().append((char) generator.generate()));
+ cBoundary = md5.result().toHex();
+}
+
+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 += QString("--" + cBoundary + "\r\n").toUtf8();
+ (*it)->prepare();
+ content += (*it)->toString().toUtf8();
+ };
+
+ content += QString("--" + cBoundary + "--\r\n").toUtf8();
+
+ MimePart::prepare();
+}
+
+void MimeMultiPart::setMimeType(const MultiPartType type) {
+ this->type = type;
+ this->cType = MULTI_PART_NAMES[type];
+}
+
+MimeMultiPart::MultiPartType MimeMultiPart::getMimeType() const { return type; }
diff --git a/src/smtp/mimepart.cpp b/src/smtp/mimepart.cpp
new file mode 100644
index 00000000..5d33884d
--- /dev/null
+++ b/src/smtp/mimepart.cpp
@@ -0,0 +1,159 @@
+/*
+ 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 "smtp/mimepart.h"
+#include "smtp/quotedprintable.h"
+
+/* [1] Constructors and Destructors */
+
+MimePart::MimePart() {
+ cEncoding = _7Bit;
+ prepared = false;
+ cBoundary = "";
+}
+
+/* [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] --- */
diff --git a/src/smtp/mimetext.cpp b/src/smtp/mimetext.cpp
new file mode 100644
index 00000000..3726647e
--- /dev/null
+++ b/src/smtp/mimetext.cpp
@@ -0,0 +1,52 @@
+/*
+ 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 "smtp/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() = default;
+
+/* [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.toUtf8());
+
+ /* !!! IMPORTANT !!! */
+ MimePart::prepare();
+}
+
+/* [3] --- */
diff --git a/src/smtp/quotedprintable.cpp b/src/smtp/quotedprintable.cpp
new file mode 100644
index 00000000..93e51122
--- /dev/null
+++ b/src/smtp/quotedprintable.cpp
@@ -0,0 +1,62 @@
+/*
+ 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 "smtp/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 (char i : input) {
+ byte = 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;
+}
diff --git a/src/smtp/smtpclient.cpp b/src/smtp/smtpclient.cpp
new file mode 100644
index 00000000..63202998
--- /dev/null
+++ b/src/smtp/smtpclient.cpp
@@ -0,0 +1,407 @@
+/*
+ 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 "smtp/smtpclient.h"
+
+#include <QByteArray>
+#include <QFileInfo>
+
+/* [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.toUtf8())
+ .append((char) 0)
+ .append(password.toUtf8())
+ .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.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;
+}
+
+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() {
+ try {
+ sendMessage("QUIT");
+ } catch (SmtpClient::SendMessageTimeoutException) {
+ // Manually close the connection to the smtp server if message "QUIT" wasn't
+ // received by the smtp server
+ if (socket->state() == QAbstractSocket::ConnectedState ||
+ socket->state() == QAbstractSocket::ConnectingState ||
+ socket->state() == QAbstractSocket::HostLookupState)
+ socket->disconnectFromHost();
+ }
+}
+
+/* [3] --- */
+
+/* [4] Protected methods */
+
+void SmtpClient::waitForResponse() {
+ 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.leftRef(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) {
+ 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] --- */
diff --git a/src/ui/AttachmentTableModel.cpp b/src/ui/AttachmentTableModel.cpp
deleted file mode 100644
index 79cbdf9b..00000000
--- a/src/ui/AttachmentTableModel.cpp
+++ /dev/null
@@ -1,134 +0,0 @@
-/**
- * This file is part of GPGFrontend.
- *
- * GPGFrontend 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 3 of the License, or
- * (at your option) any later version.
- *
- * Foobar 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Foobar. If not, see <https://www.gnu.org/licenses/>.
- *
- * The initial version of the source code is inherited from gpg4usb-team.
- * Their source code version also complies with GNU General Public License.
- *
- * The source code version of this software was modified and released
- * by Saturneric<[email protected]> starting on May 12, 2021.
- *
- */
-
-#include "ui/AttachmentTableModel.h"
-
-#include <utility>
-
-/** compare with http://doc.qt.nokia.com/4.6/itemviews-addressbook.html
- */
-
-AttachmentTableModel::AttachmentTableModel(QObject *parent) :
- QAbstractTableModel(parent) {
-}
-
-AttachmentTableModel::AttachmentTableModel(QList<MimePart> mimeparts, QObject *parent) :
- QAbstractTableModel(parent) {
- listOfMimeparts = std::move(mimeparts);
-}
-
-
-void AttachmentTableModel::add(const MimePart &mp) {
- listOfMimeparts.append(mp);
- //QModelIndex changedIndex0 = createIndex(listOfMimeparts.size(), 0);
- //QModelIndex changedIndex1 = createIndex(listOfMimeparts.size(), 1);
-
- //emit(dataChanged(changedIndex0, changedIndex1));
- // TODO: check the data-changed signal
- // reset();
-}
-
-MimePart AttachmentTableModel::getSelectedMimePart(QModelIndex index) {
- return listOfMimeparts.at(index.row());
-}
-
-MimePart AttachmentTableModel::getMimePart(int index) {
- return listOfMimeparts.at(index);
-}
-
-/*QList<MimePart> AttachmentTableModel::getSelectedMimeParts(QModelIndexList indexes){
-
- foreach(QModelIndex index, indexes) {
- qDebug() << "ir: "<< index.row();
- }
-
-}*/
-
-int AttachmentTableModel::rowCount(const QModelIndex &parent) const {
- Q_UNUSED(parent);
- return listOfMimeparts.size();
-}
-
-int AttachmentTableModel::columnCount(const QModelIndex &parent) const {
- Q_UNUSED(parent);
- return 2;
-}
-
-QVariant AttachmentTableModel::data(const QModelIndex &index, int role) const {
-
- //qDebug() << "called, index: " << index.column();
-
- if (!index.isValid())
- return QVariant();
-
- if (index.row() >= listOfMimeparts.size() || index.row() < 0)
- return QVariant();
-
- if (role == Qt::DisplayRole) {
- MimePart mp = listOfMimeparts.at(index.row());
-
- if (index.column() == 0)
- return mp.header.getParam("Content-Type", "name");
- if (index.column() == 1)
- return mp.header.getValue("Content-Type");
-
- }
-
- // set icon
- // TODO more generic matching, e.g. for audio
- if (role == Qt::DecorationRole && index.column() == 0) {
- MimePart mp = listOfMimeparts.at(index.row());
- QString icon;
- if (mp.header.getValue("Content-Type").startsWith("image")) {
- icon = ":mimetypes/image-x-generic.png";
- } else {
- icon = mp.header.getValue("Content-Type").replace("/", "-");
- icon = ":mimetypes/" + icon + ".png";
- }
- if (!QFile::exists(icon)) icon = ":mimetypes/unknown.png";
- return QIcon(icon);
- }
-
- return QVariant();
-}
-
-QVariant AttachmentTableModel::headerData(int section, Qt::Orientation orientation, int role) const {
- //qDebug() << "called, section: " << section;
- if (role != Qt::DisplayRole)
- return QVariant();
-
- if (orientation == Qt::Horizontal) {
- switch (section) {
- case 0:
- return tr("Filename");
-
- case 1:
- return tr("Contenttype");
-
- default:
- return QVariant();
- }
- }
- return QVariant();
-}
diff --git a/src/ui/main_window/MainWindowSlotUI.cpp b/src/ui/main_window/MainWindowSlotUI.cpp
index d95a9bfe..7065e41c 100644
--- a/src/ui/main_window/MainWindowSlotUI.cpp
+++ b/src/ui/main_window/MainWindowSlotUI.cpp
@@ -145,13 +145,6 @@ void MainWindow::slotOpenSettingsDialog() {
importButton->setToolButtonStyle(buttonStyle);
fileEncButton->setToolButtonStyle(buttonStyle);
- // Mime-settings
- if (settings.value("mime/parseMime").toBool()) {
- createAttachmentDock();
- } else if (attachmentDockCreated) {
- closeAttachmentDock();
- }
-
// restart mainwindow if necessary
if (getRestartNeeded()) {
if (edit->maybeSaveAnyTab()) {
diff --git a/src/ui/main_window/MainWindowUI.cpp b/src/ui/main_window/MainWindowUI.cpp
index 0f7f1040..21f6e3b7 100644
--- a/src/ui/main_window/MainWindowUI.cpp
+++ b/src/ui/main_window/MainWindowUI.cpp
@@ -447,26 +447,4 @@ void MainWindow::createDockWindows() {
infoBoardDock->setWidget(infoBoard);
infoBoardDock->widget()->layout()->setContentsMargins(0, 0, 0, 0);
viewMenu->addAction(infoBoardDock->toggleViewAction());
-
- /* Attachments-Dockwindow
- */
- if (settings.value("mime/parseMime").toBool()) {
- createAttachmentDock();
- }
-}
-
-void MainWindow::createAttachmentDock() {
- if (attachmentDockCreated) {
- return;
- }
- mAttachments = new Attachments();
- attachmentDock = new QDockWidget(tr("Attached files:"), this);
- attachmentDock->setObjectName("AttachmentDock");
- attachmentDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea | Qt::BottomDockWidgetArea);
- addDockWidget(Qt::LeftDockWidgetArea, attachmentDock);
- attachmentDock->setWidget(mAttachments);
- // hide till attachment is decrypted
- viewMenu->addAction(attachmentDock->toggleViewAction());
- attachmentDock->hide();
- attachmentDockCreated = true;
}
diff --git a/src/ui/widgets/Attachments.cpp b/src/ui/widgets/Attachments.cpp
deleted file mode 100644
index 8f741f66..00000000
--- a/src/ui/widgets/Attachments.cpp
+++ /dev/null
@@ -1,180 +0,0 @@
-/**
- * This file is part of GPGFrontend.
- *
- * GPGFrontend 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 3 of the License, or
- * (at your option) any later version.
- *
- * Foobar 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Foobar. If not, see <https://www.gnu.org/licenses/>.
- *
- * The initial version of the source code is inherited from gpg4usb-team.
- * Their source code version also complies with GNU General Public License.
- *
- * The source code version of this software was modified and released
- * by Saturneric<[email protected]> starting on May 12, 2021.
- *
- */
-
-/* TODO:
- * - check content encoding (base64 / quoted-printable) and apply appropriate opperation (maybe already in mime.cpp)
- * - check memory usage, use less copy operations / more references
- * - possibility to clear attachment-view , e.g. with decryption or encrypting a new message
- * - save all: like in thunderbird, one folder, all files go there
- */
-
-/*
- * - save, delete (clear) all
- * - each line save & clear button
- * - attached files to view-menu
- * - also an open button, whichs should save file to tmp-folder, and open with correct app (via QDesktopServices)
- */
-
-
-#include "ui/widgets/Attachments.h"
-
-Attachments::Attachments(QWidget *parent)
- : QWidget(parent) {
- table = new AttachmentTableModel(this);
-
- tableView = new QTableView;
- tableView->setModel(table);
- tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
- // only one entry should be selected at time
- tableView->setSelectionMode(QAbstractItemView::SingleSelection);
- tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
- tableView->setFocusPolicy(Qt::NoFocus);
- tableView->setAlternatingRowColors(true);
- tableView->verticalHeader()->hide();
- tableView->setShowGrid(false);
- tableView->setColumnWidth(0, 300);
- tableView->horizontalHeader()->setStretchLastSection(true);
-
- auto *layout = new QVBoxLayout;
- layout->addWidget(tableView);
- layout->setContentsMargins(0, 0, 0, 0);
- setLayout(layout);
- createActions();
-
-}
-
-void Attachments::contextMenuEvent(QContextMenuEvent *event) {
- QMenu menu(this);
- menu.addAction(saveFileAct);
- // enable open with only if allowed by user
- if (settings.value("mime/openAttachment").toBool())
- menu.addAction(openFileAct);
-
- menu.exec(event->globalPos());
-}
-
-void Attachments::createActions() {
- saveFileAct = new QAction(tr("Save File"), this);
- saveFileAct->setToolTip(tr("Save this file"));
- saveFileAct->setIcon(QIcon(":filesave.png"));
- connect(saveFileAct, SIGNAL(triggered()), this, SLOT(slotSaveFile()));
-
- openFileAct = new QAction(tr("Open File"), this);
- openFileAct->setToolTip(tr("Open this file"));
- openFileAct->setIcon(QIcon(":fileopen.png"));
- connect(openFileAct, SIGNAL(triggered()), this, SLOT(slotOpenFile()));
-
-}
-
-void Attachments::slotSaveFile() {
-
- QModelIndexList indexes = tableView->selectionModel()->selection().indexes();
-
- if (indexes.empty()) {
- return;
- }
-
- // only singe-selection possible now: TODO: foreach
- MimePart mp = table->getMimePart(indexes.at(0).row());
- QString filename = mp.header.getParam("Content-Type", "name");
- // TODO: find out why filename is quoted
- filename.chop(1);
- filename.remove(0, 1);
- // TODO: check if really base64
- saveByteArrayToFile(QByteArray::fromBase64(mp.body), filename);
-
-}
-
-void Attachments::saveByteArrayToFile(QByteArray outBuffer, QString filename) {
-
- //QString path="";
- QString path = std::move(filename);
- QString outfileName = QFileDialog::getSaveFileName(this, tr("Save File"), path);
-
- if (outfileName.isEmpty()) return;
-
- QFile outfile(outfileName);
- if (!outfile.open(QFile::WriteOnly)) {
- QMessageBox::warning(this, tr("File"),
- tr("Cannot write file %1:\n%2.")
- .arg(outfileName)
- .arg(outfile.errorString()));
- return;
- }
-
- QDataStream out(&outfile);
- out.writeRawData(outBuffer.data(), outBuffer.length());
- outfile.close();
-}
-
-/**
- * WIP: TODO:
- * - create attachments dir if not existing
- * - ask for cleanup of dir on exit
- * - remove code-duplication with saveByteArrayToFile
- */
-void Attachments::slotOpenFile() {
-
- // TODO: make attachmentdir constant or configurable
- QString attachmentDir = qApp->applicationDirPath() + "/attachments/";
- //QDir p = QDir(qApp->applicationDirPath() + "/attachments/");
- if (!QDir(attachmentDir).exists()) {
- QDir().mkpath(attachmentDir);
- }
-
- QModelIndexList indexes = tableView->selectionModel()->selection().indexes();
- MimePart mp = table->getMimePart(indexes.at(0).row());
-
-// qDebug() << "mime: " << mp.header.getValue("Content-Type");
-
- QString filename = mp.header.getParam("Content-Type", "name");
- // TODO: find out why filename is quoted
-// qDebug() << "file: " << filename;
- filename.chop(1);
- filename.remove(0, 1);
- filename.prepend(attachmentDir);
-
- // qDebug() << "file: " << filename;
- QByteArray outBuffer = QByteArray::fromBase64(mp.body);
-
-
- QFile outfile(filename);
- if (!outfile.open(QFile::WriteOnly)) {
- QMessageBox::warning(this, tr("File"),
- tr("Cannot write file %1:\n%2.")
- .arg(filename)
- .arg(outfile.errorString()));
- return;
- }
-
- QDataStream out(&outfile);
- out.writeRawData(outBuffer.data(), outBuffer.length());
- outfile.close();
- QDesktopServices::openUrl(QUrl("file://" + filename, QUrl::TolerantMode));
-}
-
-void Attachments::addMimePart(MimePart *mp) {
- table->add(*mp);
-}
-