MIME Email Attachments and Base64 Encoding

SMTP email encodes attachments as Base64 in MIME multipart messages. Learn the format, line length rules, charset headers, and common email encoding bugs.

MIME Email Attachments and Base64 Encoding

In SMTP, a Base64 attachment is a MIME part, not just encoded text.

SMTP was designed for 7-bit ASCII text in 1982.1 Binary attachments, PDFs, images, spreadsheets, require Base64 encoding to survive transmission through SMTP relays that strip or corrupt bytes with values above 127.

MIME (Multipurpose Internet Mail Extensions) defines the multipart message format that wraps attachments alongside the email body.2 Each attachment part specifies Content-Type, Content-Transfer-Encoding: base64, and the Base64-encoded content, which MIME decoders in email clients then decode.

What to look for

  • 76 characters per line, with CRLF endings (RFC 2045)
  • about 33%, plus ~2.6% more for MIME's CRLF wrapping
  • 25 MB total per message
  • 35 MB per message

LF-only line endings (common from Unix tools) can pass local validation but fail silently on a strict relay that enforces the CRLF requirement.

Opens the Base64 Text & File Encoder/Decoder with this page's reference values shown at the top of the tool.

Open in the tool →

How MIME Base64 encoding works

A MIME-encoded attachment occupies its own section in the email. The section opens with a Content-Type header (such as application/pdf; name="report.pdf"), followed by Content-Transfer-Encoding: base64, a blank line, then the Base64-encoded content wrapped at 76 characters per line with CRLF line endings (not LF). The 76-character line limit is mandatory per RFC 2045 , some older SMTP servers reject longer lines. Consequently, MIME Base64 output is longer than raw Base64 by approximately 2.6% (one CRLF pair per 76 characters).2 Building on this, Content-Disposition: attachment; filename="report.pdf" tells the email client to offer the attachment as a download rather than displaying it inline.

Keeping MIME line wrapping predictable

Use a MIME-aware encoder rather than a raw Base64 string when generating full message parts. The line breaks are part of the format, not cosmetic formatting, and they help older mail servers parse the attachment reliably. Python's email.mime.base.MIMEBase and Java's MimeBodyPart both handle the CRLF wrapping and line-length enforcement automatically, which means you should never manually construct MIME parts with raw Base64 unless you are prepared to replicate the RFC 2045 formatting rules exactly.

This matters because the failure mode is silent: a hand-rolled part that breaks the 76-character rule or uses LF instead of CRLF often validates locally and then fails only on a strict relay, so the bug surfaces in production rather than in your test mailbox. Building the part by hand also means you personally own every formatting decision, so a single copy-paste error from an old example can ship to real recipients before anyone notices.

Common pitfalls and variants

Line endings matter because MIME requires CRLF (\r\n) between each 76-character line, while Unix tools write LF only and Windows tools write CRLF by default, creating a cross-platform compatibility issue that silently corrupts attachments when the line endings do not match the standard. A attachment encoded on a Unix system with LF line endings may pass validation locally but fail when relayed through an SMTP server that enforces the MIME CRLF requirement, producing a broken attachment on the recipient's side with no error reported to the sender.

Keeping line endings and charset headers aligned

Sending LF-only MIME through a strict SMTP relay causes encoding errors that corrupt the attachment content when the relay rejects or modifies the message due to non-standard line endings. Furthermore, the character set of text attachments must be declared in the Content-Type header, such as Content-Type: text/plain; charset=UTF-8. Omitting the charset causes email clients to guess, often producing garbled non-ASCII text. The Content-Transfer-Encoding: base64 header applies to binary parts only; text parts typically use quoted-printable encoding, which is more human-readable and preserves line structure in plain text emails. A practical way to verify your MIME output is to pipe it through formail or a MIME parser before sending, which reports line-ending errors and missing headers that are difficult to spot by eye in raw message source.

Security and best practice

Inline images in HTML email use Content-ID (CID) references: Content-ID: <[email protected]>. The HTML body references them with src="cid:[email protected]". This causes email clients to render the image without an external HTTP request. Alternatively, data URIs in the HTML body embed Base64-encoded images directly, which works in Gmail, Apple Mail, and iOS Mail. MIME-encoded attachments have no size limit at the encoding level, but most mail servers enforce a per-message limit between 10 MB and 100 MB. A 10 MB PDF attachment encodes to roughly 13.3 MB of Base64 , well within common limits. The CID approach is generally preferred over data URIs for inline images because it keeps the HTML body smaller and compatible with a wider range of email clients, including Outlook for Windows which has limited data URI support.

Testing MIME structures before deployment

Before deploying an email campaign or transactional template, validate the MIME structure with a raw message viewer. Most mail clients show rendered HTML; to inspect the actual MIME parts, download the .eml file (available in Gmail via 'Show original' and in Outlook via 'View message source') and open it in a plain text editor or MIME parser. Verify that each attachment part carries Content-Transfer-Encoding: base64, that no line exceeds 76 characters, and that the boundary strings separating each MIME part are unique and consistent throughout the message.

Sending test messages to SMTP validators

SMTP validation services accept an SMTP connection to a dedicated test address and report MIME errors, spam-score issues, and malformed attachment headers. Sending your outgoing template to one of these services before deployment catches CRLF errors, incorrect charset declarations, and oversized Base64 blocks that strict relay servers reject. Validate both the plain-text and HTML parts of a multipart message, since encoding errors in either part can prevent the entire message from delivering correctly.

