Skip to content

Most "the mail server is broken" reports are the client sending something the specification forbids. RFC 5321 does not leave this ambiguous. It publishes exact octet limits, and a test suite that generates addresses or payloads without checking them will fail in ways that look like infrastructure problems.

The numbers, straight from the RFC

Section 4.5.3.1 of RFC 5321, "Size Limits and Minimums," is short and worth reading in full. The limits that matter for testing:

  • Command line: maximum 512 octets including the command word and the terminating CRLF.
  • Reply line: maximum 512 octets including the reply code and CRLF.
  • Text line: maximum 1000 octets including CRLF.
  • Local-part: maximum 64 octets.
  • Domain name: maximum 255 octets.
  • Path: maximum 256 octets for the reverse-path or forward-path, including punctuation and element separators.
  • Recipients buffer: minimum 100 recipients must be buffered.

Two of those are ceilings and one is a floor. The recipient buffer being a minimum is the detail people miss: a server that rejects a message with fewer than 100 RCPT commands is violating the spec, as section 4.5.3.1.8 states plainly.

Where generated addresses break first

A fuzzer or a random-address generator produces a local part by hashing something. Twenty bytes of base64url is 27 characters, comfortably under 64. Fifty bytes is 67 characters, and now every send fails at RCPT TO with a 501 that names the whole address. The local part limit is 64 octets, so a generator that concatenates a prefix, a timestamp, and a random suffix will cross it eventually.

The path limit is tighter than people expect at 256 octets, and it counts the punctuation. A long local part plus a long domain plus the angle brackets can exceed it even when the address itself looks legal in a UI. If you are testing a routing layer that rewrites the envelope, check the rewritten path, not the original.

The command line limit and the 512-octet trap

512 octets is roughly 512 ASCII characters. It sounds generous until you send a MAIL FROM with parameters. RFC 5321 allows extensions to raise the limit, and RFC 1870's SIZE extension is the standard way to declare and respect message size, but extensions are negotiated in EHLO. A client that assumes a raised limit without reading the EHLO response is assuming something the server never promised.

For anything large, the specification's own advice in section 4.5.3.1.7 is blunt: message size restrictions should be avoided if at all possible, and servers that must impose them should implement SIZE. So the practical test is not "does a 40 MB message go through" but "does the server advertise SIZE, and does it reject cleanly when the declared size passes the advertised maximum."

Why this matters for a disposable inbox

An inbox that accepts anything is not being generous, it is being unverifiable. Inboxmil caps per-message size at 10 MB by default (MEDIA_MAX_BYTES handles uploads separately at 5 MB) and enforces address TTLs measured in minutes for guests. Those are deliberate: a test inbox that accepts an unbounded payload and holds it forever is a storage problem wearing a feature's clothes.

When a test fails because mail "did not arrive," check these before the server logs, in this order: local part length, total path length, whether the client read the EHLO extensions, and whether the message body exceeded an advertised SIZE. Each one produces an error the server reports honestly, and each one is fixable in the generator rather than the mail server.

The takeaway

RFC 5321 hands you the exact numbers. Wire them into the generator and the assertions, and the class of failures that gets misdiagnosed as "mail is unreliable" disappears. The spec is not vague here, so there is no reason for the test to be.

Keep reading