Bounce Management: Complete Technical Guide
Soft bounce vs hard bounce handling, SMTP retry logic, bounce categorization, and automated suppression workflows
Understanding Bounce Types
Bounce management is critical for maintaining sender reputation. Every bounce sends a signal to ISPs about list quality and sending practices. Mishandling bounces—particularly continuing to send to addresses that have hard bounced—is one of the fastest ways to damage IP reputation.
Hard Bounce
Permanent delivery failure. The recipient's email address is invalid, the domain no longer exists, or the server has permanently rejected mail. Hard bounces must be removed from sending lists immediately—continuing to send to these addresses signals spam behavior to ISPs.
Common causes: Typo in email address, closed account, non-existent domain, server explicitly refusing mail
Soft Bounce
Temporary delivery failure. The email was initially accepted but couldn't be delivered due to a recoverable issue. Soft bounces should be retried according to a policy but removed after multiple failures.
Common causes: Mailbox full, server busy, message too large, content filtering
Block (Technical Rejection)
Server is actively rejecting mail, often due to reputation issues. This is the most serious bounce type and requires immediate investigation. Blocks indicate your IP or domain is on a blacklist or has severe reputation problems.
Common causes: IP on blacklist, SPF/DKIM failure, DMARC policy rejection, ISP filtering
SMTP Bounce Codes
Understanding SMTP enhanced status codes is essential for proper bounce categorization and automated handling.
| Code | Meaning | Type | Action |
|---|---|---|---|
| 550 5.1.1 | User unknown | Hard | Immediate suppression |
| 550 5.1.2 | Host unknown | Hard | Immediate suppression |
| 550 5.1.10 | Policy action not permitted | Block | Investigate, check authentication |
| 450 4.1.2 | Recipient address soft bounce | Soft | Retry with backoff |
| 450 4.2.0 | Mailbox temporarily unavailable | Soft | Retry later |
| 452 4.2.2 | Mailbox full | Soft | Retry, then suppress |
| 554 5.6.0 | Invalid message content | Block | Review content, check formatting |
📡 Enhanced Status Code Structure
SMTP codes follow format: Class.Subject.Detail (e.g., 5.1.1 = permanent failure, mailbox unknown).
Class: 4.x.x = temporary (soft), 5.x.x = permanent (hard)
Subject: 1=address, 2=mailbox, 3=system, 4=network, 5=security, 6=protocol
Retry Logic and Policies
Not all soft bounces should be retried immediately. Proper retry logic implements exponential backoff to avoid overwhelming temporarily overloaded servers.
Retry Schedule Algorithm
// Exponential backoff retry scheduler
const RETRY_CONFIG = {
maxRetries: 4,
baseDelay: 15, // minutes
maxDelay: 1440, // 24 hours
backoffMultiplier: 2
};
function calculateNextRetry(attemptCount, lastAttempt) {
const delayMinutes = Math.min(
RETRY_CONFIG.baseDelay * (RETRY_CONFIG.backoffMultiplier ** attemptCount),
RETRY_CONFIG.maxDelay
);
return new Date(lastAttempt.getTime() + delayMinutes * 60000);
}
// Retry decision matrix
function shouldRetry(bounceCode, attemptCount) {
if (bounceCode.startsWith("5.")) return false; // Permanent - no retry
if (bounceCode.startsWith("4.") && attemptCount < RETRY_CONFIG.maxRetries) return true;
return false;
}
Retry Decision Flow
// Bounce event handler
function handleBounce(emailAddress, bounceResponse, smtpResponse) {
const bounceType = classifyBounce(smtpResponse);
const bounceCode = extractEnhancedCode(smtpResponse);
if (bounceType === "hard") {
// Immediate suppression - never retry
suppressAddress(emailAddress, {
reason: "hard_bounce",
code: bounceCode,
timestamp: new Date()
});
updateListStats("hard_bounce");
}
else if (bounceType === "soft") {
if (shouldRetry(bounceCode, currentAttemptCount)) {
const nextRetry = calculateNextRetry(currentAttemptCount, new Date());
scheduleRetry(emailAddress, nextRetry);
} else {
// Max retries exceeded - suppress
suppressAddress(emailAddress, {
reason: "soft_bounce_max_retries",
code: bounceCode,
attempts: currentAttemptCount
});
}
}
else if (bounceType === "block") {
// Investigate before any more sends
quarantineIPForInvestigation(sendingIP);
alertOperations("Block detected - investigation required");
}
}
Suppression List Management
Suppression lists protect sender reputation by preventing further sends to addresses that have already bounced. They should be maintained separately from normal list management and applied at campaign send time, not just at bounce detection.
Suppression Entry Schema
// Suppression list entry
{
email: "bounced@example.com",
reason: "hard_bounce" | "soft_bounce_max_retries" | "complaint" | "unsubscribe",
code: "550 5.1.1", // Original SMTP response
firstSeen: "2026-01-15T10:30:00Z",
lastSeen: "2026-01-15T10:30:00Z",
suppressionCount: 1, // Times we suppressed send attempts
expiresAt: "2027-01-15T10:30:00Z" // Auto-cleanup after 1 year
}
Applying Suppression at Send Time
async function sendCampaignEmail(recipient, campaignId) {
// Check suppression before anything else
const suppression = await checkSuppressionList(recipient);
if (suppression) {
logSuppressedSend(recipient, campaignId, suppression.reason);
return { status: "suppressed", reason: suppression.reason };
}
// Proceed with send...
return await deliverEmail(recipient, campaignId);
}
⚠️ Suppression vs List Removal
Do NOT simply delete bounced addresses from your list. Suppression is different: the address stays in your system but is flagged so you don't attempt to send again. Some addresses may appear to "recover" (mailbox was full, now isn't) but standard practice is to never retry these without explicit re-permission.
Bounce Rate Thresholds by ISP
Exceeding these thresholds will result in ISP filtering or blacklisting:
| ISP | Hard Bounce Limit | Soft Bounce Limit | Total Bounce Limit |
|---|---|---|---|
| Gmail | 0.5% | 2.0% | 2.5% |
| Outlook | 1.0% | 3.0% | 4.0% |
| Yahoo | 0.8% | 2.5% | 3.3% |
| iCloud | 0.3% | 1.5% | 1.8% |
| AOL | 1.0% | 3.0% | 4.0% |
CloudMails Bounce Management
CloudMails infrastructure includes automated bounce handling:
- Real-time bounce classification using enhanced SMTP codes
- Automatic suppression list updates
- Configurable retry policies with exponential backoff
- Per-ISP threshold monitoring with automatic throttling
- Bounce analytics dashboard with trend analysis
- Webhook notifications for hard bounces