← Blog

How to reduce your email bounce rate

Most of your hard bounces are visible before you press send; the rest belong to the receiving server, and no validator can see them for you.

Contents

If you want to reduce your email bounce rate, the useful first move is to split "bounce" into two problems, because they have two different fixes. Most advice blurs them together, promises you a magic number, and skips the part where it admits what it cannot do. This post does the opposite: it shows you the bounces you can remove before you send, and it is honest about the ones that only the receiving mail server knows about.

Hard bounces and soft bounces are not the same problem

A bounce is the receiving server declining your message. There are two flavours, and they call for opposite responses.

A soft bounce is temporary. The mailbox is full, the server is busy, the message is too large. Retry later and it may go through.

A hard bounce is permanent. The domain does not exist, there is no mail server behind it, or the address is garbage. Retrying does nothing except make you look careless.

That last part is the whole reason to care. Mailbox providers watch your hard-bounce rate as a proxy for how well you manage your list. A steady drip of permanent failures reads like you are mailing addresses you never checked, and your sender reputation — the thing that decides whether the good addresses even reach the inbox — pays for it. Soft bounces are noise. Hard bounces are the ones that compound.

The hard bounces you can see coming

Some hard bounces are unavoidable: an address that was real yesterday and got deleted this morning is invisible to everyone until you mail it. But a meaningful share of them are sitting in your list right now, visible before you press send:

  • Malformed syntaxjane@@example, a trailing comma, a fat-thumbed space. It was never a valid address.
  • A domain with no MX record — the domain resolves, but nothing behind it accepts mail. Every message to it hard-bounces.
  • A disposable domain — a throwaway inbox the signup used once and abandoned. It technically accepts mail, but it is dead weight and a spam-trap risk.

These are the avoidable hard bounces. You do not need anyone's permission or a paid provider to catch the first category — your language already does. The point is to catch all three before the send, not after the bounce report.

Validate before you send

The pattern is a gate: check each address, and only queue the ones that clear syntax, have a mail server, and are not disposable. Here is that gate against Boundstone's email endpoint. A single request returns the three signals you need.

import requests

API = "https://api.boundstone.io/v1/verify/email"
HEADERS = {"Authorization": "Bearer bs_live_YOUR_KEY"}

def should_send(email: str) -> bool:
    r = requests.post(API, json={"email": email}, headers=HEADERS, timeout=10)
    r.raise_for_status()
    data = r.json()

    # The avoidable hard bounces: bad syntax, no mail server, throwaway domain.
    if not data["valid_syntax"]:
        return False
    if not data["mx_found"]:
        return False
    if data["disposable"]:
        return False

    return True

for address in ["jane@example.com", "not-an-email", "user@mailinator.com"]:
    print(address, "->", "send" if should_send(address) else "skip")

A valid, deliverable-looking address comes back like this:

{
  "valid_syntax": true,
  "domain": "example.com",
  "mx_found": true,
  "disposable": false,
  "role_account": true,
  "free_provider": false,
  "checks": {
    "performed": ["syntax", "mx", "disposable_list", "role_list"],
    "not_performed": ["smtp_mailbox", "catch_all"]
  }
}

role_account and free_provider are there as judgement calls, not hard filters. A role address like support@ or sales@ is a mailing-list decision, not a bounce risk, so this gate leaves it in. Note that free_provider is reported but is deliberately not listed under checks.performed — it is a hint about the address, not a deliverability verdict.

What validation cannot promise — and why that is the useful part

Look again at checks.not_performed: ["smtp_mailbox", "catch_all"]. This is not fine print. It is the reason you can trust the valid_syntax and mx_found above it.

Boundstone does not perform SMTP mailbox verification, and it does not perform catch-all detection. That means validation cannot prove a specific mailbox exists, and it cannot guarantee your message lands. mx_found: true tells you the domain is ready to receive mail; it does not tell you jane is a real account behind it. Only the receiving server knows that, and it will only tell you when you actually send — which is the moment the bounce happens.

So be precise about the win. Validating syntax, MX, and disposable status removes the hard bounces you can see coming. It does not remove the ones only the receiving server can see. Any tool that claims otherwise is either running live SMTP probes (which have their own reputation cost) or lying to you. Boundstone would rather show you the empty column than pretend it is full. If you want the longer version of that distinction, see email validation vs verification.

Where the standard library stops and the API starts

Reach for the free option first, because it is often all you need. Python's email.utils.parseaddr, a decent regex, or a library like email-validator will catch malformed syntax for zero dollars and zero network calls. If your list problem is mostly typos and paste errors, stop there — you have handled the cheap, common majority for free.

The API earns its place at the next layer: live MX resolution, a maintained disposable-domain list, and one consistent response contract across every language your stack speaks, so the gate above looks the same in Python, Node, or Go. If you would rather see it than read about it, the keyless email validator runs the exact same checks in the browser with no signup, and there is a full validate-email-in-Python walkthrough if that is your stack.

The short version

  • Split your bounces. Soft bounces are temporary and mostly harmless; hard bounces damage sender reputation.
  • Kill the avoidable hard bounces before you send: bad syntax, no MX record, disposable domain. Those three checks are one request.
  • Start with your standard library. It catches malformed addresses for free.
  • Use the API for the layer past that: live MX, disposable lists, one contract across clients.
  • Believe the honest limit. Validation cannot prove a mailbox exists or guarantee delivery — smtp_mailbox and catch_all are not_performed, and that admission is exactly why the valid_syntax and mx_found next to it mean something.

Frequently asked questions

What causes a high email bounce rate?

Bounces usually come from addresses that were never deliverable in the first place: typos and malformed addresses, domains with no working mail (MX) records, and disposable or throwaway addresses collected at signup. Role-based addresses like info@ or support@ also tend to bounce or get filtered more often than personal inboxes. Catching these before you send is the most reliable way to lower your bounce rate, because you can't un-send to a bad address. Boundstone's email check flags exactly these signals in one lookup, reporting valid_syntax, mx_found, disposable, and role_account so you can drop risky contacts up front.

Does verifying an email address guarantee it won't bounce?

No, and any tool that promises a guarantee is overstating what it can actually know. Boundstone reports an address as valid when the syntax is correct, the domain has working mail (MX) records, and it is not on a disposable or role-account list, which removes the most common bounce causes. But it is deliberately honest about the limits: it does not open an SMTP connection to confirm the specific mailbox exists, and it does not attempt catch-all detection, so a syntactically valid address on a live domain can still be an empty inbox. Treat validation as sharply reducing your bounce risk, not eliminating it entirely.

How do I check a whole email list for bounce risk before a campaign?

Upload the list as a CSV to Boundstone's bulk email endpoint, which checks each address for valid syntax, working MX records, disposable domains, role accounts, and whether it is a free-provider mailbox. The free tier handles up to 250 rows per job with no card required, and credits are reserved per row and refunded automatically for any row that errors. Use the results to remove malformed and disposable addresses before you send, since that is where most bounces originate. Just remember the check confirms deliverability signals like a real domain and clean syntax rather than opening each mailbox, so pair it with basic list hygiene such as removing long-inactive contacts.

Thomas Tsui

Founder of Boundstone — building phone, email and IP validation you can actually verify.

One honest API for email, phone and IP — every response lists what it checked and what it didn't claim to. Free tier: 250 credits/month, no card, credits never expire.

More from Boundstone — API documentation · Benchmark methodology · The benchmark series · Buyer's checklist