File indexing completed on 2024-04-28 09:12:07
0001 /* 0002 SPDX-FileCopyrightText: 2007 Volker Krause <vkrause@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "messagetest.h" 0008 #include <QTest> 0009 #include <QDebug> 0010 #include <QFile> 0011 #include <kmime_codecs.cpp> 0012 0013 using namespace KMime; 0014 0015 QTEST_MAIN(MessageTest) 0016 0017 void MessageTest::testMainBodyPart() 0018 { 0019 auto msg = new Message(); 0020 auto msg2 = new Message(); 0021 auto text = new Content(); 0022 text->contentType()->setMimeType("text/plain"); 0023 auto html = new Content(); 0024 html->contentType()->setMimeType("text/html"); 0025 0026 // empty message 0027 QCOMPARE(msg->mainBodyPart(), msg); 0028 QCOMPARE(msg->mainBodyPart("text/plain"), (Content *)nullptr); 0029 0030 // non-multipart 0031 msg->contentType()->setMimeType("text/html"); 0032 0033 QCOMPARE(msg->mainBodyPart(), msg); 0034 QCOMPARE(msg->mainBodyPart("text/plain"), (Content *)nullptr); 0035 QCOMPARE(msg->mainBodyPart("text/html"), msg); 0036 0037 // multipart/mixed 0038 msg2->contentType()->setMimeType("multipart/mixed"); 0039 msg2->appendContent(text); 0040 msg2->appendContent(html); 0041 0042 QCOMPARE(msg2->mainBodyPart(), text); 0043 QCOMPARE(msg2->mainBodyPart("text/plain"), text); 0044 QCOMPARE(msg2->mainBodyPart("text/html"), (Content *)nullptr); 0045 0046 // Careful with removing content here. If we remove one of the two contents 0047 // (by adding it to another message), the multipart will automatically be 0048 // converted to a single-part, deleting the other content! 0049 msg2->clearContents(false); 0050 0051 // multipart/alternative 0052 msg->contentType()->setMimeType("multipart/alternative"); 0053 msg->appendContent(html); 0054 msg->appendContent(text); 0055 0056 QCOMPARE(msg->mainBodyPart(), html); 0057 QCOMPARE(msg->mainBodyPart("text/plain"), text); 0058 QCOMPARE(msg->mainBodyPart("text/html"), html); 0059 0060 // multipart/alternative inside multipart/mixed 0061 auto msg3 = new Message(); 0062 msg3->contentType()->setMimeType("multipart/mixed"); 0063 msg3->appendContent(msg); 0064 auto attach = new Content(); 0065 attach->contentType()->setMimeType("text/plain"); 0066 0067 QCOMPARE(msg3->mainBodyPart(), html); 0068 QCOMPARE(msg3->mainBodyPart("text/plain"), text); 0069 QCOMPARE(msg3->mainBodyPart("text/html"), html); 0070 0071 delete msg2; 0072 delete msg3; 0073 delete attach; 0074 } 0075 0076 void MessageTest::testBrunosMultiAssembleBug() 0077 { 0078 QByteArray data = 0079 "From: Sender <sender@test.org>\n" 0080 "Subject: Sample message\n" 0081 "To: Receiver <receiver@test.org>\n" 0082 "Date: Sat, 04 Aug 2007 12:44:00 +0200\n" 0083 "MIME-Version: 1.0\n" 0084 "Content-Type: text/plain\n" 0085 "X-Foo: bla\n" 0086 "X-Bla: foo\n" 0087 "\n" 0088 "body"; 0089 0090 auto msg = new Message; 0091 msg->setContent(data); 0092 msg->parse(); 0093 msg->assemble(); 0094 QCOMPARE(msg->encodedContent(), data); 0095 0096 msg->inReplyTo(); 0097 msg->assemble(); 0098 QCOMPARE(msg->encodedContent(), data); 0099 0100 delete msg; 0101 } 0102 0103 void MessageTest::testWillsAndTillsCrash() 0104 { 0105 QByteArray deadlyMail = "From: censored@yahoogroups.com\n" 0106 "To: censored@yahoogroups.com\n" 0107 "Sender: censored@yahoogroups.com\n" 0108 "MIME-Version: 1.0\n" 0109 "Date: 29 Jan 2006 23:58:21 -0000\n" 0110 "Subject: [censored] Birthday Reminder\n" 0111 "Reply-To: censored@yahoogroups.com\n" 0112 "Content-Type: multipart/alternative;\n boundary=\"YCalReminder=cNM4SNTGA4Cg1MVLaPpqNF1138579098\"\n" 0113 "X-Length: 9594\n" 0114 "X-UID: 6161\n" 0115 "Status: RO\n" 0116 "X-Status: OC\n" 0117 "X-KMail-EncryptionState:\n" 0118 "X-KMail-SignatureState:\n" 0119 "X-KMail-MDN-Sent:\n\n"; 0120 0121 auto msg = new KMime::Message; 0122 msg->setContent(deadlyMail); 0123 msg->parse(); 0124 QVERIFY(!msg->date()->isEmpty()); 0125 QCOMPARE(msg->subject()->as7BitString(false), QByteArray("[censored] Birthday Reminder")); 0126 QCOMPARE(msg->from()->mailboxes().count(), 1); 0127 QCOMPARE(msg->sender()->mailboxes().count(), 1); 0128 QCOMPARE(msg->replyTo()->mailboxes().count(), 1); 0129 QCOMPARE(msg->to()->mailboxes().count(), 1); 0130 QCOMPARE(msg->cc()->mailboxes().count(), 0); 0131 QCOMPARE(msg->bcc()->mailboxes().count(), 0); 0132 QCOMPARE(msg->inReplyTo()->identifiers().count(), 0); 0133 QCOMPARE(msg->messageID()->identifiers().count(), 0); 0134 delete msg; 0135 } 0136 0137 void MessageTest::testDavidsParseCrash() 0138 { 0139 KMime::Message::Ptr mail = readAndParseMail(QStringLiteral("dfaure-crash.mbox")); 0140 QCOMPARE(mail->to()->asUnicodeString().toLatin1().data(), "frank@domain.com"); 0141 } 0142 0143 void MessageTest::testHeaderFieldWithoutSpace() 0144 { 0145 // Headers without a space, like the CC header here, are allowed according to 0146 // the examples in RFC2822, Appendix A5 0147 const QString mail = QStringLiteral("From:\n" 0148 "To: heinz@test.de\n" 0149 "Cc:moritz@test.de\n" 0150 "Subject: Test\n" 0151 "X-Mailer:"); 0152 KMime::Message msg; 0153 msg.setContent(mail.toLatin1()); 0154 msg.parse(); 0155 0156 QCOMPARE(msg.to()->asUnicodeString(), QLatin1String("heinz@test.de")); 0157 QCOMPARE(msg.from()->asUnicodeString(), QString()); 0158 QCOMPARE(msg.cc()->asUnicodeString(), QLatin1String("moritz@test.de")); 0159 QCOMPARE(msg.subject()->asUnicodeString(), QLatin1String("Test")); 0160 QVERIFY(msg.hasHeader("X-Mailer")); 0161 QVERIFY(msg.headerByType("X-Mailer")->asUnicodeString().isEmpty()); 0162 } 0163 0164 void MessageTest::testWronglyFoldedHeaders() 0165 { 0166 // The first subject line here doesn't contain anything. This is invalid, 0167 // however there are some mailers out there that produce those messages. 0168 const QString mail = QStringLiteral("Subject:\n" 0169 " Hello\n" 0170 " World\n" 0171 "To: \n" 0172 " test@test.de\n\n" 0173 "<Body>"); 0174 KMime::Message msg; 0175 msg.setContent(mail.toLatin1()); 0176 msg.parse(); 0177 0178 QCOMPARE(msg.subject()->asUnicodeString(), QLatin1String("Hello World")); 0179 QCOMPARE(msg.body().data(), "<Body>"); 0180 QCOMPARE(msg.to()->asUnicodeString(), QLatin1String("test@test.de")); 0181 } 0182 0183 void MessageTest::missingHeadersTest() 0184 { 0185 // Test that the message body is OK even though some headers are missing 0186 KMime::Message msg; 0187 const QString body = QStringLiteral("Hi Donald, look at those nice pictures I found!\n"); 0188 const QString content = QLatin1String("From: georgebush@whitehouse.org\n" 0189 "To: donaldrumsfeld@whitehouse.org\n" 0190 "Subject: Cute Kittens\n" 0191 "\n") + body; 0192 msg.setContent(content.toLatin1()); 0193 msg.parse(); 0194 msg.assemble(); 0195 0196 QCOMPARE(body, QString::fromLatin1(msg.body())); 0197 0198 // Now create a new message, based on the content of the first one. 0199 // The body of the new message should still be the same. 0200 // (there was a bug that caused missing mandatory headers to be 0201 // added as a empty newline, which caused parts of the header to 0202 // leak into the body) 0203 KMime::Message msg2; 0204 msg2.setContent(msg.encodedContent()); 0205 msg2.parse(); 0206 msg2.assemble(); 0207 0208 QCOMPARE(body, QString::fromLatin1(msg2.body())); 0209 } 0210 0211 void MessageTest::testBug219749() 0212 { 0213 // Test that the message body is OK even though some headers are missing 0214 KMime::Message msg; 0215 const QString content = QStringLiteral( 0216 "Content-Type: MULTIPART/MIXED;\n" 0217 " BOUNDARY=\"0-1804289383-1260384639=:52580\"\n" 0218 "\n" 0219 "--0-1804289383-1260384639=:52580\n" 0220 "Content-Type: TEXT/plain; CHARSET=UTF-8\n" 0221 "\n" 0222 "--0-1804289383-1260384639=:52580\n" 0223 "Content-Type: APPLICATION/octet-stream\n" 0224 "Content-Transfer-Encoding: BASE64\n" 0225 "Content-ID: <jaselka1.docx4AECA1F9@9230725.3CDBB752>\n" 0226 "Content-Disposition: ATTACHMENT; FILENAME=\"jaselka 1.docx\"\n" 0227 "\n" 0228 "UEsDBBQABgAIAAAAIQDd/JU3ZgEAACAFAAATAAgCW0NvbnRlbnRfVHlwZXNd\n" 0229 "SUwAAAAA\n" 0230 "\n" 0231 "--0-1804289383-1260384639=:52580--\n"); 0232 0233 msg.setContent(content.toLatin1()); 0234 msg.parse(); 0235 0236 QCOMPARE(msg.contents().size(), 2); 0237 KMime::Content *attachment = msg.contents()[1]; 0238 QCOMPARE(attachment->contentType(false)->mediaType().data(), "application"); 0239 QCOMPARE(attachment->contentType(false)->subType().data(), "octet-stream"); 0240 QCOMPARE(attachment->contentID()->identifier().data(), "jaselka1.docx4AECA1F9@9230725.3CDBB752"); 0241 QCOMPARE(attachment->contentID()->as7BitString(false).data(), "<jaselka1.docx4AECA1F9@9230725.3CDBB752>"); 0242 Headers::ContentDisposition *cd = attachment->contentDisposition(false); 0243 QVERIFY(cd); 0244 QCOMPARE(cd->filename(), QLatin1String("jaselka 1.docx")); 0245 } 0246 0247 void MessageTest::testBidiSpoofing() 0248 { 0249 const QString RLO(QChar(0x202E)); 0250 //const QString PDF( QChar( 0x202C ) ); 0251 0252 const QByteArray senderAndRLO = 0253 encodeRFC2047String(QString(QLatin1String("Sender") + RLO + QLatin1String(" <sender@test.org>")), "utf-8"); 0254 0255 // The display name of the "From" has an RLO, make sure the KMime parser balances it 0256 QByteArray data = 0257 "From: " + senderAndRLO + "\n" 0258 "\n" 0259 "Body"; 0260 0261 KMime::Message msg; 0262 msg.setContent(data); 0263 msg.parse(); 0264 0265 // Test adjusted for taking into account that KMIME now removes bidi control chars 0266 // instead of adding PDF chars, because of broken KHTML. 0267 //const QString expectedDisplayName = "\"Sender" + RLO + PDF + "\""; 0268 const QString expectedDisplayName = QStringLiteral("Sender"); 0269 const QString expectedMailbox = expectedDisplayName + QLatin1String(" <sender@test.org>"); 0270 QCOMPARE(msg.from()->addresses().count(), 1); 0271 QCOMPARE(msg.from()->asUnicodeString(), expectedMailbox); 0272 QCOMPARE(msg.from()->displayNames().first(), expectedDisplayName); 0273 QCOMPARE(msg.from()->mailboxes().first().name(), expectedDisplayName); 0274 QCOMPARE(msg.from()->mailboxes().first().address().data(), "sender@test.org"); 0275 } 0276 0277 // Test to see if header fields of mails with an UTF-16 body are properly read 0278 // and written. 0279 // See also https://issues.kolab.org/issue3707 0280 void MessageTest::testUtf16() 0281 { 0282 QByteArray data = 0283 "From: foo@bar.com\n" 0284 "Subject: UTF-16 Test\n" 0285 "MIME-Version: 1.0\n" 0286 "Content-Type: Text/Plain;\n" 0287 " charset=\"utf-16\"\n" 0288 "Content-Transfer-Encoding: base64\n" 0289 "\n" 0290 "//5UAGgAaQBzACAAaQBzACAAVQBUAEYALQAxADYAIABUAGUAeAB0AC4ACgAKAAo"; 0291 0292 KMime::Message msg; 0293 msg.setContent(data); 0294 msg.parse(); 0295 0296 QCOMPARE(msg.from()->asUnicodeString(), QLatin1String("foo@bar.com")); 0297 QCOMPARE(msg.subject()->asUnicodeString(), QLatin1String("UTF-16 Test")); 0298 QCOMPARE(msg.decodedText(false, true), QLatin1String("This is UTF-16 Text.")); 0299 0300 // Add a new To header, for testings 0301 auto to = new KMime::Headers::To; 0302 KMime::Types::Mailbox address; 0303 address.setAddress("test@test.de"); 0304 address.setName(QStringLiteral("Fränz Töster")); 0305 to->addAddress(address); 0306 to->setRFC2047Charset("ISO-8859-1"); // default changed to UTF-8 in KF6, which is fine, but breaks the test 0307 msg.appendHeader(to); 0308 msg.assemble(); 0309 0310 QByteArray newData = 0311 "From: foo@bar.com\n" 0312 "Subject: UTF-16 Test\n" 0313 "MIME-Version: 1.0\n" 0314 "Content-Type: text/plain; charset=\"utf-16\"\n" 0315 "Content-Transfer-Encoding: base64\n" 0316 "To: =?ISO-8859-1?Q?Fr=E4nz_T=F6ster?= <test@test.de>\n" 0317 "\n" 0318 "//5UAGgAaQBzACAAaQBzACAAVQBUAEYALQAxADYAIABUAGUAeAB0AC4ACgAKAAo=\n" 0319 "\n"; 0320 0321 QCOMPARE(msg.encodedContent().data(), newData.data()); 0322 } 0323 0324 void MessageTest::testDecodedText() 0325 { 0326 QByteArray data = 0327 "Subject: Test\n" 0328 "\n" 0329 "Testing Whitespace \n \n \n\n\n"; 0330 0331 KMime::Message msg; 0332 msg.setContent(data); 0333 msg.parse(); 0334 0335 QCOMPARE(msg.decodedText(true, false), QLatin1String("Testing Whitespace")); 0336 QCOMPARE(msg.decodedText(true, true), QLatin1String("Testing Whitespace")); 0337 QCOMPARE(msg.decodedText(false, true), QLatin1String("Testing Whitespace \n \n ")); 0338 0339 QByteArray data2 = 0340 "Subject: Test\n" 0341 "\n" 0342 "Testing Whitespace \n \n \n\n\n "; 0343 0344 KMime::Message msg2; 0345 msg2.setContent(data2); 0346 msg2.parse(); 0347 0348 QCOMPARE(msg2.decodedText(true, false), QLatin1String("Testing Whitespace")); 0349 QCOMPARE(msg2.decodedText(true, true), QLatin1String("Testing Whitespace")); 0350 QCOMPARE(msg2.decodedText(false, true), QLatin1String("Testing Whitespace \n \n \n\n\n ")); 0351 } 0352 0353 void MessageTest::testInlineImages() 0354 { 0355 const QByteArray data = 0356 "From: <kde@kde.org>\n" 0357 "To: kde@kde.org\n" 0358 "Subject: Inline Image (unsigned)\n" 0359 "Date: Wed, 23 Dec 2009 14:00:59 +0100\n" 0360 "MIME-Version: 1.0\n" 0361 "Content-Type: multipart/related;\n" 0362 " boundary=\"Boundary-02=_LShMLJyjC7zqmVP\"\n" 0363 "Content-Transfer-Encoding: 7bit\n" 0364 "\n" 0365 "\n" 0366 "--Boundary-02=_LShMLJyjC7zqmVP\n" 0367 "Content-Type: multipart/alternative;\n" 0368 " boundary=\"Boundary-01=_LShMLzAUPqE38S8\"\n" 0369 "Content-Transfer-Encoding: 7bit\n" 0370 "Content-Disposition: inline\n" 0371 "\n" 0372 "--Boundary-01=_LShMLzAUPqE38S8\n" 0373 "Content-Type: text/plain;\n" 0374 " charset=\"us-ascii\"\n" 0375 "Content-Transfer-Encoding: 7bit\n" 0376 "\n" 0377 "First line\n" 0378 "\n" 0379 "\n" 0380 "Image above\n" 0381 "\n" 0382 "Last line\n" 0383 "\n" 0384 "--Boundary-01=_LShMLzAUPqE38S8\n" 0385 "Content-Type: text/html;\n" 0386 " charset=\"us-ascii\"\n" 0387 "Content-Transfer-Encoding: 7bit\n" 0388 "\n" 0389 "Line 1\n" 0390 "--Boundary-01=_LShMLzAUPqE38S8--\n" 0391 "\n" 0392 "--Boundary-02=_LShMLJyjC7zqmVP\n" 0393 "Content-Type: image/png;\n" 0394 " name=\"inlineimage.png\"\n" 0395 "Content-Transfer-Encoding: base64\n" 0396 "Content-Id: <740439759>\n" 0397 "\n" 0398 "jxrG/ha/VB+rODav6/d5i1US6Za/YEMvtm2SgJC/CXVFiD3UFSH2UFeE2ENdEWIPdUWIPdQVIfZQ\n" 0399 "V4TYQ10RYg91RYg91BUh9lBXhNhDXRFiD3VFiD3UFSH2UFeE2ENdEWIPdUWIPdQVIfZQV4TYQ10R\n" 0400 "Yg91RYg91BUh9lBX5E+Tz6Vty1HSx+NR++UuCOqKEHv+Ax0Y5U59+AHBAAAAAElFTkSuQmCC\n" 0401 "\n" 0402 "--Boundary-02=_LShMLJyjC7zqmVP--"; 0403 0404 KMime::Message msg; 0405 msg.setContent(data); 0406 msg.parse(); 0407 0408 QCOMPARE(msg.contents().size(), 2); 0409 QCOMPARE(msg.contents()[0]->contentType()->isMultipart(), true); 0410 QCOMPARE(msg.contents()[0]->contentType()->subType().data(), "alternative"); 0411 0412 QCOMPARE(msg.contents()[1]->contentType()->isImage(), true); 0413 QCOMPARE(msg.contents()[1]->contentType()->name(), QLatin1String("inlineimage.png")); 0414 QCOMPARE(msg.contents()[1]->contentID()->identifier().data(), "740439759"); 0415 QCOMPARE(msg.contents()[1]->contentID()->as7BitString(false).data(), "<740439759>"); 0416 } 0417 0418 void MessageTest::testIssue3908() 0419 { 0420 KMime::Message::Ptr msg = readAndParseMail(QStringLiteral("issue3908.mbox")); 0421 QCOMPARE(msg->contents().size(), 2); 0422 KMime::Content *attachment = msg->contents().at(1); 0423 QVERIFY(attachment); 0424 QVERIFY(attachment->contentDescription(false)); 0425 QCOMPARE(attachment->contentDescription()->asUnicodeString(), QString::fromUtf8( 0426 "Kontact oder auch KDE-PIM ist der Groupware-Client aus der KDE Software Compilation 4.Eine der Besonderheiten von Kontact " 0427 "gegenüber anderen Groupware-Clients ist, dass die Teil-Programme auch weiterhin unabhängig von Kontact gestartet werden " 0428 "können. So spielt es zum Beispiel keine Rolle für das Arbeiten mit KMail, ob es mal allein oder mal im Rahmen von Kontact " 0429 "gestartet wird: Die Mails und die persönlichen Einstellungen bleiben stets erhalten.Auch sieht Kontact eine modulare " 0430 "Anbindung der Programme vor, wodurch sich auch in Zukunft weitere Module entwickeln und anfügen lassen, ohne Kontact " 0431 "dafür zu ändern. Dies bietet die Möglichkeit, auch privat entwickelte Module einzubinden und so die Groupware grundlegend " 0432 "eigenen Bedürfnissen anzupassen.")); 0433 } 0434 0435 void MessageTest::testIssue3914() 0436 { 0437 // This loads a mail which has a content-disposition of which the filename parameter is empty. 0438 // Check that the parser doesn't choke on this. 0439 KMime::Message::Ptr msg = readAndParseMail(QStringLiteral("broken-content-disposition.mbox")); 0440 0441 QCOMPARE(msg->subject()->as7BitString().data(), "Subject: Fwd: test broken mail"); 0442 QCOMPARE(msg->contents().size(), 2); 0443 KMime::Content *attachedMail = msg->contents().at(1); 0444 QCOMPARE(attachedMail->contentType()->mimeType().data(), "message/rfc822"); 0445 QVERIFY(attachedMail->contentDisposition(false)); 0446 QVERIFY(attachedMail->contentDisposition()->hasParameter(QLatin1String("filename"))); 0447 QVERIFY(attachedMail->contentDisposition()->parameter(QLatin1String("filename")).isEmpty()); 0448 } 0449 0450 void MessageTest::testBug223509() 0451 { 0452 KMime::Message::Ptr msg = readAndParseMail(QStringLiteral("encoding-crash.mbox")); 0453 0454 QCOMPARE(msg->subject()->as7BitString().data(), "Subject: Blub"); 0455 QCOMPARE(msg->contents().size(), 0); 0456 QCOMPARE(msg->contentTransferEncoding()->encoding(), KMime::Headers::CEbinary); 0457 QCOMPARE(msg->decodedText().toLatin1().data(), "Bla Bla Bla"); 0458 QCOMPARE(msg->encodedBody().data(), "Bla Bla Bla\n"); 0459 0460 // encodedContent() was crashing in this bug because of an invalid assert 0461 QVERIFY(!msg->encodedContent().isEmpty()); 0462 0463 // Make sure that the encodedContent() is sane, by parsing it again. 0464 KMime::Message msg2; 0465 msg2.setContent(msg->encodedContent()); 0466 msg2.parse(); 0467 QCOMPARE(msg2.subject()->as7BitString().data(), "Subject: Blub"); 0468 QCOMPARE(msg2.contents().size(), 0); 0469 QCOMPARE(msg2.contentTransferEncoding()->encoding(), KMime::Headers::CEbinary); 0470 0471 QCOMPARE(msg2.decodedText().toLatin1().data(), "Bla Bla Bla"); 0472 QCOMPARE(msg2.decodedText(true, true /* remove newlines at end */).toLatin1().data(), 0473 "Bla Bla Bla"); 0474 } 0475 0476 void MessageTest::testEncapsulatedMessages() 0477 { 0478 // 0479 // First, test some basic properties to check that the parsing was correct 0480 // 0481 KMime::Message::Ptr msg = readAndParseMail(QStringLiteral("simple-encapsulated.mbox")); 0482 QCOMPARE(msg->contentType()->mimeType().data(), "multipart/mixed"); 0483 QCOMPARE(msg->contents().size(), 2); 0484 QVERIFY(msg->isTopLevel()); 0485 0486 KMime::Content *const textContent = msg->contents().at(0); 0487 QCOMPARE(textContent->contentType()->mimeType().data(), "text/plain"); 0488 QVERIFY(textContent->contents().isEmpty()); 0489 QVERIFY(!textContent->bodyIsMessage()); 0490 QVERIFY(!textContent->bodyAsMessage()); 0491 QVERIFY(!textContent->isTopLevel()); 0492 QCOMPARE(textContent->decodedText(true, true), 0493 QLatin1String("Hi Hans!\nLook at this interesting mail I forwarded to you!")); 0494 QCOMPARE(textContent->index().toString().toLatin1().data(), "1"); 0495 0496 KMime::Content *messageContent = msg->contents().at(1); 0497 QCOMPARE(messageContent->contentType()->mimeType().data(), "message/rfc822"); 0498 QVERIFY(messageContent->body().isEmpty()); 0499 QCOMPARE(messageContent->contents().count(), 1); 0500 QVERIFY(messageContent->bodyIsMessage()); 0501 QVERIFY(messageContent->bodyAsMessage().data()); 0502 QVERIFY(!messageContent->isTopLevel()); 0503 QCOMPARE(messageContent->index().toString().toLatin1().data(), "2"); 0504 0505 KMime::Message::Ptr encapsulated = messageContent->bodyAsMessage(); 0506 QCOMPARE(encapsulated->contents().size(), 0); 0507 QCOMPARE(encapsulated->contentType()->mimeType().data(), "text/plain"); 0508 QVERIFY(!encapsulated->bodyIsMessage()); 0509 QVERIFY(!encapsulated->bodyAsMessage()); 0510 QCOMPARE(encapsulated->subject()->as7BitString(false).data(), "Foo"); 0511 QCOMPARE(encapsulated->decodedText(false, false), 0512 QLatin1String("This is the encapsulated message body.")); 0513 QCOMPARE(encapsulated.data(), messageContent->bodyAsMessage().data()); 0514 QCOMPARE(encapsulated.data(), messageContent->contents().constFirst()); 0515 QCOMPARE(encapsulated->parent(), messageContent); 0516 QVERIFY(!encapsulated->isTopLevel()); 0517 QCOMPARE(encapsulated->topLevel(), msg.data()); 0518 QCOMPARE(encapsulated->index().toString().toLatin1().data(), "2.1"); 0519 0520 // Now test some misc functions 0521 QCOMPARE(msg->storageSize(), msg->head().size() + textContent->storageSize() + 0522 messageContent->storageSize()); 0523 QCOMPARE(messageContent->storageSize(), messageContent->head().size() + 0524 encapsulated->storageSize()); 0525 0526 // Now change some properties on the encapsulated message 0527 encapsulated->subject()->fromUnicodeString(QStringLiteral("New subject"), "us-ascii"); 0528 encapsulated->fromUnicodeString(QStringLiteral("New body string.")); 0529 0530 // Since we didn't assemble the encapsulated message yet, it should still have the old headers 0531 QVERIFY(encapsulated->encodedContent().contains("Foo")); 0532 QVERIFY(!encapsulated->encodedContent().contains("New subject")); 0533 0534 // Now assemble the container message 0535 msg->assemble(); 0536 0537 // Assembling the container message should have assembled the encapsulated message as well. 0538 QVERIFY(!encapsulated->encodedContent().contains("Foo")); 0539 QVERIFY(encapsulated->encodedContent().contains("New subject")); 0540 QCOMPARE(encapsulated->body().data(), "New body string."); 0541 QVERIFY(msg->encodedContent().contains(encapsulated->body())); 0542 QCOMPARE(msg->contentType()->mimeType().data(), "multipart/mixed"); 0543 QCOMPARE(msg->contents().size(), 2); 0544 messageContent = msg->contents().at(1); 0545 QCOMPARE(messageContent->contentType()->mimeType().data(), "message/rfc822"); 0546 QVERIFY(encapsulated.data() == messageContent->bodyAsMessage().data()); 0547 0548 // Setting a new body and then parsing it should discard the encapsulated message 0549 messageContent->contentType()->setMimeType("text/plain"); 0550 messageContent->assemble(); 0551 messageContent->setBody("Some new body"); 0552 messageContent->parse(); 0553 QVERIFY(!messageContent->bodyIsMessage()); 0554 QVERIFY(!messageContent->bodyAsMessage()); 0555 QCOMPARE(messageContent->contents().size(), 0); 0556 } 0557 0558 void MessageTest::testOutlookAttachmentNaming() 0559 { 0560 // Try and decode 0561 KMime::Message::Ptr msg = readAndParseMail(QStringLiteral("outlook-attachment.mbox")); 0562 QVERIFY(msg->attachments().count() == 1); 0563 0564 KMime::Content *attachment = msg->contents()[1]; 0565 QCOMPARE(attachment->contentType(false)->mediaType().data(), "text"); 0566 QCOMPARE(attachment->contentType(false)->subType().data(), "x-patch"); 0567 0568 Headers::ContentDisposition *cd = attachment->contentDisposition(false); 0569 QVERIFY(cd); 0570 QCOMPARE(cd->filename(), QString::fromUtf8("å.diff")); 0571 0572 // Try and encode 0573 attachment->clear();// = new Content(); 0574 attachment->contentDisposition()->setDisposition(Headers::CDattachment); 0575 attachment->contentDisposition()->setFilename(QStringLiteral("å.diff")); 0576 attachment->contentDisposition()->setRFC2047Charset("ISO-8859-1"); // default changed to UTF-8 in KF6, which is fine, but breaks the test 0577 attachment->assemble(); 0578 qDebug() << "got:" << attachment->contentDisposition()->as7BitString(false); 0579 QCOMPARE(attachment->contentDisposition()->as7BitString(false), QByteArray("attachment; filename*=ISO-8859-1''%E5%2Ediff")); 0580 } 0581 0582 void MessageTest::testEncryptedMails() 0583 { 0584 KMime::Message::Ptr msg = readAndParseMail(QStringLiteral("x-pkcs7.mbox")); 0585 QVERIFY(msg->contents().size() == 0); 0586 QVERIFY(msg->attachments().count() == 0); 0587 QVERIFY(KMime::isEncrypted(msg.data()) == true); 0588 QVERIFY(KMime::isInvitation(msg.data()) == false); 0589 QVERIFY(KMime::isSigned(msg.data()) == false); 0590 } 0591 0592 void MessageTest::testReturnSameMail() 0593 { 0594 KMime::Message::Ptr msg = readAndParseMail(QStringLiteral("dontchangemail.mbox")); 0595 QFile file(QLatin1String(TEST_DATA_DIR) + QLatin1String("/mails/dontchangemail.mbox")); 0596 QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text)); 0597 QByteArray fileContent = file.readAll(); 0598 QCOMPARE(msg->encodedContent(), fileContent); 0599 QCOMPARE(msg->decodedText(), QLatin1String("")); 0600 KMime::Message msg2; 0601 msg2.setContent(msg->encodedContent()); 0602 msg2.parse(); 0603 QCOMPARE(msg2.encodedContent(), fileContent); 0604 } 0605 0606 void MessageTest::testEmptySubject() 0607 { 0608 auto msg = readAndParseMail(QStringLiteral("empty-subject.mbox")); 0609 QVERIFY(msg); // was crashing for Andre 0610 QVERIFY(msg->hasHeader("Subject")); 0611 QVERIFY(msg->subject()->asUnicodeString().isEmpty()); 0612 } 0613 0614 void MessageTest::testReplyHeader() 0615 { 0616 auto msg = readAndParseMail(QStringLiteral("reply-header.mbox")); 0617 QVERIFY(msg); 0618 QVERIFY(!msg->replyTo(false)); 0619 QCOMPARE(msg->hasHeader("Reply-To"), false); 0620 QCOMPARE(msg->hasHeader("Reply"), true); 0621 QVERIFY(msg->headerByType("Reply")); 0622 } 0623 0624 KMime::Message::Ptr MessageTest::readAndParseMail(const QString &mailFile) const 0625 { 0626 QFile file(QLatin1String(TEST_DATA_DIR) + QLatin1String("/mails/") + mailFile); 0627 const bool ok = file.open(QIODevice::ReadOnly); 0628 if (!ok) { 0629 qWarning() << file.fileName() << "not found"; 0630 } 0631 Q_ASSERT(ok); 0632 const QByteArray data = KMime::CRLFtoLF(file.readAll()); 0633 Q_ASSERT(!data.isEmpty()); 0634 KMime::Message::Ptr msg(new KMime::Message); 0635 msg->setContent(data); 0636 msg->parse(); 0637 return msg; 0638 } 0639 0640 void MessageTest::testBug392239() 0641 { 0642 auto msg = readAndParseMail(QStringLiteral("bug392239.mbox")); 0643 0644 QCOMPARE(msg->subject()->as7BitString().data(), "Subject: "); 0645 QCOMPARE(msg->contents().size(), 0); 0646 QCOMPARE(msg->contentTransferEncoding()->encoding(), KMime::Headers::CEbase64); 0647 QCOMPARE(msg->decodedText().toUtf8().data(), "Following this paragraph there is a double line break which should result in vertical spacing.\r\rPreceding this paragraph there is a double line break which should result in vertical spacing.\r"); 0648 } 0649 0650 void MessageTest::testBugAttachment387423() 0651 { 0652 auto msg = readAndParseMail(QStringLiteral("kmail-attachmentstatus.mbox")); 0653 0654 QCOMPARE(msg->subject()->as7BitString().data(), "Subject: XXXXXXXXXXXXXXXXXXXXX"); 0655 QEXPECT_FAIL("", "Problem with searching attachment", Continue); 0656 QCOMPARE(msg->attachments().count(), 1); 0657 QCOMPARE(msg->contents().count(), 2); 0658 0659 KMime::Content *attachment = msg->contents()[1]; 0660 QCOMPARE(attachment->contentType(false)->mediaType().data(), "image"); 0661 QCOMPARE(attachment->contentType(false)->subType().data(), "gif"); 0662 QCOMPARE(attachment->contentType(false)->subType().data(), "gif"); 0663 QCOMPARE(attachment->contentDisposition(false)->filename(), QStringLiteral("new.gif")); 0664 QCOMPARE(attachment->contentDisposition(false)->disposition(), Headers::CDattachment); 0665 } 0666 0667 void MessageTest::testCrashReplyInvalidEmail() 0668 { 0669 KMime::Message::Ptr msg = readAndParseMail(QStringLiteral("crash-invalid-email-reply.mbox")); 0670 QCOMPARE(msg->subject()->as7BitString().data(), "Subject: Re: Authorization required to post to gmane.network.wireguard (b96565298414a43aabcf9fbedf5e7e27)"); 0671 QCOMPARE(msg->contentType()->mimeType().data(), "text/plain"); 0672 QCOMPARE(msg->contentType()->charset().data(), "us-ascii"); 0673 QVERIFY(msg->isTopLevel()); 0674 } 0675 0676 0677 #include "moc_messagetest.cpp"