Let a sent message carry images inside its body

FeatureEmailService
Shipped
September 3, 2026 at 2:03 AM UTC
Author
Kamo
Commit
0c2d1ef

The body had four possible shapes and send() could only build three. The multipart/related branch — the one that puts an image where the HTML's cid: points at it — sat behind the attachment branch, so a message with both a pasted image and a file lost the image on the way out: the body kept a cid: reference to a part that was no longer in the message, and nothing said so. It was also unreachable in practice, because only the transactional path ever set inlineImages; nothing a member sent could get there at all. applyBody now builds whichever shape the content calls for — html alone, related when the body references images, mixed when there are attachments, mixed wrapping related when there are both — and a calendar invite keeps its images by offering the related as the HTML alternative. reply and forward go through send, so they inherit all of it. /send takes the images as their own binary parts, each named for the content id the HTML already references. Base64 inside the JSON part would cost a third again in size against the smallest ceiling in the chain, so a screenshot or two would be refused for a reason the member could do nothing about. A part's name becomes a Content-ID header, so InlineImageParts matches it against the exact shape the composer mints and refuses everything else — a wrong one fails the send rather than dropping quietly and leaving a hole in the body.

All changes

Like what you see shipping?

Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.

Start Free ForeverView Pricing