diff options
Diffstat (limited to 'framework/src')
-rw-r--r-- | framework/src/domain/composercontroller.cpp | 84 | ||||
-rw-r--r-- | framework/src/domain/mime/mailtemplates.cpp | 92 | ||||
-rw-r--r-- | framework/src/domain/mime/mailtemplates.h | 9 | ||||
-rw-r--r-- | framework/src/domain/mime/tests/mailtemplatetest.cpp | 28 |
4 files changed, 126 insertions, 87 deletions
diff --git a/framework/src/domain/composercontroller.cpp b/framework/src/domain/composercontroller.cpp index 3c2b7fc1..311c79f3 100644 --- a/framework/src/domain/composercontroller.cpp +++ b/framework/src/domain/composercontroller.cpp | |||
@@ -383,88 +383,6 @@ void ComposerController::recordForAutocompletion(const QByteArray &addrSpec, con | |||
383 | } | 383 | } |
384 | } | 384 | } |
385 | 385 | ||
386 | static KMime::Content *createAttachmentPart(const QByteArray &content, const QString &filename, bool isInline, const QByteArray &mimeType, const QString &name) | ||
387 | { | ||
388 | |||
389 | KMime::Content *part = new KMime::Content; | ||
390 | part->contentDisposition(true)->setFilename(filename); | ||
391 | if (isInline) { | ||
392 | part->contentDisposition(true)->setDisposition(KMime::Headers::CDinline); | ||
393 | } else { | ||
394 | part->contentDisposition(true)->setDisposition(KMime::Headers::CDattachment); | ||
395 | } | ||
396 | part->contentType(true)->setMimeType(mimeType); | ||
397 | part->contentType(true)->setName(name, "utf-8"); | ||
398 | //Just always encode attachments base64 so it's safe for binary data | ||
399 | part->contentTransferEncoding(true)->setEncoding(KMime::Headers::CEbase64); | ||
400 | part->setBody(content); | ||
401 | return part; | ||
402 | } | ||
403 | |||
404 | static KMime::Content *createBodyPart(const QByteArray &body) { | ||
405 | auto mainMessage = new KMime::Content; | ||
406 | mainMessage->setBody(body); | ||
407 | mainMessage->contentType(true)->setMimeType("text/plain"); | ||
408 | return mainMessage; | ||
409 | } | ||
410 | |||
411 | struct Attachment { | ||
412 | QString name; | ||
413 | QString filename; | ||
414 | QByteArray mimeType; | ||
415 | bool isInline; | ||
416 | QByteArray data; | ||
417 | }; | ||
418 | |||
419 | static 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) | ||
420 | { | ||
421 | auto mail = existingMessage; | ||
422 | if (!mail) { | ||
423 | mail = KMime::Message::Ptr::create(); | ||
424 | } | ||
425 | mail->to(true)->clear(); | ||
426 | applyAddresses(to, [&](const QByteArray &addrSpec, const QByteArray &displayName) { | ||
427 | mail->to(true)->addAddress(addrSpec, displayName); | ||
428 | }); | ||
429 | |||
430 | mail->cc(true)->clear(); | ||
431 | applyAddresses(cc, [&](const QByteArray &addrSpec, const QByteArray &displayName) { | ||
432 | mail->cc(true)->addAddress(addrSpec, displayName); | ||
433 | }); | ||
434 | |||
435 | mail->bcc(true)->clear(); | ||
436 | applyAddresses(bcc, [&](const QByteArray &addrSpec, const QByteArray &displayName) { | ||
437 | mail->bcc(true)->addAddress(addrSpec, displayName); | ||
438 | }); | ||
439 | |||
440 | mail->from(true)->addAddress(from); | ||
441 | |||
442 | mail->subject(true)->fromUnicodeString(subject, "utf-8"); | ||
443 | if (!mail->messageID()) { | ||
444 | mail->messageID(true)->generate("org.kde.kube"); | ||
445 | } | ||
446 | if (!mail->date(true)->dateTime().isValid()) { | ||
447 | mail->date(true)->setDateTime(QDateTime::currentDateTimeUtc()); | ||
448 | } | ||
449 | |||
450 | if (!attachments.isEmpty()) { | ||
451 | mail->contentType(true)->setMimeType("multipart/mixed"); | ||
452 | mail->contentType()->setBoundary(KMime::multiPartBoundary()); | ||
453 | mail->contentTransferEncoding()->setEncoding(KMime::Headers::CE7Bit); | ||
454 | mail->setPreamble("This is a multi-part message in MIME format.\n"); | ||
455 | for (const auto &attachment : attachments) { | ||
456 | mail->addContent(createAttachmentPart(attachment.data, attachment.filename, attachment.isInline, attachment.mimeType, attachment.name)); | ||
457 | } | ||
458 | mail->addContent(createBodyPart(body.toUtf8())); | ||
459 | } else { | ||
460 | //FIXME same implementation as above for attachments | ||
461 | mail->setBody(body.toUtf8()); | ||
462 | } | ||
463 | |||
464 | mail->assemble(); | ||
465 | return mail; | ||
466 | } | ||
467 | |||
468 | KMime::Message::Ptr ComposerController::assembleMessage() | 386 | KMime::Message::Ptr ComposerController::assembleMessage() |
469 | { | 387 | { |
470 | applyAddresses(mToModel->stringList(), [&](const QByteArray &addrSpec, const QByteArray &displayName) { | 388 | applyAddresses(mToModel->stringList(), [&](const QByteArray &addrSpec, const QByteArray &displayName) { |
@@ -491,7 +409,7 @@ KMime::Message::Ptr ComposerController::assembleMessage() | |||
491 | }; | 409 | }; |
492 | } | 410 | } |
493 | } | 411 | } |
494 | return createMessage(mExistingMessage, mToModel->stringList(), mCcModel->stringList(), mBccModel->stringList(), getIdentity(), getSubject(), getBody(), attachments); | 412 | return MailTemplates::createMessage(mExistingMessage, mToModel->stringList(), mCcModel->stringList(), mBccModel->stringList(), getIdentity(), getSubject(), getBody(), attachments); |
495 | } | 413 | } |
496 | 414 | ||
497 | void ComposerController::updateSendAction() | 415 | void ComposerController::updateSendAction() |
diff --git a/framework/src/domain/mime/mailtemplates.cpp b/framework/src/domain/mime/mailtemplates.cpp index 71a267a8..ce1cd52f 100644 --- a/framework/src/domain/mime/mailtemplates.cpp +++ b/framework/src/domain/mime/mailtemplates.cpp | |||
@@ -34,6 +34,7 @@ | |||
34 | 34 | ||
35 | #include <KCodecs/KCharsets> | 35 | #include <KCodecs/KCharsets> |
36 | #include <KMime/Types> | 36 | #include <KMime/Types> |
37 | #include <KCodecs/KEmailAddress> | ||
37 | 38 | ||
38 | #include <mimetreeparser/objecttreeparser.h> | 39 | #include <mimetreeparser/objecttreeparser.h> |
39 | 40 | ||
@@ -885,3 +886,94 @@ QString MailTemplates::plaintextContent(const KMime::Message::Ptr &msg) | |||
885 | } | 886 | } |
886 | return plain; | 887 | return plain; |
887 | } | 888 | } |
889 | |||
890 | static KMime::Content *createAttachmentPart(const QByteArray &content, const QString &filename, bool isInline, const QByteArray &mimeType, const QString &name) | ||
891 | { | ||
892 | |||
893 | KMime::Content *part = new KMime::Content; | ||
894 | part->contentDisposition(true)->setFilename(filename); | ||
895 | if (isInline) { | ||
896 | part->contentDisposition(true)->setDisposition(KMime::Headers::CDinline); | ||
897 | } else { | ||
898 | part->contentDisposition(true)->setDisposition(KMime::Headers::CDattachment); | ||
899 | } | ||
900 | part->contentType(true)->setMimeType(mimeType); | ||
901 | part->contentType(true)->setName(name, "utf-8"); | ||
902 | //Just always encode attachments base64 so it's safe for binary data | ||
903 | part->contentTransferEncoding(true)->setEncoding(KMime::Headers::CEbase64); | ||
904 | part->setBody(content); | ||
905 | return part; | ||
906 | } | ||
907 | |||
908 | static KMime::Content *createBodyPart(const QByteArray &body) { | ||
909 | auto mainMessage = new KMime::Content; | ||
910 | mainMessage->setBody(body); | ||
911 | mainMessage->contentType(true)->setMimeType("text/plain"); | ||
912 | // return MailCrypto::sign(mainMessage, {}); | ||
913 | return mainMessage; | ||
914 | } | ||
915 | |||
916 | static void applyAddresses(const QStringList &list, std::function<void(const QByteArray &, const QByteArray &)> callback) | ||
917 | { | ||
918 | for (const auto &to : list) { | ||
919 | QByteArray displayName; | ||
920 | QByteArray addrSpec; | ||
921 | QByteArray comment; | ||
922 | KEmailAddress::splitAddress(to.toUtf8(), displayName, addrSpec, comment); | ||
923 | callback(addrSpec, displayName); | ||
924 | } | ||
925 | } | ||
926 | |||
927 | // static void applyAddresses(const QString &list, std::function<void(const QByteArray &, const QByteArray &)> callback) | ||
928 | // { | ||
929 | // applyAddresses(KEmailAddress::splitAddressList(list), callback); | ||
930 | // } | ||
931 | |||
932 | 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) | ||
933 | { | ||
934 | auto mail = existingMessage; | ||
935 | if (!mail) { | ||
936 | mail = KMime::Message::Ptr::create(); | ||
937 | } | ||
938 | mail->to(true)->clear(); | ||
939 | applyAddresses(to, [&](const QByteArray &addrSpec, const QByteArray &displayName) { | ||
940 | mail->to(true)->addAddress(addrSpec, displayName); | ||
941 | }); | ||
942 | |||
943 | mail->cc(true)->clear(); | ||
944 | applyAddresses(cc, [&](const QByteArray &addrSpec, const QByteArray &displayName) { | ||
945 | mail->cc(true)->addAddress(addrSpec, displayName); | ||
946 | }); | ||
947 | |||
948 | mail->bcc(true)->clear(); | ||
949 | applyAddresses(bcc, [&](const QByteArray &addrSpec, const QByteArray &displayName) { | ||
950 | mail->bcc(true)->addAddress(addrSpec, displayName); | ||
951 | }); | ||
952 | |||
953 | mail->from(true)->addAddress(from); | ||
954 | |||
955 | mail->subject(true)->fromUnicodeString(subject, "utf-8"); | ||
956 | if (!mail->messageID()) { | ||
957 | mail->messageID(true)->generate("org.kde.kube"); | ||
958 | } | ||
959 | if (!mail->date(true)->dateTime().isValid()) { | ||
960 | mail->date(true)->setDateTime(QDateTime::currentDateTimeUtc()); | ||
961 | } | ||
962 | |||
963 | if (!attachments.isEmpty()) { | ||
964 | mail->contentType(true)->setMimeType("multipart/mixed"); | ||
965 | mail->contentType()->setBoundary(KMime::multiPartBoundary()); | ||
966 | mail->contentTransferEncoding()->setEncoding(KMime::Headers::CE7Bit); | ||
967 | mail->setPreamble("This is a multi-part message in MIME format.\n"); | ||
968 | for (const auto &attachment : attachments) { | ||
969 | mail->addContent(createAttachmentPart(attachment.data, attachment.filename, attachment.isInline, attachment.mimeType, attachment.name)); | ||
970 | } | ||
971 | mail->addContent(createBodyPart(body.toUtf8())); | ||
972 | } else { | ||
973 | //FIXME same implementation as above for attachments | ||
974 | mail->setBody(body.toUtf8()); | ||
975 | } | ||
976 | |||
977 | mail->assemble(); | ||
978 | return mail; | ||
979 | } | ||
diff --git a/framework/src/domain/mime/mailtemplates.h b/framework/src/domain/mime/mailtemplates.h index 4f559bb6..773ded05 100644 --- a/framework/src/domain/mime/mailtemplates.h +++ b/framework/src/domain/mime/mailtemplates.h | |||
@@ -23,8 +23,17 @@ | |||
23 | #include <KMime/Message> | 23 | #include <KMime/Message> |
24 | #include <functional> | 24 | #include <functional> |
25 | 25 | ||
26 | struct Attachment { | ||
27 | QString name; | ||
28 | QString filename; | ||
29 | QByteArray mimeType; | ||
30 | bool isInline; | ||
31 | QByteArray data; | ||
32 | }; | ||
33 | |||
26 | namespace MailTemplates | 34 | namespace MailTemplates |
27 | { | 35 | { |
28 | void reply(const KMime::Message::Ptr &origMsg, const std::function<void(const KMime::Message::Ptr &result)> &callback); | 36 | void reply(const KMime::Message::Ptr &origMsg, const std::function<void(const KMime::Message::Ptr &result)> &callback); |
29 | QString plaintextContent(const KMime::Message::Ptr &origMsg); | 37 | 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); | ||
30 | }; | 39 | }; |
diff --git a/framework/src/domain/mime/tests/mailtemplatetest.cpp b/framework/src/domain/mime/tests/mailtemplatetest.cpp index e9752c9e..f393f1bd 100644 --- a/framework/src/domain/mime/tests/mailtemplatetest.cpp +++ b/framework/src/domain/mime/tests/mailtemplatetest.cpp | |||
@@ -58,7 +58,7 @@ private slots: | |||
58 | QtWebEngine::initialize(); | 58 | QtWebEngine::initialize(); |
59 | } | 59 | } |
60 | 60 | ||
61 | void testPlain() | 61 | void testPlainReply() |
62 | { | 62 | { |
63 | auto msg = readMail("plaintext.mbox"); | 63 | auto msg = readMail("plaintext.mbox"); |
64 | KMime::Message::Ptr result; | 64 | KMime::Message::Ptr result; |
@@ -69,7 +69,7 @@ private slots: | |||
69 | QCOMPARE(normalize(removeFirstLine(result->body())), normalize(msg->body())); | 69 | QCOMPARE(normalize(removeFirstLine(result->body())), normalize(msg->body())); |
70 | } | 70 | } |
71 | 71 | ||
72 | void testHtml() | 72 | void testHtmlReply() |
73 | { | 73 | { |
74 | auto msg = readMail("html.mbox"); | 74 | auto msg = readMail("html.mbox"); |
75 | KMime::Message::Ptr result; | 75 | KMime::Message::Ptr result; |
@@ -80,7 +80,7 @@ private slots: | |||
80 | QCOMPARE(unquote(removeFirstLine(result->body())), QLatin1String("HTML text")); | 80 | QCOMPARE(unquote(removeFirstLine(result->body())), QLatin1String("HTML text")); |
81 | } | 81 | } |
82 | 82 | ||
83 | void testMultipartSigned() | 83 | void testMultipartSignedReply() |
84 | { | 84 | { |
85 | auto msg = readMail("openpgp-signed-mailinglist.mbox"); | 85 | auto msg = readMail("openpgp-signed-mailinglist.mbox"); |
86 | KMime::Message::Ptr result; | 86 | KMime::Message::Ptr result; |
@@ -93,7 +93,7 @@ private slots: | |||
93 | QVERIFY(content.contains("i noticed a new branch")); | 93 | QVERIFY(content.contains("i noticed a new branch")); |
94 | } | 94 | } |
95 | 95 | ||
96 | void testMultipartAlternative() | 96 | void testMultipartAlternativeReply() |
97 | { | 97 | { |
98 | auto msg = readMail("alternative.mbox"); | 98 | auto msg = readMail("alternative.mbox"); |
99 | KMime::Message::Ptr result; | 99 | KMime::Message::Ptr result; |
@@ -106,6 +106,26 @@ private slots: | |||
106 | QCOMPARE(unquote(content), QLatin1String("If you can see this text it means that your email client couldn't display our newsletter properly.\nPlease visit this link to view the newsletter on our website: http://www.gog.com/newsletter/\n")); | 106 | QCOMPARE(unquote(content), QLatin1String("If you can see this text it means that your email client couldn't display our newsletter properly.\nPlease visit this link to view the newsletter on our website: http://www.gog.com/newsletter/\n")); |
107 | } | 107 | } |
108 | 108 | ||
109 | void testCreatePlainMail() | ||
110 | { | ||
111 | QStringList to = {{"to@example.org"}}; | ||
112 | QStringList cc = {{"cc@example.org"}};; | ||
113 | QStringList bcc = {{"bcc@example.org"}};; | ||
114 | KMime::Types::Mailbox from; | ||
115 | from.fromUnicodeString("from@example.org"); | ||
116 | QString subject = "subject"; | ||
117 | QString body = "body"; | ||
118 | QList<Attachment> attachments; | ||
119 | |||
120 | auto result = MailTemplates::createMessage({}, to, cc, bcc, from, subject, body, attachments); | ||
121 | |||
122 | QVERIFY(result); | ||
123 | auto content = removeFirstLine(result->body()); | ||
124 | QCOMPARE(result->subject()->asUnicodeString(), subject); | ||
125 | QCOMPARE(result->body(), body.toUtf8()); | ||
126 | QVERIFY(result->date(false)->dateTime().isValid()); | ||
127 | } | ||
128 | |||
109 | }; | 129 | }; |
110 | 130 | ||
111 | QTEST_MAIN(MailTemplateTest) | 131 | QTEST_MAIN(MailTemplateTest) |