RFC 3030 – SMTP BINARYMIME and CHUNKING
Why This RFC Exists
Traditional SMTP uses the DATA command to transfer message content. The message body is sent as a stream of text, terminated by a line containing only a period (.\r\n). This design has two problems:
- Dot-stuffing overhead: Any line in the message that starts with a period must be escaped by adding an extra period. The server must scan every line to remove the escape. This adds processing overhead and can introduce bugs.
-
No binary support: The
DATAcommand assumes 7-bit ASCII text with CRLF line endings. Binary content (like attachments) must be Base64-encoded, which increases the data size by approximately 33%.
RFC 3030 defines two related extensions that solve these problems. CHUNKING introduces the BDAT command, which transfers data in explicitly sized chunks — no dot-stuffing required. BINARYMIME builds on CHUNKING to allow raw binary content without any encoding.
How It Works
CHUNKING (the BDAT command)
- The server advertises
CHUNKINGin its EHLO response. - Instead of
DATA, the client usesBDAT <size>to send a chunk of exactly<size>octets. - The server reads exactly that many bytes, then sends a response.
- The client can send multiple
BDATchunks. The last chunk includes theLASTkeyword:BDAT <size> LAST. - No dot-stuffing is needed because the size is explicit.
BINARYMIME
- The server advertises both
CHUNKINGandBINARYMIMEin its EHLO response. - The client declares
BODY=BINARYMIMEon theMAIL FROMcommand. - Message data is sent via
BDATand may contain raw binary content — no Base64 encoding, no CRLF line-ending requirements.
SMTP Example
Sending a message using BDAT instead of DATA:
With BINARYMIME for raw binary content:
Key Technical Details
BDAT vs. DATA
| Aspect | DATA | BDAT (CHUNKING) |
|---|---|---|
| Termination |
.\r\n (dot on a line by itself) |
Explicit byte count + LAST keyword |
| Dot-stuffing | Required | Not needed |
| Binary content | Must be Base64-encoded | Raw binary with BINARYMIME |
| Streaming | Server scans for terminator | Server reads exact byte count |
| Multiple chunks | Not applicable | Yes, intermediate status after each chunk |
Chunk Sizing
There's no mandated chunk size. Clients typically choose chunk sizes based on available memory and network conditions. Common strategies include sending the entire message as a single BDAT ... LAST, or splitting into chunks of a few hundred kilobytes. Smaller chunks allow intermediate error detection; larger chunks reduce protocol overhead.
Error Recovery
If the server rejects a BDAT chunk (e.g., message too large), the client can issue BDAT 0 LAST to abort the transaction cleanly. This is cleaner than the DATA model, where the client must send the entire message and dot-terminator even if it knows the server will reject it.
BINARYMIME Forwarding
A server that receives a BINARYMIME message must not forward it to a server that doesn't support BINARYMIME. If the next hop doesn't advertise BINARYMIME, the forwarding server must convert binary content parts to Base64 encoding before relaying. This is a critical interoperability requirement.
Common Mistakes
-
Using BDAT without checking for CHUNKING. Not all servers support CHUNKING. Always verify the EHLO response before using
BDAT. If CHUNKING isn't advertised, fall back toDATA. - Sending BODY=BINARYMIME when the next hop doesn't support it. If you're a relay server and the downstream MTA doesn't advertise BINARYMIME, you must re-encode binary parts to Base64 before forwarding. Sending raw binary to a server that doesn't understand it corrupts the message.
-
Getting the byte count wrong. The size in
BDATmust exactly match the number of octets that follow. Sending too few or too many bytes desynchronizes the protocol and corrupts the session. -
Forgetting the LAST keyword. The final
BDATchunk must includeLAST. Without it, the server waits for more chunks and the session hangs. -
Mixing BDAT and DATA. A client must use either
DATAorBDATfor a given message, never both. Switching mid-transaction is a protocol error. -
Not handling intermediate chunk errors. If a non-final
BDATchunk returns an error, the client should sendBDAT 0 LASTto reset the transaction rather than continuing to send data.
Deliverability Impact
- Reduced bandwidth for binary attachments. BINARYMIME eliminates the 33% overhead of Base64 encoding. For a 10 MB attachment, that's saving approximately 3.3 MB of transfer data. This matters at scale.
- Faster processing for large messages. BDAT with explicit sizes lets the server allocate memory upfront and skip line-by-line scanning. This reduces CPU overhead on both sides.
- Cleaner error handling. Intermediate chunk responses let clients detect failures early without transmitting the entire message. This saves bandwidth and connection time when a message will be rejected.
- Wide support among major providers. Google, Microsoft, and most large mail platforms support CHUNKING. Using it when available is a best practice for efficient delivery.
- Eliminates dot-stuffing bugs. BDAT removes an entire class of potential bugs related to dot-stuffing and line-ending handling. Messages arrive exactly as sent, byte-for-byte.