diff options
-rw-r--r-- | framework/src/domain/mime/mailtemplates.cpp | 34 | ||||
-rw-r--r-- | framework/src/domain/mime/mailtemplates.h | 3 | ||||
-rw-r--r-- | framework/src/domain/mime/tests/CMakeLists.txt | 13 | ||||
-rw-r--r-- | framework/src/domain/mime/tests/mailtemplatetest.cpp | 68 |
4 files changed, 107 insertions, 11 deletions
diff --git a/framework/src/domain/mime/mailtemplates.cpp b/framework/src/domain/mime/mailtemplates.cpp index 608f7546..dc713ee4 100644 --- a/framework/src/domain/mime/mailtemplates.cpp +++ b/framework/src/domain/mime/mailtemplates.cpp | |||
@@ -39,6 +39,8 @@ | |||
39 | 39 | ||
40 | #include <mimetreeparser/objecttreeparser.h> | 40 | #include <mimetreeparser/objecttreeparser.h> |
41 | 41 | ||
42 | #include "mailcrypto.h" | ||
43 | |||
42 | namespace KMime { | 44 | namespace KMime { |
43 | namespace Types { | 45 | namespace Types { |
44 | static bool operator==(const KMime::Types::AddrSpec &left, const KMime::Types::AddrSpec &right) | 46 | static bool operator==(const KMime::Types::AddrSpec &left, const KMime::Types::AddrSpec &right) |
@@ -910,7 +912,6 @@ static KMime::Content *createBodyPart(const QByteArray &body) { | |||
910 | auto mainMessage = new KMime::Content; | 912 | auto mainMessage = new KMime::Content; |
911 | mainMessage->setBody(body); | 913 | mainMessage->setBody(body); |
912 | mainMessage->contentType(true)->setMimeType("text/plain"); | 914 | mainMessage->contentType(true)->setMimeType("text/plain"); |
913 | // return MailCrypto::sign(mainMessage, {}); | ||
914 | return mainMessage; | 915 | return mainMessage; |
915 | } | 916 | } |
916 | 917 | ||
@@ -930,12 +931,13 @@ static void applyAddresses(const QStringList &list, std::function<void(const QBy | |||
930 | // applyAddresses(KEmailAddress::splitAddressList(list), callback); | 931 | // applyAddresses(KEmailAddress::splitAddressList(list), callback); |
931 | // } | 932 | // } |
932 | 933 | ||
933 | KMime::Message::Ptr MailTemplates::createMessage(KMime::Message::Ptr existingMessage, const QStringList &to, const QStringList &cc, const QStringList &bcc, const KMime::Types::Mailbox &from, const QString &subject, const QString &body, const QList<Attachment> &attachments) | 934 | KMime::Message::Ptr MailTemplates::createMessage(KMime::Message::Ptr existingMessage, const QStringList &to, const QStringList &cc, const QStringList &bcc, const KMime::Types::Mailbox &from, const QString &subject, const QString &body, const QList<Attachment> &attachments, const std::vector<GpgME::Key> &signingKeys) |
934 | { | 935 | { |
935 | auto mail = existingMessage; | 936 | auto mail = existingMessage; |
936 | if (!mail) { | 937 | if (!mail) { |
937 | mail = KMime::Message::Ptr::create(); | 938 | mail = KMime::Message::Ptr::create(); |
938 | } | 939 | } |
940 | |||
939 | mail->to(true)->clear(); | 941 | mail->to(true)->clear(); |
940 | applyAddresses(to, [&](const QByteArray &addrSpec, const QByteArray &displayName) { | 942 | applyAddresses(to, [&](const QByteArray &addrSpec, const QByteArray &displayName) { |
941 | mail->to(true)->addAddress(addrSpec, displayName); | 943 | mail->to(true)->addAddress(addrSpec, displayName); |
@@ -966,6 +968,7 @@ KMime::Message::Ptr MailTemplates::createMessage(KMime::Message::Ptr existingMes | |||
966 | mail->date(true)->setDateTime(QDateTime::currentDateTimeUtc()); | 968 | mail->date(true)->setDateTime(QDateTime::currentDateTimeUtc()); |
967 | } | 969 | } |
968 | 970 | ||
971 | KMime::Content *bodyPart; | ||
969 | if (!attachments.isEmpty()) { | 972 | if (!attachments.isEmpty()) { |
970 | mail->contentType(true)->setMimeType("multipart/mixed"); | 973 | mail->contentType(true)->setMimeType("multipart/mixed"); |
971 | mail->contentType()->setBoundary(KMime::multiPartBoundary()); | 974 | mail->contentType()->setBoundary(KMime::multiPartBoundary()); |
@@ -974,13 +977,32 @@ KMime::Message::Ptr MailTemplates::createMessage(KMime::Message::Ptr existingMes | |||
974 | for (const auto &attachment : attachments) { | 977 | for (const auto &attachment : attachments) { |
975 | mail->addContent(createAttachmentPart(attachment.data, attachment.filename, attachment.isInline, attachment.mimeType, attachment.name)); | 978 | mail->addContent(createAttachmentPart(attachment.data, attachment.filename, attachment.isInline, attachment.mimeType, attachment.name)); |
976 | } | 979 | } |
977 | mail->addContent(createBodyPart(body.toUtf8())); | 980 | bodyPart = createBodyPart(body.toUtf8()); |
978 | } else { | 981 | } else { |
979 | //FIXME same implementation as above for attachments | 982 | //FIXME same implementation as above for attachments |
980 | mail->setBody(body.toUtf8()); | 983 | bodyPart = createBodyPart(body.toUtf8()); |
981 | mail->contentType(true)->setMimeType("text/plain"); | ||
982 | } | 984 | } |
985 | mail->assemble(); | ||
983 | 986 | ||
987 | KMime::Content *signedResult = nullptr; | ||
988 | if (!signingKeys.empty()) { | ||
989 | signedResult = MailCrypto::sign(bodyPart, signingKeys); | ||
990 | if (!signedResult) { | ||
991 | qWarning() << "Signing failed"; | ||
992 | return {}; | ||
993 | } | ||
994 | } else { | ||
995 | if (!mail->contentType(false)) { | ||
996 | mail->contentType(true)->setMimeType("text/plain"); | ||
997 | } | ||
998 | } | ||
984 | mail->assemble(); | 999 | mail->assemble(); |
985 | return mail; | 1000 | |
1001 | const QByteArray allData = mail->head() + (signedResult ? signedResult->encodedContent() : bodyPart->encodedContent()); | ||
1002 | delete bodyPart; | ||
1003 | KMime::Message::Ptr resultMessage(new KMime::Message); | ||
1004 | resultMessage->setContent(allData); | ||
1005 | resultMessage->parse(); // Not strictly necessary. | ||
1006 | |||
1007 | return resultMessage; | ||
986 | } | 1008 | } |
diff --git a/framework/src/domain/mime/mailtemplates.h b/framework/src/domain/mime/mailtemplates.h index 773ded05..a8a4b606 100644 --- a/framework/src/domain/mime/mailtemplates.h +++ b/framework/src/domain/mime/mailtemplates.h | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <QByteArray> | 22 | #include <QByteArray> |
23 | #include <KMime/Message> | 23 | #include <KMime/Message> |
24 | #include <functional> | 24 | #include <functional> |
25 | #include <gpgme++/key.h> | ||
25 | 26 | ||
26 | struct Attachment { | 27 | struct Attachment { |
27 | QString name; | 28 | QString name; |
@@ -35,5 +36,5 @@ namespace MailTemplates | |||
35 | { | 36 | { |
36 | void reply(const KMime::Message::Ptr &origMsg, const std::function<void(const KMime::Message::Ptr &result)> &callback); | 37 | void reply(const KMime::Message::Ptr &origMsg, const std::function<void(const KMime::Message::Ptr &result)> &callback); |
37 | QString plaintextContent(const KMime::Message::Ptr &origMsg); | 38 | QString plaintextContent(const KMime::Message::Ptr &origMsg); |
38 | KMime::Message::Ptr createMessage(KMime::Message::Ptr existingMessage, const QStringList &to, const QStringList &cc, const QStringList &bcc, const KMime::Types::Mailbox &from, const QString &subject, const QString &body, const QList<Attachment> &attachments); | 39 | KMime::Message::Ptr createMessage(KMime::Message::Ptr existingMessage, const QStringList &to, const QStringList &cc, const QStringList &bcc, const KMime::Types::Mailbox &from, const QString &subject, const QString &body, const QList<Attachment> &attachments, const std::vector<GpgME::Key> &signingKeys = {}); |
39 | }; | 40 | }; |
diff --git a/framework/src/domain/mime/tests/CMakeLists.txt b/framework/src/domain/mime/tests/CMakeLists.txt index 4fad00a1..f94447ff 100644 --- a/framework/src/domain/mime/tests/CMakeLists.txt +++ b/framework/src/domain/mime/tests/CMakeLists.txt | |||
@@ -8,8 +8,13 @@ include_directories( | |||
8 | include(ECMAddTests) | 8 | include(ECMAddTests) |
9 | find_package(Qt5 REQUIRED NO_MODULE COMPONENTS Core Test WebEngine) | 9 | find_package(Qt5 REQUIRED NO_MODULE COMPONENTS Core Test WebEngine) |
10 | 10 | ||
11 | ecm_add_test(mailtemplatetest.cpp | 11 | include( ${CMAKE_SOURCE_DIR}/cmake/modules/add_gpg_crypto_test.cmake ) |
12 | TEST_NAME "mailtemplatetest" | 12 | |
13 | NAME_PREFIX "" | 13 | add_executable(mailtemplatetest mailtemplatetest.cpp) |
14 | LINK_LIBRARIES Qt5::Core Qt5::Test Qt5::WebEngine frameworkplugin | 14 | add_gpg_crypto_test(mailtemplatetest mailtemplatetest) |
15 | target_link_libraries(mailtemplatetest | ||
16 | Qt5::Core | ||
17 | Qt5::Test | ||
18 | Qt5::WebEngine | ||
19 | frameworkplugin | ||
15 | ) | 20 | ) |
diff --git a/framework/src/domain/mime/tests/mailtemplatetest.cpp b/framework/src/domain/mime/tests/mailtemplatetest.cpp index fbe5568d..62b17a6c 100644 --- a/framework/src/domain/mime/tests/mailtemplatetest.cpp +++ b/framework/src/domain/mime/tests/mailtemplatetest.cpp | |||
@@ -6,7 +6,52 @@ | |||
6 | #include <QDir> | 6 | #include <QDir> |
7 | #include <QtWebEngine> | 7 | #include <QtWebEngine> |
8 | 8 | ||
9 | #include <QGpgME/KeyListJob> | ||
10 | #include <QGpgME/Protocol> | ||
11 | #include <gpgme++/key.h> | ||
12 | #include <gpgme++/keylistresult.h> | ||
13 | |||
9 | #include "mailtemplates.h" | 14 | #include "mailtemplates.h" |
15 | #include "mailcrypto.h" | ||
16 | |||
17 | static std::vector< GpgME::Key, std::allocator< GpgME::Key > > getKeys(bool smime = false) | ||
18 | { | ||
19 | QGpgME::KeyListJob *job = nullptr; | ||
20 | |||
21 | if (smime) { | ||
22 | const QGpgME::Protocol *const backend = QGpgME::smime(); | ||
23 | Q_ASSERT(backend); | ||
24 | job = backend->keyListJob(false); | ||
25 | } else { | ||
26 | const QGpgME::Protocol *const backend = QGpgME::openpgp(); | ||
27 | Q_ASSERT(backend); | ||
28 | job = backend->keyListJob(false); | ||
29 | } | ||
30 | Q_ASSERT(job); | ||
31 | |||
32 | std::vector< GpgME::Key > keys; | ||
33 | GpgME::KeyListResult res = job->exec(QStringList(), true, keys); | ||
34 | |||
35 | if (!smime) { | ||
36 | Q_ASSERT(keys.size() == 3); | ||
37 | } | ||
38 | |||
39 | Q_ASSERT(!res.error()); | ||
40 | |||
41 | /* | ||
42 | qDebug() << "got private keys:" << keys.size(); | ||
43 | |||
44 | for (std::vector< GpgME::Key >::iterator i = keys.begin(); i != keys.end(); ++i) { | ||
45 | qDebug() << "key isnull:" << i->isNull() << "isexpired:" << i->isExpired(); | ||
46 | qDebug() << "key numuserIds:" << i->numUserIDs(); | ||
47 | for (uint k = 0; k < i->numUserIDs(); ++k) { | ||
48 | qDebug() << "userIDs:" << i->userID(k).email(); | ||
49 | } | ||
50 | } | ||
51 | */ | ||
52 | |||
53 | return keys; | ||
54 | } | ||
10 | 55 | ||
11 | static QByteArray readMailFromFile(const QString &mailFile) | 56 | static QByteArray readMailFromFile(const QString &mailFile) |
12 | { | 57 | { |
@@ -147,6 +192,29 @@ private slots: | |||
147 | //1 Plain + 2 Attachments | 192 | //1 Plain + 2 Attachments |
148 | QCOMPARE(contents.size(), 3); | 193 | QCOMPARE(contents.size(), 3); |
149 | } | 194 | } |
195 | |||
196 | void testCreatePlainMailSigned() | ||
197 | { | ||
198 | QStringList to = {{"to@example.org"}}; | ||
199 | QStringList cc = {{"cc@example.org"}};; | ||
200 | QStringList bcc = {{"bcc@example.org"}};; | ||
201 | KMime::Types::Mailbox from; | ||
202 | from.fromUnicodeString("from@example.org"); | ||
203 | QString subject = "subject"; | ||
204 | QString body = "body"; | ||
205 | QList<Attachment> attachments; | ||
206 | |||
207 | std::vector<GpgME::Key> keys = getKeys(); | ||
208 | |||
209 | auto result = MailTemplates::createMessage({}, to, cc, bcc, from, subject, body, attachments, keys); | ||
210 | |||
211 | QVERIFY(result); | ||
212 | qWarning() << "---------------------------------"; | ||
213 | qWarning().noquote() << result->encodedContent(); | ||
214 | qWarning() << "---------------------------------"; | ||
215 | QCOMPARE(result->subject()->asUnicodeString(), subject); | ||
216 | QVERIFY(result->contentType()->isMimeType("multipart/signed")); | ||
217 | } | ||
150 | }; | 218 | }; |
151 | 219 | ||
152 | QTEST_MAIN(MailTemplateTest) | 220 | QTEST_MAIN(MailTemplateTest) |