Skip to content
Deliverability

Soft bounce vs hard bounce — what they mean and what to do

The two-word split is lossy. A 4.x.x status can arrive with Action failed, and a 5xx often means the sender is broken, not the recipient. Six buckets, not two.

16 Jun 2026 12 min readBy Autocloz Editorial, Deliverability team
Soft bounce vs hard bounce — what they mean and what to do

A hard bounce is a permanent rejection at the recipient address and a soft bounce is a temporary condition such as a full mailbox — and that two-word summary throws away most of the information a bounce carries. The reply code, the enhanced status code, the diagnostic text and, in an asynchronous notification, the Action field are four independent signals, and they disagree more often than the folklore admits. A 4.x.x status can arrive with Action: failed, meaning permanent. A 5xx frequently means your own sending configuration was refused, not that the recipient is dead. Classify on all four or you will delete valid contacts.

Two words are a lossy summary of a four-part signal

Every bounce a modern receiver produces carries up to four separable pieces of evidence.

  • The SMTP reply code. Three digits, 250, 450, 550. RFC 5321 defines what the first digit means.
  • The enhanced status code. Three dot-separated numbers, 5.1.1, 4.2.2, 5.7.1. RFC 3463 defines the class and the specific condition.
  • The diagnostic text. Free-form, provider-specific, and by far the most informative field in practice.
  • The Action field, present only in an asynchronous delivery status notification. RFC 3464 defines it, and it is the field that says whether anyone will try again.

Compressing that to "soft" or "hard" answers exactly one question — do I retry — and discards the two that decide what you actually do: whose fault was it, and should this address ever be mailed again.

What the standard actually says a 4yz and a 5yz mean

RFC 5321 section 4.2.1 is worth reading in the original because the popular summary of it is wrong in a specific, expensive way.

On 4yz, a Transient Negative Completion reply: "The command was not accepted, and the requested action did not occur. However, the error condition is temporary, and the action may be requested again." The rule of thumb the standard offers is that a reply is 4yz if repeating it unchanged could succeed "without any change in command form or in properties of the sender or receiver".

On 5yz, a Permanent Negative Completion reply: "The command was not accepted and the requested action did not occur. The SMTP client SHOULD NOT repeat the exact request (in the same sequence)." And then the sentence everybody skips: "Even some 'permanent' error conditions can be corrected, so the human user may want to direct the SMTP client to reinitiate the command sequence by direct action at some point in the future."

Read those together and the meaning of 5yz becomes precise. It says do not send this identical request again. It does not say the address is dead, and it does not say the situation is unfixable. That distinction is the whole reason a two-bucket classifier goes wrong.

RFC 3463 adds the class definitions for the enhanced codes. A 4.X.X is a "persistent transient failure", one where "the message as sent is valid, but persistence of some temporary condition has caused abandonment or delay". A 5.X.X is "a permanent failure ... not likely to be resolved by resending the message in the current form". Note the qualifier: *in the current form*. Again, a statement about the message and the moment, not a verdict on the recipient.

The specific conditions matter as much as the class. RFC 3463 defines X.1.1 as bad destination mailbox address — "The mailbox specified in the address does not exist." That is the only one of these that is genuinely about the recipient. X.2.2 is "The mailbox is full because the user has exceeded a per-mailbox administrative quota or physical capacity." X.4.7 is "delivery time expired". And X.7.1 is "Delivery not authorized, message refused ... This can be the result of per-host or per-recipient filtering" — a policy decision, and one that lands under the same 5 prefix as a dead mailbox.

The bounce may arrive at RCPT time or hours later

There are two physically different events that both get called a bounce, and they are read differently.

A synchronous rejection. The receiving server refuses the recipient during the SMTP conversation, at RCPT TO or after DATA. Your sending platform sees the reply code and the diagnostic text immediately, in the same connection. This is the case everybody pictures.

An asynchronous delivery status notification. The receiving edge accepts the message, returns 250, and only later discovers it cannot deliver it. It then generates a separate message — a DSN, formatted per RFC 3464 — addressed to the envelope sender in the Return-Path. Minutes later, or days.

The large providers increasingly do the second. That has three consequences worth internalising:

  1. Acceptance proves nothing. A 250 means the receiving server took responsibility for the message. Whether it can deliver it is a later question with a later answer.
  2. You only learn about async bounces if something reads the Return-Path mailbox. If the envelope sender points somewhere nobody monitors, those bounces exist and you never see them. Every address in that batch stays in your list, and every subsequent send to it does the damage again.
  3. Your bounce rate is a lagging measurement. Today's figure describes deliveries whose outcomes arrived today, not sends that happened today. Why that latency breaks a naive auto-pause is the reason thresholds need a sample floor.

A 4.x.x status with Action: failed is a permanent failure

This is the trap that catches classifiers written by careful people, and it is documented in the standard rather than being folklore.

