A soft bounce is a temporary delivery failure: the recipient address is valid but the message could not be delivered right now. A hard bounce is permanent: the address is invalid, the domain does not exist, or the server has explicitly rejected the message with no path to recovery. The SMTP layer signals the difference with a clear numeric code. Soft bounces return a 4xx status; hard bounces return a 5xx status. What you do with each determines whether your sender reputation survives.
| Soft Bounce | Hard Bounce | |
|---|---|---|
| Definition | Temporary delivery failure | Permanent delivery failure |
| SMTP class | 4xx (transient negative) | 5xx (permanent negative) |
| Enhanced status class | 4.x.x (persistent transient) | 5.x.x (permanent failure) |
| Common causes | Mailbox full, server temporarily unavailable, message size exceeded, greylisting | Invalid address, domain does not exist, recipient unknown, server explicitly refuses |
| Sender action | Retry with exponential backoff; suppress after repeated failures | Suppress immediately, never retry |
| Reputation impact | Low if managed promptly | High: sustained hard bounces signal list quality problems to mailbox providers |
What an Email Bounce Actually Is
When a receiving mail server cannot accept a message, it returns a three-digit SMTP reply code to the sending server. RFC 5321 “Simple Mail Transfer Protocol” defines the meaning of each code class. The first digit tells you everything you need to know about retry logic: a 4 means “try again later,” a 5 means “do not try again.” For a deeper look at how SMTP works and what the full conversation looks like, including how these reply codes appear on the wire, see the SMTP guide.
Beyond the basic three-digit code, servers can optionally return an enhanced status code defined by RFC 3463 “Enhanced Mail System Status Codes”. These follow the format X.Y.Z, where X matches the SMTP class (4 or 5), Y identifies the subject category (such as mailbox or network), and Z provides a precise error condition. A code of 4.2.2 tells you the mailbox is full; 5.1.1 tells you the user does not exist.
Most modern ESPs parse these codes for you and expose them as bounce type labels in their APIs and webhooks. The labels differ by provider, but the underlying logic is the same: 4xx = soft, 5xx = hard.
Soft Bounces: Causes and Retry Behavior
A soft bounce means delivery failed for a reason that may resolve on its own. RFC 5321 describes 4xx codes as “Transient Negative Completion” replies: the error condition is temporary, and the action may be requested again. RFC 3463 calls class 4 a “persistent transient failure,” meaning some temporary condition has caused the delay but future delivery may succeed.
Common causes of soft bounces:
- Mailbox over quota (4.2.2)
- Receiving server temporarily unavailable or overloaded (4.4.2)
- Message rejected by content filter or greylisting (4.7.1)
- Message too large for the server’s current limits (4.3.4)
- Connection timeout during transmission
Retry strategy for soft bounces:
Do not retry immediately and do not retry indefinitely. A reasonable production strategy:
- First retry: 5 to 10 minutes after the initial failure
- Second retry: 30 minutes later
- Third through fifth retries: increasing intervals up to 24 hours
- After 72 hours of continuous soft bouncing: treat the address as a hard bounce and suppress it
The exact thresholds are yours to tune, but the principle is consistent across provider documentation: retry soft bounces with exponential backoff, and escalate to permanent suppression after a defined failure window. Retrying forever wastes sending volume and risks triggering spam filters at the destination.
Hard Bounces: Causes and Why You Suppress Immediately
A hard bounce means the message cannot be delivered under any circumstances with the address as-is. RFC 5321 class 5 codes are “Permanent Negative Completion” replies. RFC 3463 class 5 is “permanent failure”: not likely to be resolved by resending the message in the current form.
Common causes of hard bounces:
- Recipient address does not exist (5.1.1)
- Domain does not exist or cannot be resolved (5.1.2)
- Mailbox unavailable, deleted, or disabled (5.1.6)
- Server permanently rejects the sender’s IP or domain (5.7.1)
- Message exceeds policy limits in a way that will not change (5.3.4)
The correct response to any 5xx reply is immediate suppression. Do not retry. Do not wait 24 hours. Add the address to your suppression list the moment the bounce is received.
The reason is reputation-level: mailbox providers monitor hard bounce rates as a list quality signal. Continuing to send to invalid addresses is interpreted as evidence of poor list hygiene or spam behavior. SendGrid’s bounce documentation classifies “Invalid Address” rejections as hard bounces and notes that bounced addresses are suppressed going forward, whereas blocked (temporary) addresses are not. That automatic suppression protects sender reputation by preventing repeat delivery attempts to known-bad addresses.
The SMTP Codes Behind Bounces
Understanding the code structure helps you write handling logic that does not depend entirely on your ESP’s labeling.
Three-digit SMTP codes (RFC 5321):
| First digit | Meaning | What to do |
|---|---|---|
| 2xx | Success | Nothing; message delivered |
| 4xx | Transient failure | Retry later |
| 5xx | Permanent failure | Suppress immediately |
Enhanced status codes (RFC 3463, X.Y.Z format):
| Code | Common meaning | Bounce type |
|---|---|---|
| 4.2.2 | Mailbox over quota | Soft |
| 4.4.2 | Connection timeout | Soft |
| 4.7.1 | Greylisting or policy rejection | Soft |
| 5.1.1 | User does not exist | Hard |
| 5.1.2 | Domain does not exist | Hard |
| 5.1.6 | Mailbox disabled | Hard |
| 5.7.1 | Sender rejected by policy | Hard (often a reputation block) |
Not every SMTP server sends enhanced status codes; some return only the three-digit code with a human-readable text string. Your handling logic should read the three-digit prefix first and use the enhanced code as a refinement when available.
Handling Bounces Programmatically
The most reliable way to handle bounces in a production system is through webhooks from your ESP, not by parsing raw SMTP responses yourself. Most transactional email providers fire a bounce event payload to a URL you configure, containing the bounce type, recipient address, SMTP code, and timestamp.
Webhook-Driven Suppression
Postmark’s bounce webhook delivers a JSON payload that includes a Type field set to "HardBounce" or "SoftBounce", along with the TypeCode, Email, BouncedAt timestamp, and an Inactive flag indicating whether Postmark has already deactivated the address. For hard bounces, Inactive will be true and CanActivate will be false.
A minimal webhook handler in Python:
import json
def handle_bounce_webhook(payload: dict):
bounce_type = payload.get("Type")
email = payload.get("Email")
if bounce_type == "HardBounce":
suppression_list.add(email, reason="hard_bounce", permanent=True)
elif bounce_type == "SoftBounce":
failure_count = increment_soft_bounce_count(email)
if failure_count >= 5:
suppression_list.add(email, reason="repeated_soft_bounce", permanent=True)
else:
schedule_retry(email, delay_minutes=soft_bounce_delay(failure_count))
The pattern is the same regardless of provider: read the type field, branch on hard vs. soft, suppress hard bounces immediately, increment and conditionally escalate soft bounces.
Suppression Lists
A suppression list is a set of addresses your system will not send to, regardless of what a caller requests. Sending to a suppressed address should fail silently at the application layer, never reaching your ESP. This prevents a hard-bounced address from being accidentally re-added to a campaign or triggered by a new signup flow.
Twilio SendGrid’s suppression system maintains separate lists for hard bounces and soft bounces, with configurable retention periods. Hard bounces are kept indefinitely by default. Soft bounces can be purged after a configurable number of days (minimum 1, maximum 3,650). The practical default is to retain hard bounces forever and let soft bounces age out after 30 to 90 days, revisiting any that accumulate beyond your threshold.
Retry Logic for Soft Bounces
If you manage retries yourself rather than relying on your ESP’s built-in retry queue, implement exponential backoff and a maximum attempt count:
import time
def retry_soft_bounce(email: str, attempt: int, max_attempts: int = 5):
if attempt >= max_attempts:
suppression_list.add(email, reason="soft_bounce_exhausted", permanent=True)
return
delay_seconds = (2 ** attempt) * 300 # 5m, 10m, 20m, 40m, 80m
schedule_send(email, delay_seconds=delay_seconds, attempt=attempt + 1)
After five attempts over roughly two and a half hours, any address still failing a soft bounce is unlikely to recover within the window that matters for transactional mail, and should be treated as a hard bounce.
For more on building the transactional email infrastructure that exposes these hooks, see What Is Transactional Email?.
How Bounces Damage Deliverability and Sender Reputation
Every bounce is a data point that mailbox providers use to assess your list quality and sending behavior. The damage is asymmetric: hard bounces carry far more weight than soft bounces.
High hard bounce rates signal to providers like Gmail and Yahoo that you are sending to invalid or purchased lists. This damages your IP and domain reputation, which flows through to inbox placement for your entire sending volume: your valid recipients start seeing your mail in the spam folder, even though the messages themselves are legitimate.
Soft bounces that persist without retry limits signal a different problem: a sender who keeps hammering a known-bad configuration. If you retry a greylisted address 50 times, you look like a spam sender, not a legitimate application.
The practical thresholds are qualitative guidance rather than hard industry rules: keep hard bounce rates as low as possible, and treat repeated soft bounces as hard bounces to stay well within whatever threshold your ESP enforces. SendGrid classifies bounce types across seven categories including Invalid Address, Mailbox Unavailable, Reputation, and Technical Failure, each carrying different implications for what action you should take.
For the related question of why good messages reach spam despite correct bounce handling, see Why Do My Emails Go to Spam? Bounce management is one layer; authentication and content signals are others. The full set of inbox placement factors is covered in the email deliverability best practices guide.
A Note on Email Authentication and Bounce Sources
Misconfigured authentication can cause bounces that look like recipient problems but are actually sender problems. A 5.7.1 rejection from a receiving server often indicates that your message failed the recipient’s SPF, DKIM, or DMARC check, not that the address is invalid. If you see a spike in 5.7.1 bounces, investigate your authentication records before suppressing the affected addresses.
For a primer on authentication setup, see What Is Email Authentication? SPF, DKIM, and DMARC Explained.
Email platforms that automate bounce classification, webhook delivery, and suppression list management help teams avoid the manual plumbing described above. Look for providers that surface bounce types in their event stream and maintain suppression lists automatically; the right tooling is covered in Best Transactional Email Services Compared (2026).
Frequently Asked Questions
What is the difference between a soft bounce and a hard bounce?
A soft bounce is a temporary delivery failure: the address is valid but the message could not be delivered right now due to a transient condition such as a full mailbox or a temporarily unavailable server. A hard bounce is permanent: the address does not exist, the domain cannot be resolved, or the server has definitively refused the message. SMTP signals soft bounces with 4xx reply codes and hard bounces with 5xx reply codes.
Should I retry a soft bounce?
Yes, with limits. Retry soft bounces using exponential backoff, starting with a short delay (5 to 10 minutes) and increasing with each failed attempt. After a defined number of attempts (typically 3 to 5 over 24 to 72 hours), treat the address as a hard bounce and suppress it permanently. Retrying indefinitely wastes sending volume and risks being flagged as a spam sender.
How do I know if a bounce is soft or hard from the SMTP code?
Look at the first digit of the three-digit SMTP reply code. Codes starting with 4 (4xx) are transient negative replies: temporary failures where retry is appropriate. Codes starting with 5 (5xx) are permanent negative replies: the message cannot be delivered as-is, and you should suppress the address immediately. RFC 5321 defines this classification; RFC 3463 extended status codes (X.Y.Z format) provide additional detail about the failure category.
Does a hard bounce hurt my sender reputation?
Yes. Mailbox providers treat high hard bounce rates as a signal of poor list quality or spam behavior. Consistently sending to invalid addresses damages your IP and domain reputation, which can cause even your legitimate messages to land in spam folders or be blocked entirely. Suppressing hard bounces immediately is one of the most direct actions you can take to protect deliverability.
What is a suppression list and why does it matter?
A suppression list is a set of addresses your sending system refuses to deliver to, regardless of what a caller requests. Hard-bounced addresses should be added to this list immediately and kept there permanently. Without a suppression list, a hard-bounced address can be re-entered through a new form submission or triggered by an automated workflow, causing repeat invalid deliveries that compound reputation damage.
Can a soft bounce become a hard bounce?
Not automatically at the SMTP level: each delivery attempt either returns a 4xx or a 5xx. But your handling logic should escalate a repeatedly soft-bouncing address to permanent suppression after enough failures, effectively treating it as a hard bounce. A mailbox that has been full or offline for 72 hours is unlikely to recover within the window that matters for transactional mail, and continuing to retry it carries reputation risk.
I’ve spent my career building software at scale with a soft spot for email: deliverability, lifecycle campaigns, and getting messages to actually land. I started Coldletter to fix what bugged me about transactional and marketing email tools. I’m based in Vancouver.
