diff --git a/mimetreeparser/autotests/basicobjecttreeparsertest.cpp b/mimetreeparser/autotests/basicobjecttreeparsertest.cpp index 04f40a65..a01d090b 100644 --- a/mimetreeparser/autotests/basicobjecttreeparsertest.cpp +++ b/mimetreeparser/autotests/basicobjecttreeparsertest.cpp @@ -1,282 +1,309 @@ /* Copyright (c) 2010 Thomas McGuire Copyright (c) 2019 Sandro Knauß This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "basicobjecttreeparsertest.h" #include "util.h" #include "setupenv.h" #include #include #include #include using namespace MimeTreeParser; QTEST_MAIN(ObjectTreeParserTest) void ObjectTreeParserTest::initTestCase() { Test::setupEnv(); } void ObjectTreeParserTest::testMailWithoutEncryption() { KMime::Message::Ptr originalMessage = readAndParseMail(QStringLiteral("encapsulated-with-attachment.mbox")); NodeHelper nodeHelper; SimpleObjectTreeSource testSource; ObjectTreeParser otp(&testSource, &nodeHelper); otp.parseObjectTree(originalMessage.data()); QVERIFY(!nodeHelper.unencryptedMessage(originalMessage)); } void ObjectTreeParserTest::testSignedForwardedOpenPGPSignedEncrypted() { KMime::Message::Ptr originalMessage = readAndParseMail(QStringLiteral("signed-forward-openpgp-signed-encrypted.mbox")); NodeHelper nodeHelper; SimpleObjectTreeSource testSource; ObjectTreeParser otp(&testSource, &nodeHelper); otp.parseObjectTree(originalMessage.data()); QCOMPARE(otp.plainTextContent().toLatin1().data(), "bla bla bla"); // The textual content doesn't include the encrypted encapsulated message by design QCOMPARE(nodeHelper.overallEncryptionState( originalMessage.data()), KMMsgPartiallyEncrypted); QCOMPARE(nodeHelper.overallSignatureState( originalMessage.data()), KMMsgFullySigned); KMime::Message::Ptr unencryptedMessage = nodeHelper.unencryptedMessage(originalMessage); QVERIFY(!unencryptedMessage); // We must not invalidate the outer signature } void ObjectTreeParserTest::testForwardedOpenPGPSignedEncrypted() { KMime::Message::Ptr originalMessage = readAndParseMail(QStringLiteral("forward-openpgp-signed-encrypted.mbox")); NodeHelper nodeHelper; SimpleObjectTreeSource testSource; ObjectTreeParser otp(&testSource, &nodeHelper); testSource.setDecryptMessage(true); otp.parseObjectTree(originalMessage.data()); QCOMPARE(otp.plainTextContent().toLatin1().data(), "bla bla bla"); // The textual content doesn't include the encrypted encapsulated message by design QCOMPARE(nodeHelper.overallEncryptionState( originalMessage.data()), KMMsgPartiallyEncrypted); QCOMPARE(nodeHelper.overallSignatureState( originalMessage.data()), KMMsgPartiallySigned); // Now, test that the unencrypted message is generated correctly KMime::Message::Ptr unencryptedMessage = nodeHelper.unencryptedMessage(originalMessage); QVERIFY(unencryptedMessage.data()); QCOMPARE(unencryptedMessage->contentType()->mimeType().data(), "multipart/mixed"); QCOMPARE(unencryptedMessage->contents().size(), 2); QCOMPARE(unencryptedMessage->contents().first()->contentType()->mimeType().data(), "text/plain"); QCOMPARE(unencryptedMessage->contents().first()->decodedContent().data(), "bla bla bla"); QCOMPARE(unencryptedMessage->contents().at( 1)->contentType()->mimeType().data(), "message/rfc822"); KMime::Message::Ptr encapsulated = unencryptedMessage->contents().at(1)->bodyAsMessage(); QCOMPARE(encapsulated->contentType()->mimeType().data(), "multipart/signed"); QCOMPARE(encapsulated->contents().size(), 2); QCOMPARE(encapsulated->contents().first()->contentType()->mimeType().data(), "text/plain"); QCOMPARE(encapsulated->contents().at( 1)->contentType()->mimeType().data(), "application/pgp-signature"); QCOMPARE(encapsulated->contents().first()->decodedContent().data(), "encrypted message text"); // TODO: Check that the signature is valid } void ObjectTreeParserTest::testSMIMESignedEncrypted() { KMime::Message::Ptr originalMessage = readAndParseMail(QStringLiteral("smime-signed-encrypted.mbox")); NodeHelper nodeHelper; SimpleObjectTreeSource testSource; ObjectTreeParser otp(&testSource, &nodeHelper); testSource.setDecryptMessage(true); otp.parseObjectTree(originalMessage.data()); QCOMPARE(otp.plainTextContent().toLatin1().data(), "encrypted message text"); QCOMPARE(nodeHelper.overallEncryptionState( originalMessage.data()), KMMsgFullyEncrypted); QCOMPARE(nodeHelper.overallSignatureState( originalMessage.data()), KMMsgFullySigned); // Now, test that the unencrypted message is generated correctly KMime::Message::Ptr unencryptedMessage = nodeHelper.unencryptedMessage(originalMessage); QCOMPARE(unencryptedMessage->contentType()->mimeType().data(), "multipart/signed"); QCOMPARE(unencryptedMessage->contents().size(), 2); QCOMPARE(unencryptedMessage->contents().first()->contentType()->mimeType().data(), "text/plain"); QCOMPARE(unencryptedMessage->contents().at( 1)->contentType()->mimeType().data(), "application/pkcs7-signature"); QCOMPARE( unencryptedMessage->contents().first()->decodedContent().data(), "encrypted message text"); // TODO: Check that the signature is valid } void ObjectTreeParserTest::testOpenPGPSignedEncrypted() { KMime::Message::Ptr originalMessage = readAndParseMail(QStringLiteral("openpgp-signed-encrypted.mbox")); NodeHelper nodeHelper; SimpleObjectTreeSource testSource; ObjectTreeParser otp(&testSource, &nodeHelper); testSource.setDecryptMessage(true); otp.parseObjectTree(originalMessage.data()); QCOMPARE(otp.plainTextContent().toLatin1().data(), "encrypted message text"); QCOMPARE(nodeHelper.overallEncryptionState( originalMessage.data()), KMMsgFullyEncrypted); QCOMPARE(nodeHelper.overallSignatureState( originalMessage.data()), KMMsgFullySigned); // Now, test that the unencrypted message is generated correctly KMime::Message::Ptr unencryptedMessage = nodeHelper.unencryptedMessage(originalMessage); QCOMPARE(unencryptedMessage->contentType()->mimeType().data(), "multipart/signed"); QCOMPARE(unencryptedMessage->contents().size(), 2); QCOMPARE(unencryptedMessage->contents().first()->contentType()->mimeType().data(), "text/plain"); QCOMPARE(unencryptedMessage->contents().at( 1)->contentType()->mimeType().data(), "application/pgp-signature"); QCOMPARE( unencryptedMessage->contents().first()->decodedContent().data(), "encrypted message text"); // TODO: Check that the signature is valid } void ObjectTreeParserTest::testOpenPGPEncryptedAndSigned() { KMime::Message::Ptr originalMessage = readAndParseMail(QStringLiteral("openpgp-encrypted+signed.mbox")); NodeHelper nodeHelper; SimpleObjectTreeSource testSource; ObjectTreeParser otp(&testSource, &nodeHelper); testSource.setDecryptMessage(true); otp.parseObjectTree(originalMessage.data()); QCOMPARE(otp.plainTextContent().toLatin1().data(), "encrypted message text"); QCOMPARE(nodeHelper.overallEncryptionState( originalMessage.data()), KMMsgFullyEncrypted); QCOMPARE(nodeHelper.overallSignatureState( originalMessage.data()), KMMsgFullySigned); // Now, test that the unencrypted message is generated correctly KMime::Message::Ptr unencryptedMessage = nodeHelper.unencryptedMessage(originalMessage); QCOMPARE(unencryptedMessage->contentType()->mimeType().data(), "text/plain"); QCOMPARE(unencryptedMessage->contents().size(), 0); QCOMPARE(unencryptedMessage->decodedContent().data(), "encrypted message text"); // TODO: Check that the signature is valid } void ObjectTreeParserTest::testOpenPGPEncrypted() { KMime::Message::Ptr originalMessage = readAndParseMail(QStringLiteral("openpgp-encrypted.mbox")); NodeHelper nodeHelper; SimpleObjectTreeSource testSource; ObjectTreeParser otp(&testSource, &nodeHelper); testSource.setDecryptMessage(true); otp.parseObjectTree(originalMessage.data()); QCOMPARE(otp.plainTextContent().toLatin1().data(), "encrypted message text"); QCOMPARE(nodeHelper.overallEncryptionState( originalMessage.data()), KMMsgFullyEncrypted); // Now, test that the unencrypted message is generated correctly KMime::Message::Ptr unencryptedMessage = nodeHelper.unencryptedMessage(originalMessage); QCOMPARE(unencryptedMessage->contentType()->mimeType().data(), "text/plain"); QCOMPARE(unencryptedMessage->decodedContent().data(), "encrypted message text"); QCOMPARE(unencryptedMessage->contents().size(), 0); } void ObjectTreeParserTest::testOpenPGPEncryptedNotDecrypted() { KMime::Message::Ptr originalMessage = readAndParseMail(QStringLiteral("openpgp-encrypted.mbox")); NodeHelper nodeHelper; SimpleObjectTreeSource testSource; ObjectTreeParser otp(&testSource, &nodeHelper); otp.parseObjectTree(originalMessage.data()); QCOMPARE(nodeHelper.overallEncryptionState( originalMessage.data()), KMMsgFullyEncrypted); QCOMPARE(otp.plainTextContent().toLatin1().data(), ""); KMime::Message::Ptr unencryptedMessage = nodeHelper.unencryptedMessage(originalMessage); QVERIFY(!unencryptedMessage); } void ObjectTreeParserTest::testAsync_data() { QTest::addColumn("mailFileName"); QTest::addColumn("output"); QTest::newRow("openpgp-encrypt") << QStringLiteral("openpgp-encrypted.mbox") << QStringLiteral( "encrypted message text"); QTest::newRow("smime-opaque-sign") << QStringLiteral("smime-opaque-sign.mbox") << QStringLiteral("A simple signed only test."); QTest::newRow("smime-encrypt") << QStringLiteral("smime-encrypted.mbox") << QStringLiteral( "The quick brown fox jumped over the lazy dog."); QTest::newRow("openpgp-inline-encrypt") << QStringLiteral( "openpgp-inline-charset-encrypted.mbox") << QStringLiteral( "asdasd asd asd asdf sadf sdaf sadf \u00F6\u00E4\u00FC"); } void ObjectTreeParserTest::testAsync() { QFETCH(QString, mailFileName); QFETCH(QString, output); KMime::Message::Ptr originalMessage = readAndParseMail(mailFileName); NodeHelper nodeHelper; SimpleObjectTreeSource testSource; testSource.setDecryptMessage(true); { QEventLoop loop; ObjectTreeParser otp(&testSource, &nodeHelper); connect(&nodeHelper, &NodeHelper::update, &loop, &QEventLoop::quit); otp.setAllowAsync(true); otp.parseObjectTree(originalMessage.data()); loop.exec(); } // Job ended { ObjectTreeParser otp(&testSource, &nodeHelper); otp.setAllowAsync(true); otp.parseObjectTree(originalMessage.data()); QCOMPARE(otp.plainTextContent(), output); } } + +void ObjectTreeParserTest::testHtmlContent_data() +{ + QTest::addColumn("mailFileName"); + QTest::addColumn("output"); + + QTest::newRow("html-attachments1") << QStringLiteral("html-attachment1.mbox") << QStringLiteral( + "

A Body Text

"); + QTest::newRow("html-attachments2") << QStringLiteral("html-attachment2.mbox") + << QStringLiteral("HTML Text"); +} + +void ObjectTreeParserTest::testHtmlContent() +{ + QFETCH(QString, mailFileName); + QFETCH(QString, output); + + KMime::Message::Ptr originalMessage = readAndParseMail(mailFileName); + NodeHelper nodeHelper; + SimpleObjectTreeSource testSource; + ObjectTreeParser otp(&testSource, &nodeHelper); + testSource.setDecryptMessage(true); + otp.parseObjectTree(originalMessage.data()); + + QVERIFY(otp.plainTextContent().isEmpty()); + QCOMPARE(otp.htmlContent(), output); +} diff --git a/mimetreeparser/autotests/basicobjecttreeparsertest.h b/mimetreeparser/autotests/basicobjecttreeparsertest.h index ba6627af..069035a2 100644 --- a/mimetreeparser/autotests/basicobjecttreeparsertest.h +++ b/mimetreeparser/autotests/basicobjecttreeparsertest.h @@ -1,43 +1,45 @@ /* Copyright (c) 2010 Thomas McGuire Copyright (c) 2019 Sandro Knauß This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef MIMETREEPARSER_TESTS_OBJECTTREEPARSERTEST_H #define MIMETREEPARSER_TESTS_OBJECTTREEPARSERTEST_H #include class ObjectTreeParserTest : public QObject { Q_OBJECT private Q_SLOTS: void initTestCase(); void testMailWithoutEncryption(); void testSMIMESignedEncrypted(); void testOpenPGPSignedEncrypted(); void testOpenPGPEncryptedAndSigned(); void testForwardedOpenPGPSignedEncrypted(); void testSignedForwardedOpenPGPSignedEncrypted(); void testOpenPGPEncrypted(); void testOpenPGPEncryptedNotDecrypted(); void testAsync_data(); void testAsync(); + void testHtmlContent_data(); + void testHtmlContent(); }; #endif // MIMETREEPARSER_TESTS_OBJECTTREEPARSERTEST_H diff --git a/mimetreeparser/autotests/data/html-attachment1.mbox b/mimetreeparser/autotests/data/html-attachment1.mbox new file mode 100644 index 00000000..805030e5 --- /dev/null +++ b/mimetreeparser/autotests/data/html-attachment1.mbox @@ -0,0 +1,84 @@ +Return-path: +Envelope-to: gunter@ohrner.net +Delivery-date: Mon, 12 Sep 2016 13:38:39 +0200 +Received: from mail.from example.com ([178.251.88.150]) + by luggage.ohrner.net with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:256) + (Exim 4.80) + (envelope-from ) + id 1bjPYi-0000oA-Re + for gunter@ohrner.net; Mon, 12 Sep 2016 13:38:39 +0200 +Received: from example.com.local (172.17.124.205) by from example.com.local + (172.17.124.1) with Microsoft SMTP Server id 14.3.266.1; Mon, 12 Sep 2016 + 13:37:53 +0200 +From: +To: +Message-ID: <8614416.18.1473680273823.JavaMail.sender@example.com> +MIME-Version: 1.0 +Content-Type: multipart/mixed; + boundary="----=_Part_16_9312243.1473680273820" +Date: Mon, 12 Sep 2016 13:37:53 +0200 +X-TM-AS-Product-Ver: SMEX-11.1.0.1278-8.000.1202-22570.004 +X-TM-AS-Result: No--23.664000-5.000000-31 +X-TM-AS-User-Approved-Sender: No +X-TM-AS-User-Blocked-Sender: No +Subject: A Subject Line + +------=_Part_16_9312243.1473680273820 +Content-Type: text/html; charset="utf-8" +Content-Transfer-Encoding: 8bit + +

A Body Text

+------=_Part_16_9312243.1473680273820 +Content-Type: application/octet-stream; + name="Attachment1.pdf" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment + +JVBERi0xLjEKJeLjz9MKMSAwIG9iaiAKPDwKL1R5cGUgL0NhdGFsb2cKL1BhZ2VzIDIgMCBSCj4+ +CmVuZG9iaiAKMiAwIG9iaiAKPDwKL0tpZHMgWzMgMCBSXQovVHlwZSAvUGFnZXMKL01lZGlhQm94 +IFswIDAgMzAwIDE0NF0KL0NvdW50IDEKPj4KZW5kb2JqIAozIDAgb2JqIAo8PAovUmVzb3VyY2Vz +IAo8PAovRm9udCAKPDwKL0YxIAo8PAovU3VidHlwZSAvVHlwZTEKL1R5cGUgL0ZvbnQKL0Jhc2VG +b250IC9UaW1lcy1Sb21hbgo+Pgo+Pgo+PgovQ29udGVudHMgNCAwIFIKL1BhcmVudCAyIDAgUgov +VHlwZSAvUGFnZQovTWVkaWFCb3ggWzAgMCAzMDAgMTQ0XQo+PgplbmRvYmogCjQgMCBvYmogCjw8 +Ci9GaWx0ZXIgL0ZsYXRlRGVjb2RlCi9MZW5ndGggNTIKPj4Kc3RyZWFtCnicU1BwCuFSAAJ9N0MF +QwuFkDQwzwAIQ1LATA2P1JycfIXw/KKcFE2FkCygoGsIACsbDAQKZW5kc3RyZWFtIAplbmRvYmog +eHJlZgowIDUKMDAwMDAwMDAwMCA2NTUzNSBmIAowMDAwMDAwMDE1IDAwMDAwIG4gCjAwMDAwMDAw +NjYgMDAwMDAgbiAKMDAwMDAwMDE0OSAwMDAwMCBuIAowMDAwMDAwMzMxIDAwMDAwIG4gCnRyYWls +ZXIKCjw8Ci9Sb290IDEgMCBSCi9TaXplIDUKPj4Kc3RhcnR4cmVmCjQ1NgolJUVPRgo= + +------=_Part_16_9312243.1473680273820 +Content-Type: application/octet-stream; name="Attachment2.pdf" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment + +JVBERi0xLjEKJeLjz9MKMSAwIG9iaiAKPDwKL1R5cGUgL0NhdGFsb2cKL1BhZ2VzIDIgMCBSCj4+ +CmVuZG9iaiAKMiAwIG9iaiAKPDwKL0tpZHMgWzMgMCBSXQovVHlwZSAvUGFnZXMKL01lZGlhQm94 +IFswIDAgMzAwIDE0NF0KL0NvdW50IDEKPj4KZW5kb2JqIAozIDAgb2JqIAo8PAovUmVzb3VyY2Vz +IAo8PAovRm9udCAKPDwKL0YxIAo8PAovU3VidHlwZSAvVHlwZTEKL1R5cGUgL0ZvbnQKL0Jhc2VG +b250IC9UaW1lcy1Sb21hbgo+Pgo+Pgo+PgovQ29udGVudHMgNCAwIFIKL1BhcmVudCAyIDAgUgov +VHlwZSAvUGFnZQovTWVkaWFCb3ggWzAgMCAzMDAgMTQ0XQo+PgplbmRvYmogCjQgMCBvYmogCjw8 +Ci9GaWx0ZXIgL0ZsYXRlRGVjb2RlCi9MZW5ndGggNTIKPj4Kc3RyZWFtCnicU1BwCuFSAAJ9N0MF +QwuFkDQwzwAIQ1LATA2P1JycfIXw/KKcFE2FkCygoGsIACsbDAQKZW5kc3RyZWFtIAplbmRvYmog +eHJlZgowIDUKMDAwMDAwMDAwMCA2NTUzNSBmIAowMDAwMDAwMDE1IDAwMDAwIG4gCjAwMDAwMDAw +NjYgMDAwMDAgbiAKMDAwMDAwMDE0OSAwMDAwMCBuIAowMDAwMDAwMzMxIDAwMDAwIG4gCnRyYWls +ZXIKCjw8Ci9Sb290IDEgMCBSCi9TaXplIDUKPj4Kc3RhcnR4cmVmCjQ1NgolJUVPRgo= + +------=_Part_16_9312243.1473680273820 +Content-Type: application/octet-stream; name="Attachment3.pdf" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment + +JVBERi0xLjEKJeLjz9MKMSAwIG9iaiAKPDwKL1R5cGUgL0NhdGFsb2cKL1BhZ2VzIDIgMCBSCj4+ +CmVuZG9iaiAKMiAwIG9iaiAKPDwKL0tpZHMgWzMgMCBSXQovVHlwZSAvUGFnZXMKL01lZGlhQm94 +IFswIDAgMzAwIDE0NF0KL0NvdW50IDEKPj4KZW5kb2JqIAozIDAgb2JqIAo8PAovUmVzb3VyY2Vz +IAo8PAovRm9udCAKPDwKL0YxIAo8PAovU3VidHlwZSAvVHlwZTEKL1R5cGUgL0ZvbnQKL0Jhc2VG +b250IC9UaW1lcy1Sb21hbgo+Pgo+Pgo+PgovQ29udGVudHMgNCAwIFIKL1BhcmVudCAyIDAgUgov +VHlwZSAvUGFnZQovTWVkaWFCb3ggWzAgMCAzMDAgMTQ0XQo+PgplbmRvYmogCjQgMCBvYmogCjw8 +Ci9GaWx0ZXIgL0ZsYXRlRGVjb2RlCi9MZW5ndGggNTIKPj4Kc3RyZWFtCnicU1BwCuFSAAJ9N0MF +QwuFkDQwzwAIQ1LATA2P1JycfIXw/KKcFE2FkCygoGsIACsbDAQKZW5kc3RyZWFtIAplbmRvYmog +eHJlZgowIDUKMDAwMDAwMDAwMCA2NTUzNSBmIAowMDAwMDAwMDE1IDAwMDAwIG4gCjAwMDAwMDAw +NjYgMDAwMDAgbiAKMDAwMDAwMDE0OSAwMDAwMCBuIAowMDAwMDAwMzMxIDAwMDAwIG4gCnRyYWls +ZXIKCjw8Ci9Sb290IDEgMCBSCi9TaXplIDUKPj4Kc3RhcnR4cmVmCjQ1NgolJUVPRgo= + +------=_Part_16_9312243.1473680273820-- + diff --git a/mimetreeparser/autotests/data/html-attachment2.mbox b/mimetreeparser/autotests/data/html-attachment2.mbox new file mode 100644 index 00000000..04723637 --- /dev/null +++ b/mimetreeparser/autotests/data/html-attachment2.mbox @@ -0,0 +1,30 @@ +From maillists@whattf.com Tue Jul 05 19:20:58 2011 +Return-path: +Envelope-to: maillists@whattf.com +Date: Mon, 24 Oct 2016 11:53:00 +0100 +To: maillists@whattf.com +From: maillists@whattf.com +MIME-Version: 1.0 +Subject: Test +Content-Type: multipart/related; boundary="----=_Part_20324_1054669183.1477306380301" +MIME-Version: 1.0 + +------=_Part_20324_1054669183.1477306380301 +Content-Type: text/html; charset="UTF-8" +Content-Transfer-Encoding: 7bit + +HTML Text +------=_Part_20324_1054669183.1477306380301 +Content-Type: image/png +Content-Disposition: attachment; filename="image1.png" +Content-ID: cid1 + +Image1 +------=_Part_20324_1054669183.1477306380301 +Content-Type: image/png +Content-Disposition: attachment; filename="image2.png" +Content-ID: cid2 + +Image2 +------=_Part_20324_1054669183.1477306380301-- +