Message formats and rendering
Rendering base64 attachments in webmail: pitfalls
Webmail must decode base64 MIME parts safely—valid fixtures render; broken padding, wrong types, and active content should not execute.

Decode bytes; do not trust declared types blindly. When a webmail client renders a base64 attachment, it must correctly interpret Content-Transfer-Encoding: base64, respect MIME boundaries, map Content-Type to a safe handler, and refuse to execute active content. A minimal valid fixture proves the happy path; intentionally broken padding, truncated bodies, and misleading types prove the client’s safety boundaries. Mailby’s Quick Inbox uses a safe HTML preview model for message bodies—attachments and active content are treated cautiously; never assume every webmail behaves the same.
Webmail client context and boundaries
MIME messages often include:
multipart/mixedwith a text part and an attachment partContent-Transfer-Encoding: base64on binary filesContent-Disposition: attachment; filename="…"
Boundaries for this guide:
- You are inspecting mail you are authorized to read.
- Examples are educational fixtures, not exploits against third-party systems.
- Base64 is an encoding, not encryption. Anyone with the message can decode it.
- Product truth: Mailby is receive-only; TLS in transit and encryption at rest protect storage during a lease—not E2EE with the sender (security, data retention).
Canonical references: RFC 2045 (MIME), RFC 4648 (Base64).
Fixtures: valid vs intentionally broken
Working path (valid PDF-like bytes)
Construct a message (conceptually) with:
multipart/mixedboundary.text/plainpart explaining the test.- Attachment part:
Content-Type: application/pdf
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="receipt.pdf"
JVBERi0xLjQKJeLjz9MKMyAwIG9iago8PC9UeXBlIC9QYWdl... (padded base64)
In a careful webmail client you should observe:
- Filename offered for download matches disposition (after sanitization).
- Bytes after decode begin with
%PDFif it is truly a PDF. - Inline preview may be blocked for PDFs (good) or sandboxed.
Failure / limitation fixtures
| Break | What you did | Likely client behavior |
|---|---|---|
| Bad padding | Strip = pad characters | Decode error; no file / error toast |
| Truncation | Cut base64 mid-stream | Corrupt download; checksum fail |
| Wrong type | Content-Type: image/png on PDF bytes | Misleading icon; decode still yields PDF magic |
| Pathful name | filename="../../evil.pdf" | Sanitized name or rejection |
| HTML labeled plain | text/html as attachment with script | Must not execute in parent session |
Limitation: Some clients sniff magic bytes; others trust headers. Either way, the security bar is “no unexpected script execution in the mail UI.”
Mechanism: how base64 attachment rendering works
- MIME parser splits parts on boundaries.
- For each part, read CTE. If
base64, decode to octets (RFC 4648). - Apply content-type handlers: force download, sandboxed preview, or block.
- Sanitize filename; never use raw path segments.
- Enforce size limits to avoid memory exhaustion.
Webmail adds a browser twist: if developers accidentally inject decoded HTML into the DOM without sanitization, attachment handling becomes an XSS bug. Safe preview pipelines parse and sterilize HTML bodies separately from binary attachments.
Mailby’s receive UI emphasizes safe preview and code/link extraction for verification workflows—binary attachment policy should be confirmed in the live product rather than assumed from this article.
Rendering table
| Raw part | declared type | observed rendering | accessibility/security implication |
|---|---|---|---|
| Valid base64 PDF | application/pdf | Download / sandboxed preview | Prefer download; screen readers need filename |
| Valid base64 PNG | image/png | Inline image if allowed | Alt text usually absent—add caption in body |
| Base64 text CSV | text/csv | Download or text view | Good for a11y if shown as text |
| Broken base64 | any | Error state | Must not partially execute |
text/html attachment | text/html | Download or sanitized view | Never run scripts |
| Empty body | any | Empty file warn | Avoid silent “success” |
Worked example
A QA engineer sends themselves a message with a small PNG encoded as base64 through their staging app into Quick Inbox. The preview shows the HTML body safely; the image part is available per product rules without running scripts from a forged HTML attachment in the same test suite. Separately, a broken-padding fixture produces a clear failure instead of a truncated “successful” file—this is the correct failure mode.
Alternatives and durable mailboxes
- Desktop clients (Thunderbird, Apple Mail): useful cross-check for MIME quirks.
- CLI (
munpack, custom Pythonemailmodule): authoritative decode for CI assertions. - Developer API inboxes: automate MIME checks on apps you own (/developers).
- Durable mailboxes store attachments longer; temporary leases mean attachment bytes vanish when the inbox expires—copy out anything you must keep (data retention).
Short answers
What causes base64 attachment issues in webmail?
Malformed MIME, bad padding, oversized parts, or unsafe HTML handling—not “base64 being broken.”
What should I do first?
Validate the raw MIME in a parser you trust; compare magic bytes to Content-Type.
When is a permanent address safer?
When attachments are legal/financial records you must retain beyond a temporary lease.
What evidence changes the recommendation?
If your client executes HTML attachments, stop using it for untrusted mail immediately.
Sources, test date, limitations
- Fixtures conceptualized 2026-09-24; do not paste untrusted attachments from strangers.
- RFC 2045, RFC 4648.
Limitations: Not a full MIME encyclopedia. Distinct from a message-format hub by focusing on base64 attachment rendering pitfalls.
Conclusion
Treat base64 as boring transport for bytes. Good webmail decodes faithfully and renders defensively. Use Quick Inbox when you need a receive-only place to inspect verification mail and safe previews—and keep long-term attachments in durable storage, not an expiring lease. See security for Mailby’s receive posture.
Minimal generator sketch (authorized self-test)
Using Python’s stdlib email package, build a multipart message, attach base64-encoded bytes, and send through your staging SMTP to an inbox you control. Keep fixtures in CI as .eml files so parsers stay pinned.
Assert in tests:
- Decoded length matches source bytes
- SHA-256 of decoded attachment matches
- Filename sanitization rules
Client matrix (what to expect)
| Client class | Base64 decode | HTML attach risk | Notes |
|---|---|---|---|
| Strict webmail | Yes | Sandboxed / blocked | Prefer for untrusted mail |
| Desktop client | Yes | Varies by settings | Good MIME cross-check |
| Mobile app | Yes | Inline previews differ | Watch auto image load |
| Raw developer UI | Yes | You own the risk | Use for debugging |
Accessibility
Blind users need meaningful filenames and body text describing the attachment. A blank filename="file" fails everyone. If the attachment is the only place a code appears, also put the code in the text part—verification UX depends on it.
Security regression tests
Add negative tests that feed:
- Overlong base64 bodies
- Nested multipart bombs (bounded)
Content-Type: text/htmlwith script payloads as attachments
Expect refusal or inert download—not DOM execution.
Retention reminder
Attachments inherit inbox life. Temporary leases mean binary loss at expiry (/data-retention). Export records you must keep. Quick Inbox is for inspection, not archives (/inbox).
Multipart edge cases worth one fixture each
multipart/mixedcontainingmultipart/alternativeplus attachment- Attachment before text part (unusual ordering)
- Duplicate filenames in two parts
filename*RFC 5987 encoded filenames with UTF-8
Webmail that only handles the happy path will mishandle one of these. Keep fixtures small.
Performance budgets
Decoding multi-megabyte base64 in the browser can freeze a tab. Server-side decode with size caps is usually safer. Temporary inboxes should reject or truncate oversized messages per policy rather than attempt heroic rendering.
Developer verification workflow
- Generate
.emlfixture - Parse with a reference library
- Deliver to staging inbox
- Observe webmail UI
- Assert download hash
Use Mailby when you need a hosted receive UI for humans in that loop (/inbox), or API for machines (/developers).
Hash verification worked example
Source PNG bytes hash to sha256:…. After webmail download, hash again. Mismatch means truncation, corruption, or client transcoding. Some clients re-encode images; prefer opaque application/octet-stream fixtures when testing bit-exact decode.
Policy for untrusted senders
Default deny inline render for odd types. Offer download with malware scanning if you operate an enterprise gateway. Consumer Mailby focuses on safe message preview for verification workflows—confirm live behavior rather than assuming desktop-parity attachment galleries (/inbox).
Security review questions for your own webmail
- Where does decode run (server vs browser)?
- What is the max decoded size?
- Are Content-Types allowlisted?
- Is HTML attachment sanitized with a battle-tested library?
- Are filenames normalized to a safe subset?
- Do logs store raw attachments longer than bodies?
Answer these in design docs before shipping. Temporary inbox products should bias toward safer defaults even if desktop clients are more permissive. Cross-check behavior on /inbox for Mailby-specific preview limits and keep long-term files elsewhere (/data-retention).
Broken padding laboratory
Base64 length must be a multiple of 4 after padding. Removing one trailing = often breaks decode. Your client should surface a clear error. Silently producing a shorter binary is worse because users open corrupted PDFs and think the sender is at fault. Log decode errors with message IDs for support.
Content-Disposition vs inline
attachment should download; inline may preview. Attackers flip these. Enforce server-side rules by type, not by attacker-supplied disposition alone. For verification emails, prefer codes in text over “download this HTML attachment to verify,” which is a smell.
Closing guidance
Base64 attachments are ordinary MIME. Webmail earns trust by decoding accurately, capping size, sanitizing names, and refusing to execute active content. Build valid and broken fixtures, hash the results, and document unsafe behaviors as bugs. Use temporary inboxes to inspect verification messages—not as long-term attachment archives (/data-retention, /inbox).
Note on scope
This guide stays within authorized testing and published Mailby product behavior—receive-only inboxes, documented retention, and live developer tools—without promising universal deliverability or anonymity. Verify live UI details on the product pages before you rely on a specific lease length in production workflows for teams you support beyond this article's examples and checklists here.
Appendix: operator acceptance checks
Before calling attachment rendering done:
- Valid base64 PDF downloads with matching hash.
- Broken padding shows an error, not a partial file.
- HTML attachment cannot execute script in the parent origin.
- Oversized parts are rejected with a clear message.
- Filenames with path segments are sanitized.
- Screen-reader users hear a meaningful filename.
Ship only when all six pass on staging. Temporary inboxes help humans spot-check verification mail; they are not archival stores for binary evidence (/data-retention).
One-paragraph recap
Decode base64 faithfully, render defensively, test broken fixtures on purpose, and never confuse temporary message previews with long-term attachment storage. When verification codes matter, put them in the text part too—attachments should be optional evidence, not the only path to completing signup.
Try it on Mailby
Open a receive-only disposable inbox when a short-lived address fits the job — session-bound, with timed purge.
