Developer Guide
Base64 Encoding for Email
How MIME uses Base64 for attachments and HTML email. Covers 76-character line wrapping, cid: versus data URIs, and why inline images must stay tiny.
SMTP was designed to move 7-bit ASCII. A PNG, a PDF, or a UTF-8 résumé is not that, so email adopted MIME and a transfer encoding that turns bytes into a letter-safe alphabet. That encoding is Base64: Content-Transfer-Encoding: base64 on a MIME part, then the payload as A–Z, a–z, 0–9, +, /, and =.
HTML email adds a second question. Many clients block remote <img src="https://…"> until the reader opts in, so designers attach the image and point at it with cid:, or they inline a data URI. Both still ride on Base64. Neither is a deliverability cheat code — oversized mail is slow to download and easy to treat as bulk. This page stays on the mechanics.
MIME Content-Transfer-Encoding: base64
A MIME message is a tree of parts. Each part has headers, including Content-Type and usually Content-Transfer-Encoding. For binary attachments the encoding is base64. The mail server and the client treat the body as ASCII; the client decodes back to bytes before saving the file or painting the image.
Quoted-printable is for mostly-ASCII text, not images. Produce a payload in /tools/base64 or a data URI in /tools/image-to-base64 and, for a MIME part, use only the bytes after the comma.
76-character wrapping versus JSON Base64
RFC 2045 tells MIME to wrap Base64 at 76 characters per line, with CRLF between lines. JSON APIs almost never do that: they store one long string. If you copy a MIME body into a JSON field, strip the line breaks. If you copy a JSON Base64 blob into a .eml part, wrap it or a picky gateway may reject the message.
/tools/base64 emits unwrapped output, which is what you want for JSON, data URIs, and debugging. Wrapping is a MIME concern, not a Base64 alphabet concern. Padding = characters still belong at the end of the payload, wrapped or not.
cid: versus a data URI in HTML email
cid: (Content-ID) references a sibling MIME part: <img src="cid:logo@campaign"> plus a part with Content-ID: <logo@campaign> and Content-Disposition: inline. The image travels with the message, and most desktop clients render it.
A data URI puts the Base64 in the HTML itself: <img src="data:image/png;base64,…">. That skips a MIME part, but support is uneven. Some webmail strips data: images; some mobile clients cap HTML size. When you do use a data URI, generate it on /tools/image-to-base64 and keep the file tiny. For a logo that must render in Outlook-class clients, cid: is the conservative choice.
Remote images are often blocked
A remote URL is easy to cache and easy to change after send. It is also how open-tracking pixels work, which is why many clients show a placeholder until the user allows images. If the message has to make sense with images off, put the words in HTML, not in a PNG.
When the picture is required — a receipt header, a signature mark — attach it. Do not host a 1 MB banner and hope the client fetches it. Do not inline that banner either. Resize first, then encode.
Keep inline images tiny
Base64 grows the part by about 33%, and email gateways still count the encoded size. A few kilobytes of PNG or GIF is the right order of magnitude for a logo. Animated GIFs and JPEGs of screenshots belong as attachments the reader opens, not as wallpaper in the HTML.
The 1×1 GIF data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7 is a useful spacer, not a reason to add tracking pixels.
Common pitfalls
Mixing wrapped MIME Base64 with an unwrapped JSON decoder leaves CR/LF in the payload. Strip whitespace before you decode a MIME body.
Encode and decode on /tools/base64 when you only need the alphabet. /tools/base64-to-image still needs the data:image/TYPE;base64, prefix.
- MIME wraps at 76 characters; JSON Base64 usually does not.
cid:needs a matchingContent-IDpart, not a public URL.- Nothing on thedevtools.in sends mail — you only encode locally.
Worked examples
MIME headers for an inline PNG
Content-Type: image/png; name="logo.png"
Content-Transfer-Encoding: base64
Content-ID: <logo@campaign>
Content-Disposition: inline; filename="logo.png"
iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg==The HTML then uses <img src="cid:logo@campaign" alt="Logo">. The payload here is a 1×1 PNG, not a production logo.
Encode a short subject-safe string
helloaGVsbG8=Same alphabet MIME uses. Encode Unicode on /tools/base64 — नमस्ते becomes 4KSo4KSu4KS44KWN4KSk4KWH.
Frequently asked questions
Does Base64 improve inbox placement?
No. It is a transfer encoding, not a reputation signal. Oversized encoded images can make a message slower and bulkier. Do not treat encoding as a delivery tactic.
Why does my decoder choke on an .eml attachment?
MIME inserts CRLF every 76 characters. Strip whitespace, then decode. /tools/base64 expects a continuous string unless you remove the breaks first.
Should I use a data URI or cid: for a logo?
cid: is the safer default for HTML email. Data URIs are simpler in a few web clients and brittle in others. Either way, keep the file small.
Can I encode the image on a server at thedevtools.in?
No. /tools/base64 and /tools/image-to-base64 run in the browser. Encode the file locally, then put the result in your MIME builder.
Summary
Email uses Base64 because the pipe is text. Wrap at 76 characters in MIME, leave JSON unwrapped, prefer cid: for logos that must render, and keep inline images tiny. Encode a sample on /tools/base64 or /tools/image-to-base64 before you fight a client that is actually stripping remote pictures.