summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/fixtures/body_with_content_id.eml20
-rw-r--r--tests/test_mimeparser.cpp31
2 files changed, 51 insertions, 0 deletions
diff --git a/tests/fixtures/body_with_content_id.eml b/tests/fixtures/body_with_content_id.eml
new file mode 100644
index 0000000..dd0f6be
--- /dev/null
+++ b/tests/fixtures/body_with_content_id.eml
@@ -0,0 +1,20 @@
+From: Bulk Sender <news@example.org>
+Subject: Body part carrying a content id
+Date: Sat, 01 Aug 2026 10:00:00 +0000
+Message-ID: <body-cid-1@example.org>
+MIME-Version: 1.0
+Content-Type: multipart/related; boundary="REL"
+
+--REL
+Content-Type: text/html; charset=utf-8
+Content-ID: <body@example.org>
+
+<html><body><p>Body text.</p><img src="cid:logo@example.org"></body></html>
+--REL
+Content-Type: image/png
+Content-Transfer-Encoding: base64
+Content-ID: <logo@example.org>
+
+iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9
+awAAAABJRU5ErkJggg==
+--REL--
diff --git a/tests/test_mimeparser.cpp b/tests/test_mimeparser.cpp
index f1bbc8a..d16735f 100644
--- a/tests/test_mimeparser.cpp
+++ b/tests/test_mimeparser.cpp
@@ -31,6 +31,7 @@ private slots:
void prefersHtmlWhenAvailable();
void fallsBackToPlainWhenHtmlDisabled();
void collectsInlineCidParts();
+ void aBodyCarryingAContentIdStillRenders();
void decodesQuotedPrintableAttachment();
void decodesEncodedHeaders();
void malformedMessageDoesNotCrash();
@@ -109,6 +110,36 @@ void TestMimeParser::collectsInlineCidParts()
QVERIFY(part.data.startsWith(QByteArray("\x89PNG", 4)));
}
+void TestMimeParser::aBodyCarryingAContentIdStillRenders()
+{
+ // Reported by the user: a bulk sender's message opened blank, with the app
+ // saying it had no HTML part.
+ //
+ // A Content-Id makes a part referenceable, not non-displayable, and setting
+ // one on the text/html body is legal and common. collectParts filed any
+ // part with an id into inlineParts and returned before the body branches,
+ // so such a message parsed with both body slots empty.
+ MimeParser parser;
+ const ParsedMessage msg =
+ parser.parse(fixture(QStringLiteral("body_with_content_id.eml")));
+
+ QVERIFY(msg.ok);
+
+ // The body fills its slot despite the id.
+ QVERIFY2(msg.hasHtml(), "the html body was swallowed by its own content id");
+ QVERIFY(msg.htmlBody.contains(QStringLiteral("Body text.")));
+
+ // And it stays reachable under that id, so a sibling referencing it still
+ // resolves. Register first, then assign: the two are independent.
+ QVERIFY(msg.inlineParts.contains(QStringLiteral("body@example.org")));
+ QCOMPARE(msg.inlineParts.value(QStringLiteral("body@example.org")).mimeType,
+ QStringLiteral("text/html"));
+
+ // The genuinely inline image is untouched by the change.
+ QVERIFY(msg.inlineParts.contains(QStringLiteral("logo@example.org")));
+ QCOMPARE(msg.inlineParts.size(), 2);
+}
+
void TestMimeParser::decodesQuotedPrintableAttachment()
{
MimeParser parser;