emailverifier.dev
Posts

Why Email Attachments Get Bigger: Base64 and SMTP SIZE

| 5 min read | Usama Ejaz
Three binary blocks expand into four Base64 blocks inside a larger MIME message that meets an SMTP size gate.

A binary email attachment normally grows by about 36.8% before SMTP sends it. Base64 turns every three input bytes into four characters, then MIME line wrapping adds a CRLF after each line of up to 76 characters. The receiving server's SMTP SIZE limit applies to the complete encoded message, not the file on disk.

In the byte-counted fixture I ran for this guide, a 25 MiB file became a 35,872,926-byte message, or 34.21 MiB. The message was intentionally small apart from the attachment, so a real message with HTML, inline images, long headers, or multiple files will be larger.

Count the encoded body first

RFC 2045 section 6.8 defines Base64 in 24-bit groups: three 8-bit input bytes become four 6-bit values represented as printable characters. Padding completes the final group when the input length is not divisible by three.

base64Characters = 4 * ceil(fileBytes / 3)
wrappedBodyBytes = base64Characters
                 + 2 * ceil(base64Characters / 76)

The second line assumes the encoder fills each line to 76 characters and writes a two-byte CRLF after the final line. RFC 2045 permits shorter lines, so the exact result depends on the serializer. The familiar 33% estimate counts only the four Base64 characters produced from three input bytes. MIME line breaks push a large encoded body to about 36.8% over the original file.

I generated deterministic binary buffers, encoded them with Node.js, wrapped the output at 76 characters, and compared the measured byte length with the formula. All five tested sizes matched. I then placed each body inside the same hypothetical multipart/mixed message with one plain-text part and one attachment.

Original file Wrapped Base64 body Complete fixture message
1 MiB (1,048,576 bytes) 1,434,898 bytes 1,435,484 bytes (1.37 MiB)
10 MiB (10,485,760 bytes) 14,348,938 bytes 14,349,524 bytes (13.68 MiB)
25 MiB (26,214,400 bytes) 35,872,340 bytes 35,872,926 bytes (34.21 MiB)

MiB means 1,048,576 bytes here. A provider that labels limits in MB may use decimal units, binary units, or a product-specific allowance. Keep byte counts explicit in application code and provider documentation.

The complete message is what SMTP measures

The attachment body is only one part of the wire message. Add the top-level headers, MIME part headers, text and HTML bodies, boundary delimiters, inline images, other attachments, and every CRLF between lines. A DKIM signature added at the sending boundary also occupies bytes in the message delivered to the next hop.

RFC 1870 section 5 defines message size as the octets sent after the server's 354 reply, including CRLF pairs. It excludes the SMTP DATA terminating dot and the extra dots added for SMTP transparency.

That distinction is useful. Do not apply a flat 37% multiplier to a file and call the result exact. Serialize the message your transport will send, then count its bytes. If you need to inspect how multipart/mixed, multipart/alternative, and multipart/related contribute boundaries and parts, the MIME email structure guide owns that nesting problem.

Read SMTP SIZE before DATA

An SMTP server that supports the Message Size Declaration extension advertises SIZE in its EHLO response. A following number is the largest message the server says it will accept. The client can declare an estimated message size on MAIL FROM and learn that the message is too large before uploading it.

This hypothetical exchange uses the 25 MiB server limit and fixture message above:

S: 250-SIZE 26214400
C: MAIL FROM:<sender@example.com> SIZE=35872926
S: 552 Message size exceeds fixed maximum message size

A 552 response for the fixed maximum is permanent for that message as constructed. A 452 response means the server currently lacks storage and may accept the message later. RFC 1870 section 6.2 also warns that a 250 response to MAIL FROM is not a delivery guarantee. The client still has to handle temporary and permanent failures during or after DATA.

If the server advertises SIZE without a number, it has not advertised a fixed maximum. That does not mean the message is unlimited. Resource limits, per-recipient limits, and later policy checks can still reject it.

The SMTP session here is server-to-server delivery. Applications normally submit mail through port 587 or 465, while mail servers deliver to one another on port 25. The SMTP ports guide separates those paths.

Preflight the message you will actually send

  1. Build the final MIME message with the real text, HTML, inline resources, filenames, and attachments.
  2. Serialize it with CRLF line endings and the same transfer encodings used by the sending transport.
  3. Count the serialized octets. If a later sending layer adds headers such as DKIM, reserve measured headroom or count again at that boundary.
  4. Parse a numeric SIZE advertisement when the next hop provides one. Stop before DATA when the message is already too large.
  5. Send the declared estimate on MAIL FROM, then keep 452 retry logic separate from permanent 552 handling.

The strongest fair objection is that a mail provider may already describe its limit as an “attachment limit.” That label is useful to a person composing mail, but it does not change the protocol boundary. Some products reserve space for encoding and headers; others publish a message limit or apply additional recipient rules. Treat the provider's current documentation as the product rule and the serialized message size as the engineering measurement.

When the finished message is over the limit, repeated retries cannot make the bytes smaller. Remove or compress a file when that preserves the recipient's job, split the content only when the workflow can safely reassemble it, or send a permissioned download link instead. Preserve the server response as evidence rather than converting every size failure into a bad-recipient claim. The hard versus soft bounce guide explains that failure boundary.

Continue reading