Size planning for attachments and server limits

Server-side email attachment size limits vary across providers. Gmail accepts messages up to 25 MB total, including all headers and encoding overhead.3 Microsoft 365 Exchange Online defaults to 35 MB per message.4 Base64 expands each attachment by 33%, so a 7.5 MB PDF occupies 10 MB after encoding.5 The combined encoded size of all attachments in a multipart message contributes to this total, not each attachment individually.

For large attachments, a link-to-download approach avoids the size constraint entirely: upload the file to cloud storage, generate a time-limited download link, and include the link in the message body instead of attaching the file. This also bypasses the security filters that some mail gateways apply to executable or archive attachments by inspecting byte signatures in the Base64-encoded content. Recipients at organizations with attachment scanning also receive the message faster when large binary content travels out-of-band.

When to use this

Use MIME Base64 encoding for email attachments, inline CID images, and any binary content in email messages. Use Content-Transfer-Encoding: quoted-printable for text parts that need to preserve line structure and remain partially human-readable. If a .eml export looks wrong, reconstruct the attachment from its Base64 block to confirm it matches the original file before you blame the mail server.

Examples

MIME attachment part structure

Before
Content-Type: application/octet-stream

<raw binary>
After
Content-Type: application/pdf; name="report.pdf"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="report.pdf"

JVBERi0xLjQKJcfs...

Each MIME part must end with CRLF before the boundary separator.

Encode an attachment in Python (smtplib)

Before
from email.mime.text import MIMEText
msg = MIMEText('Hello')
After
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders

msg = MIMEMultipart()
with open('report.pdf', 'rb') as f:
    part = MIMEBase('application', 'pdf')
    part.set_payload(f.read())
    encoders.encode_base64(part)
    part.add_header('Content-Disposition', 'attachment', filename='report.pdf')
    msg.attach(part)

encoders.encode_base64() handles line-wrapping and CRLF automatically.

Sources
  1. 1.

    J. Postel, "Simple Mail Transfer Protocol," RFC 821, IETF, August 1982. https://datatracker.ietf.org/doc/html/rfc821

  2. 2.

    N. Freed and N. Borenstein, "Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies," RFC 2045, IETF, November 1996. https://www.rfc-editor.org/rfc/rfc2045.html

  3. 3.

    "Send attachments with your Gmail message," support.google.com, accessed June 2026. https://support.google.com/mail/answer/6584

  4. 4.

    "Exchange Online limits," learn.microsoft.com, accessed June 2026. https://learn.microsoft.com/en-us/office365/servicedescriptions/exchange-online-service-description/exchange-online-limits

  5. 5.

    "Base64," Wikipedia, accessed June 2026. https://en.wikipedia.org/wiki/Base64

FAQ

Common causes: LF line endings instead of CRLF in the MIME part, incorrect Content-Type, truncated Base64 due to SMTP size limits, or a relay that modified the message body. Validate the MIME structure with a raw email viewer before blaming the recipient.

RFC 2045 §6.8 requires MIME Base64 to wrap at 76 characters per line with CRLF line endings. Java Base64.getMimeEncoder() and Python base64.encodebytes() apply this limit automatically.

Both work in most clients. Data URIs are simpler to construct , inline the Base64 directly in the src attribute. CID references require a multipart/related MIME structure. Gmail and Apple Mail support both; Outlook for Windows prefers CID attachments.

For binary files (PDFs, images, archives), yes , Base64 or uuencode. For plain text files, quoted-printable is the alternative. Most email libraries choose Base64 for all binary content automatically.

Common server limits range from 10 MB (Gmail) to 100 MB (custom mail servers). Because Base64 adds 33% overhead, a 10 MB file must be under 7.5 MB before encoding to stay under most server limits. CapyToolkit can help you inspect the encoded value locally before you paste it into an email test.

Additional resources

Guides

Embedding Images as Data URIs in HTML and CSS Learn how to embed images, SVGs, and fonts as Base64 data URIs in HTML attributes and CSS. Includes format, size limits, and when to avoid inlining. Building HTTP Basic Auth Headers with Base64 HTTP Basic Authentication encodes username:password in Base64 for the Authorization header. Learn the format, curl usage, and why HTTPS is required. How JWT Tokens Use Base64url Encoding JWT tokens encode header and payload as Base64url without padding. Learn the structure, how to decode the claims, and why JWTs are not encrypted by default. Base64 in Kubernetes Secrets Kubernetes Secrets store values as Base64-encoded strings in YAML. Learn how to encode, decode, and manage secrets , and why Base64 is not encryption. MIME Email Attachments and Base64 Encoding SMTP email encodes attachments as Base64 in MIME multipart messages. Learn the format, line length rules, charset headers, and common email encoding bugs. Storing Binary Secrets in Environment Variables Environment variables only hold text strings, but Base64 encoding lets you store binary secrets like TLS keys and certificates as env var values. Learn the pattern and risks. Embedding Binary Data in JSON APIs JSON cannot represent raw binary data. Base64 encoding is the standard way to embed images, files, and binary fields in JSON API requests and responses. URL-Safe Base64 vs Standard Base64 URL-safe Base64 replaces + with - and / with _ so strings are safe in URLs, HTTP headers, and filenames. Learn when to use each variant and how to convert between them. SSH Keys and PEM Certificates in Base64 SSH keys, TLS certificates, and PEM files wrap raw binary keys in Base64 between header and footer markers. Learn the format, how to decode keys, and common CI/CD patterns.