Skip to content

← All writing

Deliverability

Why a good mail server refuses instead of bouncing

24 July 2026 · 2 min read · TMailr

There are two moments a mail server can say no. During the SMTP conversation, before it has accepted responsibility, or afterwards by generating a bounce message back to the sender. Both look like a rejection from the outside. Only one of them is honest.

Refusing during the conversation

The sending server is still connected. You answer the RCPT command with a 5xx and it knows immediately: it can tell its user, log it, stop retrying. Nothing has been accepted and nothing needs to be undone.

The cost is that you have to decide quickly, with only the envelope in hand. You know who is connecting, what they claim to be, and who they are writing to. You do not have the message yet.

Bouncing afterwards

You answer 250, the sender goes away satisfied, and then you discover you cannot deliver. Now you have to generate a new message back to whoever the envelope claimed sent it.

The trouble is the word claimed. Envelope senders are forged constantly, so a bounce is a message you send to somebody who probably did not write to you. At volume that is backscatter, it lands in innocent people’s inboxes, and it is your reputation that pays for it. Meanwhile the actual sender, if they were legitimate, was told an hour ago that everything was fine.

So the rule is simple

Decide before you accept. Every check that can be made from the envelope belongs at RCPT time: does this recipient exist, is it still active, is it over quota, is this sender permitted to write to it.

The failure mode to avoid is answering 250 and then dropping the message. The sender believes it was delivered, the recipient never sees it, and nothing anywhere records that it happened. A refusal at least reaches somebody.

Temporary and permanent are different promises

A 4xx says try again, a 5xx says do not. Getting this backwards is expensive in both directions.

  • A message too large to accept will be exactly as large on the retry. Answering 4xx makes the sender queue it for days before giving up, so they find out on Thursday about something that failed on Monday.
  • A mailbox that is temporarily full deserves a 4xx. A 5xx tells the sender to give up on an address that will work again in an hour.
  • If your own systems are down, 4xx everything. Refusing permanently because your database is unreachable throws mail away over a five-minute outage.

One recipient at a time

When a message has several recipients and only one is a problem, the protocol you deliver over matters. LMTP gives a separate answer per recipient, so the sender retries the one that failed. Answering once for all of them means a retry redelivers to everyone who already received it, and nobody downstream can tell the copies apart.

None of this is exotic. It is the difference between a server that tells the truth at the moment it knows it, and one that says yes and works out the consequences later.

More on deliverability