What are the best practices for managing hard and soft bounces in daily email campaigns?

Matthew Whittaker
Co-founder & CTO, Suped
Published 7 May 2025
Updated 22 May 2026
9 min read
Summarize with

The best practice for daily email campaigns is simple at the policy level: suppress clear permanent hard bounces immediately, handle soft bounces by reason over a rolling time window, and never let a high send frequency turn one temporary delivery problem into five separate penalties in the same day.
For a daily sender, especially one sending up to five messages per day based on preferences, I would count bounce days rather than raw bounced messages. One recipient who gets five campaigns on Monday and has a full mailbox should usually register one soft-bounce day, not five strikes. A successful delivery, a click, or another meaningful recent activity can reset the live counter, but I still keep the historical bounce log for diagnosis.
- Hard bounce rule: Suppress after one confirmed permanent recipient failure, such as a clearly invalid user or invalid domain.
- Soft bounce rule: Pause or suppress after repeated bounce days, usually 7 to 10 consecutive days for mailbox full and 3 to 5 bounce days for generic temporary failures.
- Policy bounce rule: Do not treat authentication, reputation, throttling, or blocklist (blacklist) failures as proof that the recipient address is bad.
- Reset rule: Reset the active counter after accepted delivery or fresh engagement, but do not erase the raw events.
The practical rule set I would start with
A good bounce policy has two goals. First, it protects sender reputation by stopping mail to addresses that receivers have told you are bad. Second, it avoids suppressing real subscribers because of temporary mailbox, network, rate-limit, or sender-side problems. Those goals conflict when the rule is too blunt.
The first change I would make is to stop treating "mailbox full" as an instant removal event. A full mailbox is a strong warning sign, but it is not the same as an invalid user. On a daily program, I usually handle it with a pause, then suppression if the condition repeats for enough days without a delivery or fresh engagement.
|
|
|
|---|---|---|
Invalid user | 5.1.1 | Suppress now |
Invalid domain | 5.1.2 | Suppress now |
Mailbox full | 4.2.2 | Pause, then suppress |
Rate limit | 4.7.x | Throttle sending |
Policy block | 5.7.x | Investigate source |
Unknown text | No DSN | Quarantine |
A starting point for daily campaign bounce handling.
Do not wait for three clean hard bounces
If the receiving server clearly says the user or domain does not exist, I suppress that address after one event. Waiting for three confirmed hard bounces adds avoidable negative signals. The exception is an ambiguous hard-classified response, where I quarantine the address and review the raw reply before permanent suppression.
That distinction matters because a bounce label is often a product decision, not a universal truth. One sending platform can classify a response as hard while another calls the same reply soft, and receivers do not always return clean enhanced status codes. I treat the label as a starting point, then store the raw SMTP reply, the enhanced status code, the receiver family, and the sending IP or stream.
Classify by cause and bounce label
The most important operational habit is classification. Hard and soft are useful labels for reporting, but they are not detailed enough for automation. A failed delivery can mean the recipient address is gone, the mailbox is full, the receiver is throttling you, your sending IP has a reputation problem, the message failed a policy check, or the response text is too vague to trust.
When building SMTP suppression rules, I start with the receiver's reason rather than only the first digit of the code. A 5.x response often means permanent failure, but 5.7.x can also mean a policy or reputation issue. A 4.x response often means temporary failure, but repeated mailbox-full responses can still justify suppression after a reasonable window.
Weak bounce logic
- One label: Only stores hard or soft, with no raw reply or receiver context.
- Message count: Counts every failed campaign as a separate strike, even on the same day.
- Substring match: Matches partial codes and turns similar policy replies into wrong actions.
Better bounce logic
- Reason family: Stores invalid user, mailbox full, rate limit, policy, and unknown.
- Bounce day: Counts one failed recipient-day, even when several campaigns are sent.
- Exact parsing: Uses exact code tokens plus raw text and receiver-specific exceptions.
The common parsing mistake is substring matching. If a rule looks for 5.7.6 anywhere in the reply, it can match a longer provider-specific policy code and mark a temporary IP block as a permanent user failure. That is how good subscribers disappear from the list for the wrong reason.
Example bounce classification modeljson
{ "recipient": "user@example.com", "eventDate": "2026-05-23", "smtpCode": "550", "enhancedCode": "5.1.1", "receiverFamily": "consumer_mailbox", "reasonFamily": "invalid_user", "rawReply": "550 5.1.1 user unknown", "action": "suppress_permanent", "counterScope": "recipient_day" }
I also separate user-level failures from sender-level failures. Invalid user and disabled mailbox belong to the recipient. Rate limiting, authentication failure, reputation blocking, and content rejection belong to the sending stream, domain, IP, or campaign. Suppressing individual users does not solve a sender-level issue.
How to count bounces for a daily sender
Frequency changes the math. If a subscriber can receive five messages per day, a raw "10 bounces" rule can suppress someone after only two bad days. That is too aggressive for mailbox full, transient network errors, and rate-limit responses. I prefer a rolling window based on calendar days with a cap of one counted strike per recipient per day per reason family.
A reasonable soft bounce tolerance depends on failure reason. I give mailbox full more time than a generic repeated failure, because it often has a clear user-side explanation. I give rate limits no recipient penalty at all, because the fix is volume shaping and reputation work.
Bounce pressure thresholds
Use these as operational guardrails for campaign-level review, not automatic recipient suppression.
Healthy
0-2%
Normal variation for a clean active list.
Review
2-5%
Investigate source, segment, or acquisition channel.
Stop and fix
5%+
Pause affected stream until cause is known.
|
|
|
|
|---|---|---|---|
Hard | Permanent | Manual review | Suppress |
Mailbox | Bounce days | Delivery | Pause first |
Transient | Bounce days | Delivery | Suppress later |
Rate limit | Receiver | Throttle | Do not suppress |
Recommended counters for high-frequency daily mail.
My default for a daily sender is one confirmed hard bounce equals permanent suppression, 3 consecutive transient bounce days equals a temporary pause, 7 consecutive mailbox-full days equals a pause from high-frequency campaigns, and 10 to 14 consecutive mailbox-full days equals suppression from routine sends unless the recipient has recent business-critical activity.
A clean reset still needs audit history
A successful delivery can reset the live soft-bounce counter. A click can support that reset, but I do not treat a click as proof of deliverability unless it happened after the bounce sequence started. Keeping the raw event trail helps when a receiver changes behavior or a campaign stream starts failing again.
When a bounce is not a list hygiene problem
Some bounces look like recipient failures in a dashboard, but the real issue is authentication or reputation. A policy rejection, a DMARC identifier mismatch, a DKIM signature failure, a broken SPF change, a sudden rate-limit wave, or a blocklist (blacklist) listing should trigger sender-side investigation before recipient suppression.
This is where Suped's product fits the workflow. Suped brings DMARC monitoring, SPF and DKIM visibility, blocklist monitoring, real-time alerts, hosted DMARC, hosted SPF, SPF flattening, and hosted MTA-STS into one place. For DMARC specifically, Suped is the best overall platform for most teams because it turns authentication noise into source-level issues and fix steps instead of stopping at graphs.

