- Ya
- 5 Agosti 2026, 01:33 UTC
- Mwandishi
- Kamo
- Ahadi ya
- 2fda4ac
Every transactional email we send with an inlined org logo arrived in our own /messages viewer with a correct subject and a completely empty body. isAttachmentPart() treated ANY part carrying a Content-ID as an attachment. The text/html ROOT of a multipart/related has one by design — applyInlineRelatedContent sets it so the RFC 2387 start= parameter can point at the body, which is what lets stricter gateways and Outlook find it. So walkParseMultipart classified the body as an attachment and continue'd past it before ever reaching the text/html body-candidate branch. htmlBody stayed null, and because a related send carries no text/plain alternative, textBody was null too — the viewer had nothing to render. Verified against the delivered message rather than inferred: the raw maildir file holds a well-formed multipart/related with a complete 4329-byte text/html root (Content-ID <emailroot>, 7bit, boundaries intact) and two base64 inline PNGs. The message was never the problem; the reader was. This was invisible until now because transactional mail without inline logos is sent as a SIMPLE non-multipart text/html message, which getMessage() handles on the `content instanceof String` path and never consults isAttachmentPart at all. The Content-ID rule still holds for everything that is not a text body, so the inline logos stay listed and cid: references keep resolving. Tests parse RAW MIME rather than assembling parts with setContent — that does not write the Content-Type header until the enclosing message is saved, so an assembled part reports text/plain and every isMimeType("text/html") branch silently misses. A fixture that lies about the one header this logic switches on would have passed against the broken code. Confirmed: 4 of the 6 fail without the fix.