RFC 3464 defines the Action field, which "MUST be present for each recipient named in the DSN", with five permitted values. Two matter here. failed "indicates that the message could not be delivered to the recipient. The Reporting MTA has abandoned any attempts to deliver the message to this recipient. No further notifications should be expected." delayed "indicates that the Reporting MTA has so far been unable to deliver or relay the message, but it will continue to attempt to do so."

Then the specification adds an explicit note that the Action field is not redundant with the status code, with a worked example: a server that repeatedly fails to reach a recipient's mail exchanger might issue a delayed DSN after a few hours and, after a few days, "abandon its attempt to deliver the message and return a 'failed' DSN. The status code (which would begin with a '4' to indicate 'temporary failure') would be the same for both DSNs."

So: Status: 4.4.7 with Action: failed is a message that will never be delivered, carrying a status code every simple classifier maps to "soft, retry". A system that keys only on the leading digit will re-queue it forever and count it in the wrong bucket. Read the Action field first when one is present.

The six buckets a classifier needs, and the two that are neither soft nor hard

Two categories are not enough. Six are, and Autocloz's classifier uses exactly these:

  • hard — permanent, and about the recipient. Nonexistent user, disabled mailbox, dead domain. 5.1.1, 5.1.10, "no such user", "recipient address rejected". Suppress permanently.
  • soft — transient. Mailbox full, quota exceeded, greylisting, 4.2.x, 4.3.x, 4.4.x, 421, 451, 452. Retry, then give up.
  • block — the receiver refused you for reputation. "Blocked", "blacklisted", "policy reasons", "too many connections", "throttled". The recipient is innocent; the fix is your sending behaviour.
  • complaint — a recipient reported the message as spam, or an abuse-report-format message arrived through a feedback loop. Suppress permanently and treat it as far more serious than a bounce.
  • sender — your own configuration was refused at submission. The recipient may be perfectly valid.
  • unknown — anything that cannot be placed. Conservative by design: an unclassified failure stays out of the suppression list.

Only hard and complaint cause suppression. That is the whole reason the six-way split exists, and the sender bucket earns its place with real incidents.

Amazon SES raises AccountSuspendedException when your AWS account is suspended. It arrives as a 5xx. Classified naively it is a hard bounce, so a perfectly good recipient is added to a global suppression list and their lead marked undeliverable because of a billing problem on your side. Autocloz hit exactly that on 1 August 2026 and now matches "account suspended", "sandbox", "identity not verified", "message rejected" and "sending paused" before the hard patterns, precisely so this cannot happen.

Microsoft 365 supplies the other common case. A tenant with authenticated SMTP disabled rejects your login with 550 5.7.139 SMTPClientAuthentication is disabled for the tenant. The substring 5.7.1 sits inside 5.7.139, so a naive pattern match reads a tenant policy about your account as a permanent rejection of their recipient. Same for 5.7.57, and for bare 530, 534 and 535 authentication codes.

The strings that get misfiled most often

Learn to recognise these five on sight. Four of them are sender-side, and the wider catalogue of bounce-back messages covers the codes beyond them.

  • 550 5.1.1 The email account that you tried to reach does not exist. - gsmtp — Gmail, genuine dead mailbox. The one true hard bounce here.
  • 550 5.7.1 ... Our system has detected that this message is likely unsolicited mail. To reduce the amount of spam sent to Gmail, this message has been blocked. — reputation, not the recipient. Correct handling is a block, and a whole batch of these means stop sending, not suppress everyone.
  • 550 5.7.26 Unauthenticated email from example.com is not accepted due to domain's DMARC policy. — your authentication. The recipient is fine.
  • 550 5.7.515 Access denied, sending domain does not meet the required authentication level. — Microsoft's consumer high-volume authentication rule. Your DNS records.
  • 421 4.7.0 Try again later, closing connection. — rate or reputation throttling. Slow down.

Greylisting deserves its own line because it is designed to be indistinguishable from failure at the moment it happens. RFC 6647 describes it as "providing temporarily degraded service to unknown email clients as an abuse mechanism" and says "the only two reasonable choices are 421 if the implementation wishes to terminate the connection immediately and 450 otherwise", with an acceptable retry window that "SHOULD be from one minute to 24 hours". You identify greylisting retrospectively: the same address succeeded on a later attempt. A verification probe that treats the first 450 as a verdict gets this wrong every time, which is one reason what a pre-send address check can actually prove is narrower than most tools imply.

What to do with each class, and the schedule the standard specifies

  • hard — suppress the address immediately, at workspace scope, permanently. Do not retry. Do not re-import it next quarter.
  • complaint — suppress, and treat the underlying cause as urgent. Complaint rate is the signal every provider weighs most heavily.
  • soft — retry on the standard's schedule. RFC 5321: delay after a failure, "the retry interval SHOULD be at least 30 minutes", and "the give-up time generally needs to be at least 4-5 days", with "two connection attempts in the first hour ... and then backing off to one every two or three hours". A soft bounce that never clears inside that window becomes a candidate for suppression, but only after the window, not after three tries in an afternoon.
  • block — stop sending from that identity and diagnose reputation. Suppressing recipients here actively destroys your list while leaving the actual problem untouched.
  • sender — fix your configuration. Surface it on the mailbox, not on the lead.
  • unknown — log it, alert, leave the address alone.

