An email bounce occurs when a message you send cannot be delivered to the recipient's mailbox and is returned to the sender with a failure notification. While a single bounce might seem insignificant, a high bounce rate erodes your sender reputation over time, causing more and more of your legitimate email to be filtered to spam or rejected outright. This guide explains the critical difference between Hard Bounces and Soft Bounces, how to read SMTP error codes, analyze mail server logs, and implement fixes that genuinely reduce your bounce rate.
How Email Delivery Works and Why Bounces Occur
When you send an email, your Mail Transfer Agent (MTA) opens an SMTP connection to the destination mail server. The receiving server then responds with a status code that indicates whether it accepts the message, is temporarily unavailable, or permanently rejects delivery. If the server cannot accept the message, it generates a Non-Delivery Report (NDR) — also called a Bounce Message — and returns it to the sender.
A bounce message contains three critical pieces of information: the SMTP status code, the Enhanced Status Code (ESC) providing additional context, and a human-readable diagnostic string. Understanding how to parse this information is the starting point for fixing delivery problems effectively.
What Is a Hard Bounce?
A Hard Bounce is a permanent delivery failure. The receiving server responds with a 5xx SMTP code indicating that no amount of retrying will result in successful delivery. The sending MTA records the failure and stops attempting retransmission immediately.
The most common causes of Hard Bounces include:
- Non-existent email address — The mailbox does not exist on the destination server, often due to a typo (e.g., gmial.com instead of gmail.com) or a deleted account. Servers typically respond with
550 5.1.1 User Unknown. - Invalid or non-existent domain — The domain has no MX records in DNS, the domain has expired, or the domain was never valid. The sending MTA cannot resolve a delivery target.
- Permanent policy rejection — The receiving server has a permanent rule rejecting mail from your IP or domain. Typical response:
550 5.7.1 Message rejected due to policy. - Deactivated or suspended account — The user's account has been closed or suspended by the organization. The mailbox exists in name but no longer accepts mail.
Hard Bounces are serious because each one is a direct signal to receiving infrastructure that your list hygiene is poor. Google, Microsoft, and Yahoo use bounce rates as a key factor in their filtering decisions — senders with consistently high hard bounce rates see their mail routed to spam or blocked entirely.
What Is a Soft Bounce?
A Soft Bounce is a temporary delivery failure. The receiving server responds with a 4xx SMTP code indicating that it cannot accept the message right now but may be able to do so later. The sending MTA queues the message and retries delivery on a schedule — typically every 15-30 minutes with increasing intervals — for a period of 24 to 72 hours before giving up and generating a bounce notification.
Common causes of Soft Bounces include:
- Mailbox over quota — The recipient's inbox has exceeded its storage limit. The server responds with
452 4.2.2 Mailbox full. The message will be queued until the recipient frees space. - Receiving server temporarily unavailable — The destination server is down for maintenance, experiencing high load, or has a temporary network issue. Response:
421 4.3.2 Service temporarily unavailable. - Message size exceeds limit — The email (including attachments) is larger than the receiving server's configured maximum. Response:
552 5.3.4 Message size exceeds limit. - Rate limiting — You are sending too many messages too quickly to a single domain, and the receiving server is throttling incoming connections. Response:
421 4.7.0 Too many connections.
While individual soft bounces are a normal part of email delivery, a Soft Bounce that repeats multiple times against the same address is a warning sign. Many email platforms automatically convert a repeated Soft Bounce into a Hard Bounce to prevent indefinite retry loops.
Hard Bounce vs Soft Bounce: SMTP Code Reference
| Type | SMTP Code | Enhanced Code | Meaning | Action |
|---|---|---|---|---|
| Hard | 550 |
5.1.1 |
User Unknown / mailbox does not exist | Remove from list immediately |
| Hard | 551 |
5.1.6 |
User not local; forwarding not permitted | Remove from list |
| Hard | 554 |
5.7.1 |
Rejected — spam or policy violation | Check Blacklist + SPF/DKIM/DMARC |
| Soft | 421 |
4.3.2 |
Service unavailable / rate limit | Let MTA retry automatically |
| Soft | 452 |
4.2.2 |
Mailbox full / over quota | MTA retry; notify recipient if persistent |
| Soft | 452 |
4.3.1 |
Insufficient system storage | MTA retry automatically |
Reading and Analyzing Bounce Logs
Effective bounce management starts with reading the MTA log directly. The two most common MTAs in Linux hosting environments are Postfix and Exim. Both record detailed bounce information that tells you exactly why delivery failed — not just that it failed.
Analyzing Postfix Logs
Postfix logs are typically found at /var/log/maillog or /var/log/mail.log. Lines containing bounce events are marked with status=bounced.
# View all bounce events in Postfix log grep "status=bounced" /var/log/maillog | tail -50 # Example output: # Jun 9 10:23:11 mailserver postfix/smtp[1234]: ABC123: to=<[email protected]>, # relay=mail.example.com[93.184.216.34]:25, # status=bounced (host mail.example.com said: # 550 5.1.1 The email account does not exist) # Count bounces grouped by destination domain grep "status=bounced" /var/log/maillog \ | grep -oP 'to=<[^@]+@\K[^>]+' \ | sort | uniq -c | sort -rn | head -20
Analyzing Exim Logs
Exim is used by DirectAdmin and many shared hosting environments. The main log is at /var/log/exim_mainlog. Bounce events are marked with **.
# View bounce events in Exim log grep " \*\* " /var/log/exim_mainlog | tail -50 # Example output: # 2026-06-09 10:25:00 1lOXxx-0000YY-00 ** [email protected] # R=dnslookup T=remote_smtp: SMTP error after RCPT TO: # 550 5.1.1 User unknown # Count today's bounces grep "$(date '+%Y-%m-%d')" /var/log/exim_mainlog | grep " \*\* " | wc -l
Fixing Hard Bounces Systematically
Hard bounces require immediate and systematic action. The steps below address the root causes rather than just the symptoms.
Step 1 — Remove Bounced Addresses From Your List
Any email address that generates a Hard Bounce must be removed from your mailing list immediately and never retried. Continued sending to known-invalid addresses is one of the clearest spam signals that filtering systems use. The following Python script extracts unique hard-bounced addresses from a Postfix log:
import re
bounced_emails = set()
with open('/var/log/maillog') as f:
for line in f:
if 'status=bounced' in line:
match = re.search(r'to=<([^>]+)>', line)
if match:
bounced_emails.add(match.group(1).lower())
with open('hard_bounce_list.txt', 'w') as out:
for email in sorted(bounced_emails):
out.write(email + '\n')
print(f"Found {len(bounced_emails)} hard-bounced addresses")
Step 2 — Verify and Fix Your DNS Authentication Records
A significant proportion of Hard Bounces, especially those with 554 5.7.1 or 550 5.7.26 codes, result from SPF, DKIM, or DMARC misconfigurations. The receiving server rejects email because it cannot verify that it genuinely originates from your domain.
# Check SPF record dig TXT yourdomain.com | grep "v=spf1" # Check DKIM public key dig TXT selector1._domainkey.yourdomain.com # Check DMARC policy dig TXT _dmarc.yourdomain.com # A correct SPF record looks like: # "v=spf1 mx a ip4:your.server.ip include:mail.provider.com ~all" # A correct DKIM record looks like: # "v=DKIM1; k=rsa; p=MIGfMA0GCSq..." # A monitoring DMARC record (start here): # "v=DMARC1; p=none; rua=mailto:[email protected]"
Step 3 — Check and Resolve Blacklist Listings
If Hard Bounces are occurring across multiple destination domains with policy rejection codes, your sending IP or domain may be blacklisted. Use the following method to check against Spamhaus — the most widely used blacklist:
# Check an IP against Spamhaus ZEN (reverse the octets first) # Example: checking 93.184.216.34 → query 34.216.184.93.zen.spamhaus.org dig 34.216.184.93.zen.spamhaus.org A # If the query returns 127.0.0.x = LISTED (blocked) # If the query returns NXDOMAIN = NOT LISTED (clean) # Check multiple lists at once using MXToolbox (manual): # https://mxtoolbox.com/blacklists.aspx # After delisting: # 1. Fix the root cause (spam complaints, compromised account) # 2. Submit delisting request to each list # 3. Monitor for re-listing over the next 30 days
Reducing Soft Bounces and Unnecessary Retries
Most Soft Bounces resolve automatically through the MTA's retry mechanism. However, when specific Soft Bounce types recur persistently, proactive intervention is more efficient than waiting.
Handling Repeated Mailbox Full Bounces (452)
If a key contact's mailbox repeatedly appears full, contact them through an alternative channel (phone, instant messaging) to let them know. For users on your own server, you can increase their quota through DirectAdmin or the command line:
# Increase mailbox quota via DirectAdmin API curl -k "https://your-server:2222/CMD_API_EMAIL_QUOTA" \ -u admin:password \ -d "domain=yourdomain.com&user=username"a=1024" # quota value is in MB
Configuring Postfix Send Rate Limits to Avoid 421 Errors
When sending bulk email, per-domain rate limits prevent you from triggering 421 throttling responses from large providers. Configure these in Postfix:
# /etc/postfix/main.cf — rate limiting configuration smtp_destination_rate_delay = 1s # 1 second delay between messages smtp_extra_recipient_limit = 10 # max 10 recipients per connection default_destination_concurrency_limit = 2 # max 2 simultaneous connections per domain smtp_destination_recipient_limit = 50 # max 50 recipients per destination # Apply changes postfix reload
Pro Tip: Before sending any large email campaign, run an Email List Verification pass to remove invalid addresses before they become bounces. Combine this with Double Opt-In for all new signups. Your target before sending should be a predicted Hard Bounce Rate below 2% and a Soft Bounce Rate below 5%.
Protecting Sender Reputation with SPF, DKIM, and DMARC
Properly configured email authentication is the single most effective way to prevent Policy Rejection bounces. Starting in 2024, Google and Yahoo made SPF, DKIM, and DMARC mandatory for bulk senders. Even for transactional email, these three records are essential.
SPF — Define Authorized Senders
# Complete SPF record example yourdomain.com. IN TXT "v=spf1 mx a ip4:192.0.2.1 include:sendgrid.net ~all" # Explanation: # mx = servers listed in MX records are authorized # a = A record of the domain is authorized # ip4:x.x.x = explicit IP authorization # include: = inherit authorization from another domain's SPF # ~all = softfail (mark but don't reject) — recommended during migration # -all = hardfail (reject immediately) — recommended for stable setups
DKIM — Cryptographic Signing
# Generate DKIM key pair (OpenSSL) openssl genrsa -out dkim_private.pem 2048 openssl rsa -in dkim_private.pem -pubout -out dkim_public.pem # The public key goes into DNS as a TXT record: # selector1._domainkey.yourdomain.com TXT "v=DKIM1; k=rsa; p=<BASE64_PUBLIC_KEY>" # Verify DKIM signing is working by checking email headers: # Look for: DKIM-Signature: v=1; a=rsa-sha256; d=yourdomain.com; s=selector1 # And verify result: Authentication-Results: dkim=pass
DMARC — Policy and Reporting
# Start with p=none (monitoring mode) _dmarc.yourdomain.com. IN TXT "v=DMARC1; p=none; rua=mailto:[email protected]" # After reviewing aggregate reports for 2-4 weeks, move to quarantine: "v=DMARC1; p=quarantine; pct=25; rua=mailto:[email protected]" # Gradually increase pct until reaching reject: "v=DMARC1; p=reject; rua=mailto:[email protected]; ruf=mailto:[email protected]"
Ongoing Bounce Rate Monitoring
Reducing your bounce rate is not a one-time fix — it requires continuous monitoring. The following tools and practices keep your bounce rate under control long-term:
- Google Postmaster Tools — Tracks your domain and IP reputation for Gmail delivery. Provides daily data on spam rates, authentication failures, and delivery errors.
- Microsoft SNDS — Smart Network Data Services provides reputation data for Outlook and Hotmail delivery.
- MXToolbox Email Health — Centralizes Blacklist checking, DNS record validation, and SMTP diagnostics in one place.
- Automated daily reporting — A cron-scheduled script that summarizes your bounce rate and alerts you if it exceeds a threshold.
#!/bin/bash
# /usr/local/bin/check_bounce_rate.sh
DATE=$(date '+%Y-%m-%d' -d "yesterday")
TOTAL=$(grep "$DATE" /var/log/maillog | grep "status=" | wc -l)
BOUNCED=$(grep "$DATE" /var/log/maillog | grep "status=bounced" | wc -l)
if [ "$TOTAL" -gt 0 ]; then
RATE=$(echo "scale=2; $BOUNCED * 100 / $TOTAL" | bc)
echo "Date: $DATE | Sent: $TOTAL | Bounced: $BOUNCED | Rate: ${RATE}%"
if (( $(echo "$RATE > 5" | bc -l) )); then
echo "ALERT: Bounce Rate exceeded 5% — immediate investigation required"
fi
fi
# Add to crontab to run at 08:00 daily:
# 0 8 * * * /usr/local/bin/check_bounce_rate.sh | mail -s "Daily Bounce Report" [email protected]
Frequently Asked Questions
What is the difference between a Hard Bounce and a Soft Bounce?
A Hard Bounce is a permanent delivery failure where the receiving server responds with an SMTP 5xx code, indicating the email can never be delivered. Common causes include non-existent addresses, invalid domains, and permanent policy blocks. These must be removed from your list immediately. A Soft Bounce is a temporary failure (SMTP 4xx), where the MTA queues the message and retries delivery for 24-72 hours. Common causes include full mailboxes, server downtime, and rate limiting.
What bounce rate is acceptable and when should I be concerned?
A Hard Bounce Rate below 2% is generally acceptable. Once you exceed 2%, your sender reputation begins to suffer. If your Hard Bounce Rate exceeds 5%, you risk IP or domain Blacklisting, which causes widespread delivery failures. You should clean your email list every 3-6 months and implement Double Opt-In to prevent accumulation of invalid addresses over time.
How do I read SMTP bounce error codes in mail logs?
SMTP codes fall into two groups: 4xx for temporary failures (Soft Bounce) and 5xx for permanent failures (Hard Bounce). Common examples: 421 = service temporarily unavailable or rate limiting, 452 = mailbox full or insufficient storage, 550 = mailbox does not exist or policy rejection, 554 = rejected as spam or violating policy. The enhanced status code provides more specificity — for example, 550 5.1.1 means User Unknown specifically.
How do I fix a high bounce rate caused by a Blacklist listing?
First check whether your IP or domain is blacklisted using MXToolbox or MultiRBL. If listed, investigate the root cause — spam complaints, a compromised account sending spam, or botnet activity — and resolve it first. Then submit a Delisting Request to each blacklist you appear on, explaining the corrective actions taken. Simultaneously, verify your SPF/DKIM/DMARC records are correctly configured, clean your email list of invalid addresses, and implement Double Opt-In to prevent future accumulation of bad addresses.
Business Email Hosting at Your Own Domain
AsiaGB Email comes with SPF, DKIM, and DMARC pre-configured for high deliverability. Starting from 200 THB/year.
View Email Plans