554 Recipient count exceeds 50 (Amazon SES)
The error, as SES returns it at the end of DATA:
554 Transaction failed: Recipient count exceeds 50If you relay through Mailway, this is already handled
Section titled “If you relay through Mailway, this is already handled”Above a provider’s recipient cap, Mailway rewrites the message so SES accepts it and delivers to everyone. You don’t need to split the send yourself. Skip to what changes for your recipients, because one thing does.
If you send through the HTTP API instead, you never see this
error: the API rejects more than 50 recipients up front with a 422, before
anything is queued.
What SES actually counts
Section titled “What SES actually counts”This is the part that is easy to get wrong. SES does not count the
SMTP envelope. It counts the union of the envelope and the To/Cc/Bcc
header addresses, and it evaluates that count after the DATA
terminator — so every RCPT TO can be accepted with 250 Ok and the
message can still be rejected wholesale a moment later.
Probed against live SES in eu-central-1, 2026 Q3:
Envelope (RCPT TO) |
To: header |
Result |
|---|---|---|
| 1 | 51 addresses | 554 exceeds 50 |
| 2 | undisclosed-recipients:; (0) |
250 Ok, delivered |
| 51 | undisclosed-recipients:; (0) |
554 exceeds 50 |
Row 1 proves the header alone trips the cap — the envelope held one address. Row 3 proves the envelope still counts too — the header was empty. Both are counted, together.
The consequence is the trap: splitting the envelope alone fixes nothing.
Send 52 recipients as two chunks of 26 RCPT TO while DATA still carries all
52 addresses in To:, and both chunks fail exactly as the unsplit message did.
This also contradicts the intuition most people bring from AWS’s own
“send to multiple recipients” material, which describes the v2 API and its
explicit Destinations argument, where header and envelope are decoupled. On
the SMTP and SendRawEmail path SES re-derives the count from the message
itself. AWS’s troubleshooting documentation is the one that matches observed
behavior: a recipient is any address on the To:, CC:, or BCC: lines.
What Mailway does about it
Section titled “What Mailway does about it”Above the cap, and only above it, Mailway:
- Removes every
To/Cc/Bccheader from the raw message, including folded continuation lines, and appends one empty group:To: undisclosed-recipients:;. Header count becomes 0. - Chunks the SMTP envelope into groups of at most the provider’s cap and dials once per chunk.
Union per chunk is then 0 + (≤ cap), which SES accepts. This is classic BCC
fan-out.
Two details worth knowing:
- The fan-out leaves the body alone. The rewrite operates on the header
block only, so the body, and therefore the DKIM body hash, stays as it
is. A sender signature that covered
To/Cc/Bccis invalidated, which is acceptable because SES re-signs the modified headers with your domain’s own DKIM and DMARC aligns on that signature. - It is one of four automatic changes Mailway makes to a relayed message.
The second is the provider instruction headers:
a few headers Mailway adds at the top of the message for the provider to
read and remove (for SES,
X-SES-CONFIGURATION-SET), so your recipient never sees them. The third: a bare line feed or a bare carriage return reaches the provider as a carriage return and a line feed (CRLF). The fourth: a message without aMessage-IDorDategets one when Mailway receives it, and aBccfield is removed. A fifth change, re-encoding for a structured-only API provider, is opt-in: it is off by default and an admin must turn it on. Mailway otherwise relays byte-for-byte. The fan-out exists because SES cannot accept the message as sent, and it fires only when the recipient count exceeds the cap. At or below the cap, the recipient headers stay as they are and the envelope is never even computed.
The cap is a per-provider property, not an SES special case. Both SES transports declare 50; providers that impose no such limit take the ordinary single-dial path.
What changes for your recipients
Section titled “What changes for your recipients”Because the send becomes a BCC:
- Recipients no longer see each other. Each one sees only the sender and
undisclosed-recipients:;. - Reply-all reaches the sender only, not the group.
That is the visible cost of SES accepting the message at all, and it’s the industry-standard handling of large recipient sets. If mutual visibility matters for a particular send, keep it under the cap.
Your own records are unaffected. The console mail list, the message detail,
and share links read the stored recipient set from the database, not the
transmitted headers — so you still see everyone who received it, even though
the wire headers say undisclosed-recipients:;.
Related
Section titled “Related”- SMTP relay — the relay’s fidelity guarantees and this exception
- Limits & quotas — recipient caps per path
- Troubleshooting — the full symptom index
Cookie consent
We may run ads on Google and Reddit. If we do, knowing whether they work needs your OK for one cookie each from them, used only to tie a signup back to the ad that brought it. Analytics here is cookieless either way, and declining changes nothing else.
Change your mind any time with "Cookie choices" in the footer. Details in the privacy policy.