Subject: fix(mime): a body part carrying a Content-Id no longer renders blank

From: "Danilo M." <[email-masked]>
Date: Fri, 7 Aug 2026 10:44:55 +0200

collectParts() filed any part with a Content-Id into inlineParts and
returned before the text/plain and text/html branches. Setting a
Content-Id on the text/html body is legal and common in bulk-sender
output, and such a message parsed with both body slots empty, so
hasHtml() was false, HtmlBuilder fell through to an empty plain body,
and the pane rendered nothing. Both halves of the report, the blank
message and "no HTML part", came from that one ordering.

A content id makes a part referenceable, not undisplayable. The two are
independent. The branch now registers the part and falls through rather
than returning, so the body still fills its slot. Registering first
keeps a part that is both the body and a cid: target reachable under
its id for any sibling referencing it.

Content-Disposition is deliberately not used as the discriminator: it
is absent far more often than it is correct, and a body part commonly
carries none. The existing attachment check remains the only test for
"not a body", and the first-one-wins isEmpty() guard still stops an
inline image displacing a real body, since an image matches neither
text branch.

Verified against a hand-written fixture whose text/html part carries a
Content-Id, asserting the body renders, the id still resolves, and the
sibling image is unaffected. Load-bearing by mutation: restoring the
early return fails the test. The user could not relocate the message
that prompted the report, so the end-to-end path is unconfirmed.

Closes item 41.

Co-Authored-By: Claude Opus 5 <[email-masked]>
---
 tests/fixtures/body_with_content_id.eml | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)
 create mode 100644 tests/fixtures/body_with_content_id.eml

(limited to 'tests/fixtures/body_with_content_id.eml')

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 <[email-masked]>
+Subject: Body part carrying a content id
+Date: Sat, 01 Aug 2026 10:00:00 +0000
+Message-ID: <[email-masked]>
+MIME-Version: 1.0
+Content-Type: multipart/related; boundary="REL"
+
+--REL
+Content-Type: text/html; charset=utf-8
+Content-ID: <[email-masked]>
+
+<html><body><p>Body text.</p><img src="cid:[email-masked]"></body></html>
+--REL
+Content-Type: image/png
+Content-Transfer-Encoding: base64
+Content-ID: <[email-masked]>
+
+iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9
+awAAAABJRU5ErkJggg==
+--REL--
-- 
cgit v1.2.3