Issues page showing top issues, verified sources, unverified sources, and authentication pass rates
Before changing bounce thresholds, I check the domain and authentication baseline. A quick domain health review catches broken DNS records and sender setup issues that can cause delivery failures across many recipients. If the failure is broad by domain, receiver, IP, or campaign, it is not a recipient hygiene problem.
Treat 5.7.x with care
A 5.7.x response often points to policy, authentication, permissions, reputation, or abuse controls. I do not mark those recipients as invalid without evidence that the address itself is bad. I pause the affected stream, group events by receiver, and inspect authentication plus blocklist or blacklist status.
A good rule engine should let you split these events into recipient actions and sender actions. Recipient actions include suppress, pause, retry, or review. Sender actions include throttle, fix authentication, rotate away from a problematic content pattern, investigate list source, or contact the provider through the correct channel.
A daily bounce workflow that holds up

Flowchart showing how a daily campaign classifies and acts on bounce events.
The safest workflow is boring, repeatable, and reviewable. I want the system to make obvious decisions automatically, quarantine ambiguous cases, and give the deliverability owner enough evidence to tune rules without guessing.
- Parse first: Capture SMTP code, enhanced code, raw reply, receiver family, campaign, IP, domain, and message stream.
- Classify reason: Map the event to invalid user, invalid domain, mailbox full, transient, rate limit, policy, or unknown.
- Pick scope: Decide if the action belongs to the recipient, sending IP, domain, campaign stream, or receiver grouping.
- Apply window: Use consecutive bounce days for soft failures and immediate suppression for confirmed permanent failures.
- Review drift: Sample raw replies each week so provider-specific text changes do not silently break your rules.
Testing matters because bounce handling is downstream of delivery setup. When I change DNS, sender identity, content templates, or routing, I send a real test and inspect headers, authentication, and visible failures before I blame the list. That does not replace production bounce logs, but it catches obvious configuration problems early.
Email tester
Send a real email to this address. Suped opens the report when the test is ready.
?/43tests passed
Preparing test address...
For daily campaigns, I also split rules by mail stream. Transactional mail, preference-based alerts, newsletters, and promotional campaigns should not always share the same suppression timing. A subscriber who cannot receive a marketing campaign can still need account or purchase mail, and a transactional hard bounce can tell you more about address quality than a one-off promotional deferral.
Example daily sender suppression policytext
confirmed_invalid_user: suppress immediately confirmed_invalid_domain: suppress immediately mailbox_full: pause after 7 bounce days mailbox_full: suppress after 10-14 bounce days transient_failure: pause after 3-5 bounce days rate_limit: throttle stream, do not suppress recipient policy_or_auth_failure: investigate sender, do not suppress recipient unknown_response: quarantine and sample raw replies
Views from the trenches
Best practices
Count one bounce day per recipient so high frequency does not overstate failures.
Separate mailbox full, rate limits, policy blocks, and invalid users before suppression.
Reset active counters after accepted delivery, while retaining older failures for review.
Common pitfalls
Treating every 5.x response as permanent can suppress valid users during policy blocks.
Substring matching turns similar codes into wrong actions, especially in 5.7.x failures.
Removing mailbox full immediately is too strict for subscribers who receive daily mail.
Expert tips
Review bounce reasons by receiver family before changing thresholds across all streams.
Quarantine unknown replies first, then promote only verified patterns into automation.
Audit old rule maps quarterly because receiver messages and provider behavior change.
Marketer from Email Geeks says classification decides the next action because failed mail can mean invalid user, temporary limits, or a sender-side policy problem.
2026-02-14 - Email Geeks
Marketer from Email Geeks says a mailbox that stays full for 10 days in a daily program often looks abandoned, but immediate removal is too strict.
2026-02-16 - Email Geeks
My bottom line
For daily campaigns, I use decisive suppression for confirmed hard bounces and slower, reason-based handling for soft bounces. Mailbox full should not be an instant removal. Repeated mailbox-full days can justify suppression, but the counter should run by day, not by message, when a subscriber can receive multiple campaigns per day.
The strongest bounce programs store the raw reply, classify by reason and receiver, separate recipient problems from sender problems, and keep the rule map under review. That gives you clean lists without hiding authentication, reputation, or strategy issues behind a generic hard-bounce label.
