summaryrefslogtreecommitdiffstats
path: root/framework/src
diff options
context:
space:
mode:
Diffstat (limited to 'framework/src')
-rw-r--r--framework/src/domain/composercontroller.cpp21
-rw-r--r--framework/src/domain/mime/mailtemplates.cpp82
-rw-r--r--framework/src/domain/mime/mimetreeparser/tests/CMakeLists.txt2
-rw-r--r--framework/src/domain/mime/mimetreeparser/tests/mimetreeparsertest.cpp (renamed from framework/src/domain/mime/mimetreeparser/tests/interfacetest.cpp)2
-rw-r--r--framework/src/domain/mime/tests/mailtemplatetest.cpp49
5 files changed, 137 insertions, 19 deletions
diff --git a/framework/src/domain/composercontroller.cpp b/framework/src/domain/composercontroller.cpp
index 09d4c154..2286a71b 100644
--- a/framework/src/domain/composercontroller.cpp
+++ b/framework/src/domain/composercontroller.cpp
@@ -99,19 +99,19 @@ class AddresseeController : public Kube::ListPropertyController
99public: 99public:
100 100
101 bool mFoundAllKeys = true; 101 bool mFoundAllKeys = true;
102
102 QSet<QByteArray> mMissingKeys; 103 QSet<QByteArray> mMissingKeys;
103 AddresseeController() 104 AddresseeController() : Kube::ListPropertyController{{"name", "keyFound", "key"}}
104 : Kube::ListPropertyController{{"name", "keyFound", "key"}}
105 { 105 {
106 QObject::connect(this, &Kube::ListPropertyController::added, this, [this] (const QByteArray &id, const QVariantMap &map) { 106 QObject::connect(
107 findKey(id, map.value("name").toString()); 107 this, &Kube::ListPropertyController::added, this, [this](const QByteArray &id, const QVariantMap &map) {
108 }); 108 findKey(id, map.value("name").toString());
109 });
110
109 QObject::connect(this, &Kube::ListPropertyController::removed, this, [this] (const QByteArray &id) { 111 QObject::connect(this, &Kube::ListPropertyController::removed, this, [this] (const QByteArray &id) {
110 mMissingKeys.remove(id); 112 mMissingKeys.remove(id);
111 setFoundAllKeys(mMissingKeys.isEmpty()); 113 setFoundAllKeys(mMissingKeys.isEmpty());
112 }); 114 });
113
114
115 } 115 }
116 116
117 bool foundAllKeys() 117 bool foundAllKeys()
@@ -133,12 +133,13 @@ public:
133 mb.fromUnicodeString(addressee); 133 mb.fromUnicodeString(addressee);
134 134
135 SinkLog() << "Searching key for: " << mb.address(); 135 SinkLog() << "Searching key for: " << mb.address();
136 asyncRun<std::vector<GpgME::Key>>(this, [mb] { 136 asyncRun<std::vector<GpgME::Key>>(this,
137 [mb] {
137 return MailCrypto::findKeys(QStringList{} << mb.address(), false, false, MailCrypto::OPENPGP); 138 return MailCrypto::findKeys(QStringList{} << mb.address(), false, false, MailCrypto::OPENPGP);
138 }, 139 },
139 [this, addressee, id](const std::vector<GpgME::Key> &keys) { 140 [this, addressee, id](const std::vector<GpgME::Key> &keys) {
140 if (!keys.empty()) { 141 if (!keys.empty()) {
141 if (keys.size() > 1 ) { 142 if (keys.size() > 1) {
142 SinkWarning() << "Found more than one key, encrypting to all of them."; 143 SinkWarning() << "Found more than one key, encrypting to all of them.";
143 } 144 }
144 SinkLog() << "Found key: " << keys.front().primaryFingerprint(); 145 SinkLog() << "Found key: " << keys.front().primaryFingerprint();
@@ -154,7 +155,7 @@ public:
154 155
155 void set(const QStringList &list) 156 void set(const QStringList &list)
156 { 157 {
157 for (const auto &email: list) { 158 for (const auto &email : list) {
158 add({{"name", email}}); 159 add({{"name", email}});
159 } 160 }
160 } 161 }
diff --git a/framework/src/domain/mime/mailtemplates.cpp b/framework/src/domain/mime/mailtemplates.cpp
index 8e644b34..30f9a48d 100644
--- a/framework/src/domain/mime/mailtemplates.cpp
+++ b/framework/src/domain/mime/mailtemplates.cpp
@@ -53,6 +53,18 @@ static bool operator==(const KMime::Types::Mailbox &left, const KMime::Types::Ma
53 return (left.addrSpec().asString() == right.addrSpec().asString()); 53 return (left.addrSpec().asString() == right.addrSpec().asString());
54} 54}
55 } 55 }
56
57 Message* contentToMessage(Content* content) {
58 content->assemble();
59 const auto encoded = content->encodedContent();
60
61 auto message = new Message();
62 message->setContent(encoded);
63 message->parse();
64
65 return message;
66 }
67
56} 68}
57 69
58static KMime::Types::Mailbox::List stripMyAddressesFromAddressList(const KMime::Types::Mailbox::List &list, const KMime::Types::AddrSpecList me) 70static KMime::Types::Mailbox::List stripMyAddressesFromAddressList(const KMime::Types::Mailbox::List &list, const KMime::Types::AddrSpecList me)
@@ -215,7 +227,7 @@ KMime::Content *createMultipartAlternativeContent(const QString &plainBody, cons
215 //FIXME This is supposed to select a charset out of the available charsets that contains all necessary characters to render the text 227 //FIXME This is supposed to select a charset out of the available charsets that contains all necessary characters to render the text
216 // QTextCodec *charset = selectCharset(m_charsets, htmlBody); 228 // QTextCodec *charset = selectCharset(m_charsets, htmlBody);
217 // htmlPart->contentType()->setCharset(charset->name()); 229 // htmlPart->contentType()->setCharset(charset->name());
218 textPart->contentType()->setCharset("utf-8"); 230 htmlPart->contentType()->setCharset("utf-8");
219 htmlPart->contentTransferEncoding()->setEncoding(KMime::Headers::CE8Bit); 231 htmlPart->contentTransferEncoding()->setEncoding(KMime::Headers::CE8Bit);
220 htmlPart->fromUnicodeString(htmlBody); 232 htmlPart->fromUnicodeString(htmlBody);
221 multipartAlternative->addContent(htmlPart); 233 multipartAlternative->addContent(htmlPart);
@@ -223,6 +235,19 @@ KMime::Content *createMultipartAlternativeContent(const QString &plainBody, cons
223 return multipartAlternative; 235 return multipartAlternative;
224} 236}
225 237
238KMime::Content *createMultipartMixedContent(QVector<KMime::Content *> contents)
239{
240 KMime::Content *multiPartMixed = new KMime::Content();
241 multiPartMixed->contentType()->setMimeType("multipart/mixed");
242 multiPartMixed->contentType()->setBoundary(KMime::multiPartBoundary());
243
244 for (const auto &content : contents) {
245 multiPartMixed->addContent(content);
246 }
247
248 return multiPartMixed;
249}
250
226void addProcessedBodyToMessage(const KMime::Message::Ptr &msg, const QString &plainBody, const QString &htmlBody, bool forward) 251void addProcessedBodyToMessage(const KMime::Message::Ptr &msg, const QString &plainBody, const QString &htmlBody, bool forward)
227{ 252{
228 //FIXME 253 //FIXME
@@ -864,27 +889,70 @@ void MailTemplates::reply(const KMime::Message::Ptr &origMsg, const std::functio
864 }); 889 });
865} 890}
866 891
867void MailTemplates::forward(const KMime::Message::Ptr &origMsg, const std::function<void(const KMime::Message::Ptr &result)> &callback) 892void MailTemplates::forward(const KMime::Message::Ptr &origMsg,
893 const std::function<void(const KMime::Message::Ptr &result)> &callback)
868{ 894{
869 KMime::Message::Ptr wrapperMsg(new KMime::Message); 895 KMime::Message::Ptr wrapperMsg(new KMime::Message);
870 896
871 wrapperMsg->to()->clear(); 897 wrapperMsg->to()->clear();
872 wrapperMsg->cc()->clear(); 898 wrapperMsg->cc()->clear();
873 899
874 wrapperMsg->subject()->fromUnicodeString(forwardSubject(origMsg->subject()->asUnicodeString()), "utf-8"); 900 // Decrypt the original message, it will be encrypted again in the composer
901 // for the right recipient
902 KMime::Message::Ptr forwardedMessage(new KMime::Message());
903 if (isEncrypted(origMsg.data())) {
904 qDebug() << "Original message was encrypted, decrypting it";
905 MimeTreeParser::ObjectTreeParser otp;
906 otp.parseObjectTree(origMsg.data());
907 otp.decryptParts();
875 908
876 const QByteArray refStr = getRefStr(origMsg); 909 auto htmlContent = otp.htmlContent();
910
911 KMime::Content *recreatedMsg =
912 htmlContent.isEmpty() ? createPlainPartContent(otp.plainTextContent()) :
913 createMultipartAlternativeContent(otp.plainTextContent(), htmlContent);
914
915 KMime::Message::Ptr tmpForwardedMessage;
916 auto attachments = otp.collectAttachmentParts();
917 if (!attachments.isEmpty()) {
918 QVector<KMime::Content *> contents = {recreatedMsg};
919 for (const auto &attachment : attachments) {
920 contents.append(attachment->node());
921 }
922
923 auto msg = createMultipartMixedContent(contents);
924
925 tmpForwardedMessage.reset(KMime::contentToMessage(msg));
926 } else {
927 tmpForwardedMessage.reset(KMime::contentToMessage(recreatedMsg));
928 }
929
930 origMsg->contentType()->fromUnicodeString(tmpForwardedMessage->contentType()->asUnicodeString(), "utf-8");
931 origMsg->assemble();
932 forwardedMessage->setHead(origMsg->head());
933 forwardedMessage->setBody(tmpForwardedMessage->encodedBody());
934 forwardedMessage->parse();
935
936 } else {
937 qDebug() << "Original message was not encrypted, using it as-is";
938 forwardedMessage = origMsg;
939 }
940
941 wrapperMsg->subject()->fromUnicodeString(
942 forwardSubject(forwardedMessage->subject()->asUnicodeString()), "utf-8");
943
944 const QByteArray refStr = getRefStr(forwardedMessage);
877 if (!refStr.isEmpty()) { 945 if (!refStr.isEmpty()) {
878 wrapperMsg->references()->fromUnicodeString(QString::fromLocal8Bit(refStr), "utf-8"); 946 wrapperMsg->references()->fromUnicodeString(QString::fromLocal8Bit(refStr), "utf-8");
879 } 947 }
880 948
881 KMime::Content* fwdAttachment = new KMime::Content; 949 KMime::Content *fwdAttachment = new KMime::Content;
882 950
883 fwdAttachment->contentDisposition()->setDisposition(KMime::Headers::CDinline); 951 fwdAttachment->contentDisposition()->setDisposition(KMime::Headers::CDinline);
884 fwdAttachment->contentType()->setMimeType("message/rfc822"); 952 fwdAttachment->contentType()->setMimeType("message/rfc822");
885 fwdAttachment->contentDisposition()->setFilename(origMsg->subject()->asUnicodeString() + ".eml"); 953 fwdAttachment->contentDisposition()->setFilename(forwardedMessage->subject()->asUnicodeString() + ".eml");
886 // The mail was parsed in loadMessage before, so no need to assemble it 954 // The mail was parsed in loadMessage before, so no need to assemble it
887 fwdAttachment->setBody(origMsg->encodedContent()); 955 fwdAttachment->setBody(forwardedMessage->encodedContent());
888 956
889 wrapperMsg->addContent(fwdAttachment); 957 wrapperMsg->addContent(fwdAttachment);
890 wrapperMsg->assemble(); 958 wrapperMsg->assemble();
diff --git a/framework/src/domain/mime/mimetreeparser/tests/CMakeLists.txt b/framework/src/domain/mime/mimetreeparser/tests/CMakeLists.txt
index edc037bc..88f7c47a 100644
--- a/framework/src/domain/mime/mimetreeparser/tests/CMakeLists.txt
+++ b/framework/src/domain/mime/mimetreeparser/tests/CMakeLists.txt
@@ -11,7 +11,7 @@ include(ECMAddTests)
11find_package(Gpgmepp 1.7.1 CONFIG) 11find_package(Gpgmepp 1.7.1 CONFIG)
12find_package(QGpgme 1.7.1 CONFIG) 12find_package(QGpgme 1.7.1 CONFIG)
13 13
14add_executable(mimetreeparsertest interfacetest.cpp) 14add_executable(mimetreeparsertest mimetreeparsertest.cpp)
15add_gpg_crypto_test(mimetreeparsertest mimetreeparsertest) 15add_gpg_crypto_test(mimetreeparsertest mimetreeparsertest)
16target_link_libraries(mimetreeparsertest 16target_link_libraries(mimetreeparsertest
17 kube_otp 17 kube_otp
diff --git a/framework/src/domain/mime/mimetreeparser/tests/interfacetest.cpp b/framework/src/domain/mime/mimetreeparser/tests/mimetreeparsertest.cpp
index 69509715..961dbf9a 100644
--- a/framework/src/domain/mime/mimetreeparser/tests/interfacetest.cpp
+++ b/framework/src/domain/mime/mimetreeparser/tests/mimetreeparsertest.cpp
@@ -374,4 +374,4 @@ private slots:
374}; 374};
375 375
376QTEST_GUILESS_MAIN(InterfaceTest) 376QTEST_GUILESS_MAIN(InterfaceTest)
377#include "interfacetest.moc" 377#include "mimetreeparsertest.moc"
diff --git a/framework/src/domain/mime/tests/mailtemplatetest.cpp b/framework/src/domain/mime/tests/mailtemplatetest.cpp
index 8d044608..6338cd58 100644
--- a/framework/src/domain/mime/tests/mailtemplatetest.cpp
+++ b/framework/src/domain/mime/tests/mailtemplatetest.cpp
@@ -248,6 +248,55 @@ private slots:
248 QCOMPARE(origMsg->subject(false)->asUnicodeString(), {"A random subject with alternative contenttype"}); 248 QCOMPARE(origMsg->subject(false)->asUnicodeString(), {"A random subject with alternative contenttype"});
249 } 249 }
250 250
251 void testEncryptedForwardAsAttachment()
252 {
253 auto msg = readMail("openpgp-encrypted.mbox");
254 KMime::Message::Ptr result;
255 MailTemplates::forward(msg, [&](const KMime::Message::Ptr &r) { result = r; });
256 QTRY_VERIFY(result);
257 QCOMPARE(result->subject(false)->asUnicodeString(), {"FW: OpenPGP encrypted"});
258 QCOMPARE(result->to()->addresses(), {});
259 QCOMPARE(result->cc()->addresses(), {});
260
261 auto attachments = result->attachments();
262 QCOMPARE(attachments.size(), 1);
263 auto attachment = attachments[0];
264 QCOMPARE(attachment->contentDisposition(false)->disposition(), KMime::Headers::CDinline);
265 QCOMPARE(attachment->contentDisposition(false)->filename(), {"OpenPGP encrypted.eml"});
266 QVERIFY(attachment->bodyIsMessage());
267
268 attachment->parse();
269 auto origMsg = attachment->bodyAsMessage();
270 QCOMPARE(origMsg->subject(false)->asUnicodeString(), {"OpenPGP encrypted"});
271 }
272
273 void testEncryptedWithAttachmentsForwardAsAttachment()
274 {
275 auto msg = readMail("openpgp-encrypted-two-attachments.mbox");
276 KMime::Message::Ptr result;
277 MailTemplates::forward(msg, [&](const KMime::Message::Ptr &r) { result = r; });
278 QTRY_VERIFY(result);
279 QCOMPARE(result->subject(false)->asUnicodeString(), {"FW: OpenPGP encrypted with 2 text attachments"});
280 QCOMPARE(result->to()->addresses(), {});
281 QCOMPARE(result->cc()->addresses(), {});
282
283 auto attachments = result->attachments();
284 QCOMPARE(attachments.size(), 1);
285 auto attachment = attachments[0];
286 QCOMPARE(attachment->contentDisposition(false)->disposition(), KMime::Headers::CDinline);
287 QCOMPARE(attachment->contentDisposition(false)->filename(), {"OpenPGP encrypted with 2 text attachments.eml"});
288 QVERIFY(attachment->bodyIsMessage());
289
290 attachment->parse();
291 auto origMsg = attachment->bodyAsMessage();
292 QCOMPARE(origMsg->subject(false)->asUnicodeString(), {"OpenPGP encrypted with 2 text attachments"});
293
294 auto attattachments = origMsg->attachments();
295 QCOMPARE(attattachments.size(), 2);
296 QCOMPARE(attattachments[0]->contentDisposition(false)->filename(), {"attachment1.txt"});
297 QCOMPARE(attattachments[1]->contentDisposition(false)->filename(), {"attachment2.txt"});
298 }
299
251 void testCreatePlainMail() 300 void testCreatePlainMail()
252 { 301 {
253 QStringList to = {{"to@example.org"}}; 302 QStringList to = {{"to@example.org"}};