# Email validation vs verification vs deliverability

_2026-07-18 · Boundstone (https://boundstone.io/blog/email-validation-vs-verification)_


You searched "email validation vs verification" because someone — a vendor's pricing page, a teammate, a bounce report — used the two words as if they were interchangeable, and you need to know whether they describe the same thing. They do not. There are three distinct layers hiding inside those words, plus a fourth thing, deliverability, that is not a check at all but an outcome. Conflating them is how you end up paying for a "verified" list that still bounces.

## Three words, three different questions

Strip the marketing off and each term answers a specific question:

- **Validation** asks: is this string shaped like an email address? That is syntax.
- **Verification** asks: could this address actually receive mail? That question splits in two — *domain* verification (does the domain accept mail at all?) and *mailbox* verification (does this specific inbox exist?).
- **Deliverability** asks: will *your* message reach the inbox? That depends mostly on you, not on the address.

Most tools blur these together on purpose, because "verified" sounds more expensive than "we checked the syntax." Keep them separate and you can tell exactly what you are buying.

## Layer 1: syntactic validation (your stdlib already does this)

The cheapest layer is free and you already have it. Every language ships a way to catch the obvious garbage — missing `@`, no dot in the domain, a trailing space. Often that is genuinely all you need to stop a fat-fingered signup form from writing junk to your database.

```python
import re

# Pragmatic shape check — good enough to reject obvious garbage.
EMAIL = re.compile(r"^[^@\s]+@[^@\s]+\.[^@\s]+$")

def looks_like_email(value: str) -> bool:
    return bool(EMAIL.match(value.strip())) and len(value) <= 254
```

This tells you the string *looks* like an address. It tells you nothing about whether the domain exists or the mailbox is real. If a client-side check is all you're after, use the free [email validator tool](/tools/email-validator) and stop there — no account, no API call.

## Layer 2: domain verification (the MX record)

The first thing your form validator cannot answer is whether the domain can receive mail at all. That is a DNS question: does the domain publish a mail exchanger (MX) record? No MX (and no fallback A record) means no mailbox is reachable there, no matter how well-formed the address is. This is where typo domains like `gmial.com` get caught.

```bash
dig +short MX acme.io
```

An MX lookup is a real network round trip, and doing it reliably across millions of rows — with fallbacks, timeouts, and caching — is more than a one-liner. If you want the mechanics, we wrote them up in [what is an MX record](/blog/what-is-an-mx-record). Boundstone performs this check and returns it as `mx_found`.

## Layer 3: mailbox verification (SMTP) — and why "yes" often lies

The deepest layer is mailbox verification: opening an SMTP conversation with the receiving server and asking, in effect, "does `jane@acme.io` exist?" This is the layer most vendors mean when they charge for "verification." It is also the layer we deliberately do **not** perform, because an SMTP "yes" is frequently meaningless:

- **Catch-all domains** accept mail for *every* local part. `anything@acme.io` returns `250 OK` whether or not the mailbox exists. The "yes" is noise.
- **Accept-then-bounce.** Plenty of servers accept at SMTP time, queue the message, then bounce it minutes later. The probe said yes; the mail still failed.
- **Greylisting** temporarily rejects unknown senders, so a real mailbox reads as a soft failure.
- **Reputation cost.** Hammering strangers' mail servers with probe connections is how your sending IPs get onto blocklists.

So an SMTP check is unreliable *and* expensive to your own reputation. That is why Boundstone marks `smtp_mailbox` and `catch_all` as `not_performed` rather than shipping a confident answer we cannot stand behind. Carrier-grade liveness does exist for phone, as a paid opt-in (`hlr:true`); SMTP mailbox probing is a check we are choosing not to fake.

## Deliverability is a separate outcome

Now the fourth word. Even a real, reachable mailbox does not guarantee your email lands in the inbox. Deliverability is decided at send time by your sender reputation, your SPF, DKIM, and DMARC alignment, the message content, list hygiene, and how recipients engage. None of that is knowable from a point-in-time address lookup, so no validation API — including this one — can promise it. Anyone who does is selling you a feeling.

## What Boundstone returns (and what it doesn't)

Here is the actual contract. One request, one response, every field labelled:

```bash
curl -s https://api.boundstone.io/v1/verify/email \
  -H "Authorization: Bearer bs_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"email":"billing@acme.io"}'
```

```json
{
  "valid_syntax": true,
  "domain": "acme.io",
  "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"]
  }
}
```

Past the stdlib layer, the API adds the checks you cannot cheaply run yourself: a live MX lookup, a disposable-domain list (throwaway inboxes), and role-account detection (`billing@`, `sales@`, `noreply@` — addresses that inflate a list and rarely convert). The `free_provider` field flags consumer mailboxes like Gmail or Outlook; note it is a returned signal, not a member of `checks.performed`. Every response carries the same shape across every language and client, so you write your bounce logic once. Full field reference lives in the [docs](/docs).

The `not_performed` array is the point, not an apology. When Boundstone returns `"valid_syntax": true` with `"mx_found": true`, it means exactly that — the shape is right and the domain accepts mail — and it refuses to imply the mailbox itself is confirmed. A "valid" you can trust is one that tells you where it stops.

## The short version

- **Validation** = syntax. Your language already does it; often that's enough.
- **Verification** = domain (MX, cheap and reliable) plus mailbox (SMTP, unreliable and reputation-costly).
- **Deliverability** = an outcome you earn at send time, not a field any API can return.
- **Boundstone does syntax, MX, disposable and role.** It marks `smtp_mailbox` and `catch_all` as `not_performed` — because a confident SMTP "yes" is often wrong, and we would rather show you the boundary than blur it.