One more rule from the standard that is regularly broken by caching layers: "5yz responses to the MAIL command MUST NOT be cached." A permanent rejection of the envelope sender is about that transaction, not a durable fact about the domain.

Suppression is permanent by design, which makes misclassification expensive

A suppression list is not a delete. It is a structure that outlives the campaign, the list and the import, so that an address which hard-bounced or complained cannot be reintroduced by the next CSV. Why a hard bounce has to be permanent is the reason the list exists at all.

That permanence is exactly why the classifier matters. Every misclassified sender-side or reputation failure removes a valid prospect from every future campaign, silently, and the mistake is invisible because a suppressed address simply never appears again.

Autocloz's free plan covers 5 users and 10 mailboxes with the six-way classifier, workspace-scope suppression and 1,000 address verifications a day — start free and read one real bounce end to end before you build any rule on top of it.

What a bounce cannot tell you, and what Autocloz does not do

A bounce reports one delivery attempt. It cannot tell you whether an accepted message reached an inbox or a spam folder, because the folder decision happens after acceptance and is never reported back through SMTP.

It cannot tell you the recipient's intent. A 5.7.1 policy refusal on a per-recipient filter and one on a per-host filter read identically and mean different things.

And bounce rates are not comparable between systems, because the numerators differ. Amazon SES states that its rate "includes only hard bounces to domains you haven't verified", excluding "temporary and intermittent failures such as 'mailbox full,' or bounces due to blocked IP addresses" — and computes it over a "representative volume" rather than a fixed period, which is why AWS says you cannot reproduce its figure from your own send statistics. If you connect Amazon SES as a sending provider, your dashboard and theirs will legitimately disagree.

Autocloz classifies on the diagnostic text first and the numeric code second, keeps sender-side failures away from the suppression list, and applies health decay only when a receiver actually issued a verdict — a transport or credential error with no provider reply leaves mailbox health untouched, because our own outage is not evidence about your domain. The honest limit: Gmail signals a reputation block with 5.7.1, an enhanced code the standard defines as a policy refusal and which most classifiers, this one included, treat as permanent — so a batch refused for reputation can put recipients on the suppression list. That is one reason the list is reviewable and an owner or admin can remove an entry, and one reason email sending pauses a mailbox on accumulated failures rather than quietly working through them. Autocloz cannot see inside a receiving filter, cannot tell you why a policy refusal was issued, and does not read a Return-Path mailbox it has not been given access to.

Frequently asked

Is a 5xx bounce always a dead email address?

No. RFC 5321 defines a 5yz reply as "the command was not accepted and the requested action did not occur" and instructs the client not to repeat the exact request — and it adds that "even some permanent error conditions can be corrected". A 550 can mean a nonexistent mailbox, a policy refusal, a reputation block, or a rejection of your own sending configuration. Only the first justifies suppressing the recipient permanently.

How many times should I retry a soft bounce?

Follow the standard rather than a fixed count. RFC 5321 says the sender must delay after a failed attempt, that the retry interval should generally be at least 30 minutes, and that the give-up time generally needs to be at least four to five days. Two connection attempts in the first hour and then one every two or three hours is the pattern the specification describes as reflecting experience. In practice your sending platform owns this schedule, not you.

What is greylisting and how do I tell it apart from a real failure?

Greylisting is the practice of temporarily refusing mail from an unfamiliar client so that only software which correctly retries gets through. RFC 6647 says the only two reasonable replies for it are 421 if the server wants to close the connection immediately and 450 otherwise, and recommends a retry window from one minute to 24 hours. It looks identical to any other temporary failure at the moment it happens; it is distinguished by the message succeeding on a later attempt.

Should a bounce caused by my own misconfiguration count against the recipient?

Never. A rejection such as "identity not verified", an account-level sending pause, or "SMTPClientAuthentication is disabled for the tenant" is the provider refusing to accept a message from you. The recipient address may be perfectly valid. Suppressing it because of your own configuration error silently destroys good contacts and hides the real fault, which is why a classifier needs a sender-side category separate from hard and soft.

Does a full mailbox count towards my bounce rate?

It depends who is calculating it. Amazon SES states that its bounce rate "includes only hard bounces to domains you haven't verified" and that "temporary and intermittent failures such as 'mailbox full,' or bounces due to blocked IP addresses, don't count toward your bounce rate". Other systems count every failed delivery. Before you compare two bounce-rate figures, check whether they even have the same numerator.

Can a temporary status code be a permanent failure?

Yes, and it is documented. RFC 3464 notes that a temporary-failure status code beginning with 4 can appear with an Action field of either "delayed" or "failed" — a mail server that retries for days and then gives up issues a final notification whose status code still begins with 4. The Action field, not the status code, tells you whether further delivery attempts will be made.

Share
Free to start

Stop reading. Start sending.

Every tactic in this article is implemented behind the Autocloz dashboard.