> Enrich.chat gives AI agents verified work emails and mobiles. To use it from an agent, read https://enrich.chat/agents.md . This is the Markdown version of https://enrich.chat/blog/email-validation/

# Email validation explained: what syntax, domain and mailbox checks can and cannot prove

Five checks, cheapest first, from RFC 5322 syntax to a confirmation link. See what each one catches, where each one fails, and what the labels in validation APIs mean.

By Enrich.chat Editorial. Updated October 16, 2026.

**Short answer:** Email validation is a set of automatic checks that estimate whether an address can receive mail without sending to it: a syntax check ([RFC 5322](https://www.rfc-editor.org/rfc/rfc5322.html)), a domain and MX lookup, an SMTP mailbox check ([RFC 5321](https://www.rfc-editor.org/rfc/rfc5321.html)), and catch-all, disposable and role flags. Each layer rules out one kind of bad address, but none proves a person reads the mailbox. Only a [confirmation link](https://cheatsheetseries.owasp.org/cheatsheets/Email_Validation_and_Verification_Cheat_Sheet.html) shows the owner controls it.

## Key takeaways

- Validation runs in layers, cheapest first: syntax, domain and MX, mailbox check, risk flags, then a confirmation link. Only the last one shows the owner controls the address.
- The HTML Standard calls the browser rule for type=email a willful violation of RFC 5322. It accepts jane@example and jane..doe@example.com, so treat it as a typo filter.
- A 250 reply to RCPT TO is not proof. Catch-all servers accept everyone, some servers check recipients only after the message arrives, and a 550 can mean policy, not a missing mailbox.
- Validation APIs return labels and flags, not verdicts: Mailgun has five results, ZeroBounce seven statuses and Hunter six. Hunter may return a result up to a month old.
- Enrich.chat is not a validation API. It returns a status (verified, catch_all or unknown) with each work email it finds, and its free catch-all checker tests a domain.

## What is email validation, and how is it different from verification?

Email validation is a set of automatic checks that estimate whether an address can receive mail, run without sending a message to it. The checks work in layers: syntax, the domain's mail records, a mailbox check against the mail server, and flags such as catch-all, disposable and role. A confirmation link is the only layer that needs the owner to act.

The two words have no standard split, and vendors use them in opposite ways. [Mailtrap](https://mailtrap.io/blog/email-verification/) uses validation for front-end checks of format and typos, and verification for sending an activation link or code to prove a person is on the other end. [Abstract API](https://www.abstractapi.com/guides/email-validation/what-is-email-validation) puts syntax, domain and mail server checks under validation. [Knock's free validator](https://www.knock.app/tools/email-validator) runs syntax, domain format, MX and disposable checks and calls its result a likelihood, not a guarantee. This guide says validation for any automatic check and confirmation for the click-a-link step. Figure 1 lists the five layers, cheapest first.

**Figure 1: Five email validation layers, cheapest first.** A five row table. Syntax asks if the address is shaped like name@domain and cannot tell if the domain or mailbox exists. Domain and MX asks if DNS shows a route for mail and cannot tell if the mailbox exists. The mailbox check reads the mail server reply and cannot see catch-all, delayed or blocked replies. Risk flags mark catch-all, disposable and role addresses and cannot tell if anyone reads the mailbox. Only a confirmation link shows the owner controls the address.

*The five layers of email validation, cheapest first, and what each leaves open. Layers 1 to 3 follow [RFC 5322](https://www.rfc-editor.org/rfc/rfc5322.html) and [RFC 5321](https://www.rfc-editor.org/rfc/rfc5321.html), the flags in layer 4 follow the documentation of [Mailgun](https://documentation.mailgun.com/docs/validate/single-valid-ir) and [Hunter](https://hunter.io/api-documentation/v2#email-verifier), and layer 5 follows [OWASP's guidance on ownership verification](https://cheatsheetseries.owasp.org/cheatsheets/Email_Validation_and_Verification_Cheat_Sheet.html).*

Each layer rules out one kind of bad address and leaves the next kind alone. Believing a layer proves more than it does is the usual mistake.

## How does an email syntax check work, and how strict should it be?

A syntax check tests whether the text is shaped like an address: a local part, one @ and a domain. The rulebook is [RFC 5322, section 3.4.1](https://www.rfc-editor.org/rfc/rfc5322.html#section-3.4.1). It allows a local part written as a dot-atom or a quoted string, and a domain written as a dot-atom or a domain literal such as [192.0.2.1]. The RFC calls its domain syntax liberal and says implementations must follow the syntax of the protocol that carries the address.

Browsers do not follow it. The HTML Standard defines a valid address for input type=email and calls that definition a [willful violation of RFC 5322](https://html.spec.whatwg.org/multipage/input.html#email-state-%28type=email%29), because the RFC syntax is too strict before the @, too vague after it and too lax in other ways. The table applies both rules to five addresses.

| Address | RFC 5322 | Browser type=email |
| --- | --- | --- |
| jane.doe@example.com | valid | valid |
| jane..doe@example.com | invalid | valid |
| jane@example | valid | valid |
| "jane doe"@example.com | valid | invalid |
| jane@[192.0.2.1] | valid | invalid |

The browser accepts jane@example, a domain with no dot, because the Standard's pattern allows a single label. It also accepts doubled dots that the RFC rejects. So the browser check is a typo filter. [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/input/email) says a passing value is formatted correctly but does not necessarily exist, and that you must not rely on the check for security, because it is easy to bypass.

Keep your own syntax check loose. [OWASP's cheat sheet](https://cheatsheetseries.owasp.org/cheatsheets/Email_Validation_and_Verification_Cheat_Sheet.html) says to use well-tested libraries instead of custom regex, because strict patterns often reject valid addresses, and to reject only clearly malformed input. A loose check can test for one @, text on both sides, no spaces and a total length of 254 characters or fewer. Our guide to [email address formats](https://enrich.chat/blog/email-address-formats/) explains where the 254 and 64 character limits come from.

## How do domain and MX checks work?

A domain check asks DNS whether mail can reach the domain. [RFC 5321, section 5.1](https://www.rfc-editor.org/rfc/rfc5321.html#section-5.1), tells a sender to look up the domain's MX records first. If the domain has none, the sender treats the domain's own address record as an implicit mail server. A domain that does not exist is an error, and a temporary DNS failure means the sender retries later.

That gives a validator three honest results: a mail route exists, no route exists, or DNS could not answer. Vendors report the first two as flags. [Abstract API](https://docs.abstractapi.com/api/email-validation) returns is_mx_found, [Mailgun](https://documentation.mailgun.com/docs/validate/single-valid-ir) returns a no_mx reason, and [ZeroBounce](https://www.zerobounce.net/docs/email-validation-api-quickstart/v2-status-codes) returns a no_dns_entries sub-status.

A domain can also say it takes no mail at all. [RFC 7505](https://www.rfc-editor.org/rfc/rfc7505.html) defines a null MX: a single MX record with preference 0 and a dot as the host name. Without one, a sender may retry delivery to a domain with no mail server for about a week before it gives up. With one, the sender fails at once, and the RFC says a server that rejects the recipient should use reply code 556 and status 5.1.10.

A domain check cannot catch a typo that lands on a real domain. [Spamhaus](https://www.spamhaus.org/resource-hub/deliverability/spamtraps-fix-the-problem-not-the-symptom/) lists typo domain traps among its trap types: look-alike domains such as homail.com that receive mail sent to mistyped addresses. An address there passes the syntax and domain checks, so only a typo suggestion or a confirmation link catches it.

### How do typo suggestions work?

A typo suggestion compares the domain with a list of common domains and offers the closest match. The [Mailcheck library](https://github.com/mailcheck/mailcheck) does this in the browser, for example turning sample@gmial.con into sample@gmail.com. Its README calls it a typo suggester, not an email validator, and says to show the suggestion rather than silently replace the address or block the person. Server-side APIs return the same hint: Mailgun's did_you_mean field, Abstract API's autocorrect field and the "Did you mean" output on [Emailable](https://emailable.com/email-verifier). Abstract adds that its other checks still run on the address as submitted. Treat a suggestion as a question for the person.

## How does a mailbox check work, and what does each reply mean?

A mailbox check opens an SMTP session with the domain's mail server, names the address as a recipient and reads the reply. [RFC 5321, section 3.3](https://www.rfc-editor.org/rfc/rfc5321.html#section-3.3), splits a mail transaction into three steps: MAIL, one or more RCPT commands, then DATA. A checker stops after RCPT, so no message is sent. The server answers 250 when it accepts the recipient and normally 550 when the recipient is known not to be deliverable.

The first digit of the reply tells the checker what to do next. Under [section 4.2.1](https://www.rfc-editor.org/rfc/rfc5321.html#section-4.2.1), a 2yz reply is success, a 4yz reply is temporary and may be retried, and a 5yz reply is permanent. The digits do not say why. [Section 4.2.2](https://www.rfc-editor.org/rfc/rfc5321.html#section-4.2.2) describes 550 as covering a mailbox that is not found, has no access, or was refused for policy reasons. The enhanced codes in [RFC 3463](https://www.rfc-editor.org/rfc/rfc3463.html) are more exact: X.1.1 means the mailbox does not exist, and X.7.1 means the sender is not authorized to send to it. So a 550 means "no such mailbox" only when the enhanced code says so. Figure 2 maps each reply to a label.

**Figure 2: From an RCPT TO reply to a label.** A four row map. A 250 reply means the recipient was accepted, so the checker names a made-up address at the same domain: a second 250 means accept-all and a 550 means accepted. A 450 or 451 reply is temporary, from greylisting or a limit, so retry later and then call it unknown. A 550 or 553 reply is permanent: a 5.1.1 status means no such mailbox and a 5.7.x status is a policy block, so rejected or unknown. No reply means a slow, blocking or unreachable server and the label is unknown.

*How a checker can turn an RCPT TO reply into a label. Reply classes come from [RFC 5321](https://www.rfc-editor.org/rfc/rfc5321.html#section-4.2.1), status meanings from [RFC 3463](https://www.rfc-editor.org/rfc/rfc3463.html), greylisting from [RFC 6647](https://www.rfc-editor.org/rfc/rfc6647.html), and the made-up address test from our [catch-all checker page](https://enrich.chat/tools/catch-all-checker/). The labels are this guide's own.*

### Why can a mailbox check be wrong?

- **The domain is catch-all.** The server says 250 to every recipient, real or not, and [Hunter's documentation](https://hunter.io/api-documentation/v2#email-verifier) warns that SMTP checks on such a server can give false positives. Our [catch-all checker](https://enrich.chat/tools/catch-all-checker/) and the guide to [catch-all emails](https://enrich.chat/blog/what-is-a-catch-all-email/) cover this case.
- **The server checks later.** RFC 5321 section 3.3 says some servers do not verify recipients until after the message text arrives. [Section 7.3](https://www.rfc-editor.org/rfc/rfc5321.html#section-7.3) adds that RCPT may then return no information at all, and the failure comes back as a bounce message.
- **Greylisting.** [RFC 6647](https://www.rfc-editor.org/rfc/rfc6647.html) defines greylisting as temporarily degraded service to unknown email clients. ZeroBounce lists greylisted as an unknown sub-status and says it often validates when you resubmit.
- **Blocks and timeouts.** Hunter's response has a block field that is true when the server prevented the SMTP check. A home-built check may not connect at all: [Google Cloud's documentation](https://docs.cloud.google.com/compute/docs/tutorials/sending-mail) says connections to external destinations on TCP port 25 are blocked, with exceptions for some projects.
- **A closed shortcut.** The older VRFY command asks a server whether a user exists, but a site that turns it off must answer 252, which is neither yes nor no.

### What does a mailbox check look like in code?

The sketch below runs a syntax check, then a mailbox check with a catch-all probe. You pass the mail host yourself, which would normally come from an MX lookup. Run it only against a server you operate or a stand-in, never against other people's mail servers. The table shows the results of running these exact lines against stand-in SMTP servers on localhost.

```
import re
import smtplib

ADDR = re.compile(
    r"^[A-Za-z0-9.!#$%&'*+/=?^_`{|}~-]+"
    r"@[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?"
    r"(?:\.[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?)+$"
)

def syntax_ok(address):
    local = address.rpartition("@")[0]
    return (
        len(address) <= 254
        and len(local) <= 64
        and not local.startswith(".")
        and not local.endswith(".")
        and ".." not in local
        and ADDR.match(address) is not None
    )

def rcpt_code(mx_host, address, port=25):
    with smtplib.SMTP(mx_host, port, timeout=10) as smtp:
        smtp.ehlo("check.example.com")
        smtp.mail("probe@example.com")
        code, _ = smtp.rcpt(address)
    return code

def check(mx_host, address, port=25):
    if not syntax_ok(address):
        return "bad syntax"
    domain = address.rpartition("@")[2]
    try:
        code = rcpt_code(mx_host, address, port)
        if code >= 500:
            return "rejected"
        if code >= 400:
            return "retry later"
        probe = rcpt_code(mx_host, "no-such-mailbox-7q2zk9@" + domain, port)
    except OSError:
        return "unknown"
    if probe < 300:
        return "accept-all"
    return "accepted" if probe >= 500 else "retry later"
```

| Address | Stand-in server | check() returns |
| --- | --- | --- |
| jane@acme | any | bad syntax |
| dana.lee@example.com | knows two mailboxes | accepted |
| nobody@example.com | knows two mailboxes | rejected |
| grey.sam@example.com | delays names that start with grey | retry later |
| dana.lee@example.com | accepts every recipient | accept-all |
| dana.lee@example.com | nothing is listening | unknown |

The final + in the domain pattern requires a dot, which is stricter than the browser rule. Accepted means the server said yes to this recipient and no to a made-up one. It is the best a mailbox check can report, and it still says nothing about the person. The sketch has no retry for greylisting, no rate limit and no handling for servers that block the check. For real lists, use a maintained library or an API.

## How do you spot catch-all, disposable and role addresses?

You spot them with flags that describe the kind of address, not whether the mailbox exists. The table lists four flags and how a validator finds each one.

| Flag | How a validator finds it | What to do |
| --- | --- | --- |
| Catch-all | The server accepts a made-up recipient. Mailgun calls it catch_all, Hunter calls it accept_all | Treat the mailbox as unconfirmed. Hold it, or send small batches |
| Disposable | The domain is on a list of throwaway providers | Prefer risk-based rules to a hard block |
| Role | The local part matches a name such as admin, sales or webmaster | Keep it off marketing lists |
| Free webmail | The domain is on a list of free providers such as Gmail | A label, not a defect |

Lists drive the disposable and webmail flags, so they age. The open [disposable-email-domains list](https://github.com/disposable-email-domains/disposable-email-domains) says it cannot guarantee that every domain on it is still disposable, only that each was at one point. It asks implementers to check the domain and each parent domain. OWASP advises risk-based controls over strict blocking. A disposable flag is a strong hint. A missing flag is not clearance.

Role addresses are real inboxes that belong to a job. [Spamhaus](https://www.spamhaus.org/resource-hub/deliverability/spamtraps-fix-the-problem-not-the-symptom/) says role addresses published in domain registration records, such as postmaster@, abuse@ and admin@, should almost never be on a marketing list. It also says addresses that ISPs switch off can be turned back on as spam traps after 12 months or more of hard bounces. ZeroBounce reports spamtrap and abuse as statuses of their own, and our [email bounce rate guide](https://enrich.chat/blog/email-bounce-rate/) covers how old lists turn into traps.

## What do email validation APIs return?

Validation APIs return a label, a set of flags and sometimes a score, not a plain yes or no. The same address can get different labels from different vendors, because each one runs its own checks and uses its own words. The table lists the verdict field and the extras from each vendor's documentation, read on October 16, 2026.

| API | Verdict values | Flags and extras |
| --- | --- | --- |
| Mailgun | result: deliverable, undeliverable, do_not_send, catch_all, unknown | risk level, reason list, did_you_mean, is_disposable_address, is_role_address |
| ZeroBounce | status: valid, invalid, catch-all, spamtrap, abuse, do_not_mail, unknown | sub_status such as greylisted, disposable, role_based, possible_typo |
| Hunter | status: valid, invalid, accept_all, webmail, disposable, unknown | score, smtp_check, accept_all, block, mx_records, gibberish |
| Abstract API | deliverability: DELIVERABLE, UNDELIVERABLE, UNKNOWN | quality_score, is_valid_format, is_mx_found, is_smtp_valid, is_catchall_email, autocorrect |
| Emailable | state: Deliverable, Risky, Undeliverable, Unknown | reason code, score, attributes such as Accept-All, Disposable, Role and Free, Did you mean |

Three details in those documents change how you should read a result. Abstract API advises against blocking sign-ups on a failed SMTP check alone. Hunter says it can return a verification made up to a month old, so the date in a response can be earlier than your request. ZeroBounce says credits for unknown results are refunded. A label is a reading from one moment, taken under one vendor's rules.

Whatever the vendor, you can sort every result into four actions. Send what the check confirms. Hold catch-all, risky and unknown results. Drop what is invalid or undeliverable. Fix typo suggestions with the person who typed them. Our guides cover the next steps: how to [choose an email verification API](https://enrich.chat/blog/email-verification-api/), a comparison of [email verification tools](https://enrich.chat/blog/email-verification-tools/), how to clean a list with [bulk email verification](https://enrich.chat/blog/bulk-email-verification/), and the label table in [cold email data](https://enrich.chat/blog/cold-email/).

## Where should you validate: at sign-up, on import or before a send?

Validate at three points, because each has a different job. A sign-up form needs a loose check and a confirmation link. A new list needs the full stack of checks. A send needs bounce handling and a re-check of old rows. Figure 3 shows the split.

**Figure 3: Where each email check belongs.** Three columns. At sign-up: a loose syntax check, a typo suggestion and a confirmation link, and never block on an SMTP result alone. On a new list: domain and MX, mailbox check and risk flags, and hold catch-all and unknown results. Before each send: re-check old rows, read bounce codes and suppress hard bounces at once, and keep one shared suppression list.

*Where each check belongs. Sign-up advice follows [OWASP](https://cheatsheetseries.owasp.org/cheatsheets/Email_Validation_and_Verification_Cheat_Sheet.html), [Yahoo's sender guide](https://senders.yahooinc.com/best-practices/) and [Abstract API's documentation](https://docs.abstractapi.com/api/email-validation). Send advice follows Yahoo's guidance on bounces.*

**At sign-up.** Check the shape of the address, offer a typo suggestion and send a confirmation link. [OWASP](https://cheatsheetseries.owasp.org/cheatsheets/Email_Validation_and_Verification_Cheat_Sheet.html) says to use single-use, time-limited tokens and not to activate an account before the address is verified. [Yahoo's sender guide](https://senders.yahooinc.com/best-practices/) recommends a confirmation email on subscription, because it keeps fake addresses and most robots off the list. Do not turn a visitor away because an SMTP check failed.

**On a list you did not collect.** Run the domain check, the mailbox check and the flags, then split the results as in the previous section. Hold catch-all and unknown rows back from the first send. Our guides to [bulk email verification](https://enrich.chat/blog/bulk-email-verification/) and [database hygiene](https://enrich.chat/blog/database-hygiene/) give the steps.

**Before and after each send.** Results age. Yahoo's guide says to monitor hard and soft bounces and to remove invalid recipients promptly. Our [email bounce rate](https://enrich.chat/blog/email-bounce-rate/) guide lists the limits that sending platforms enforce, and the [hard versus soft bounce](https://enrich.chat/blog/hard-bounce-vs-soft-bounce/) guide explains the codes.

## What can no email validation prove?

No validation proves that the right person reads the mailbox, that the address will keep working, or that you may email it. Each layer narrows the doubt, and none removes it.

- **A person reads it.** The [Mailcheck README](https://github.com/mailcheck/mailcheck) says even a correct suggestion does not prove that an address exists, accepts mail or belongs to a person.
- **The server meant yes.** RFC 5321 says a server that accepts a message and then cannot deliver it must send a failure notice (section 6.1). It also notes that silently dropping mail is permitted in practice, though dangerous (section 6.2). A 250 reply is a promise to try, not a delivery.
- **The address still works.** A work email follows the job, and a result is a reading from one moment. Our guide to [B2B data decay](https://enrich.chat/blog/b2b-data-decay/) compares published rates.
- **You may send to it.** A valid address is not consent, and no validator answers that legal question. Our guides to [cold email data](https://enrich.chat/blog/cold-email/) and [buying email lists](https://enrich.chat/blog/buying-email-lists/) cover the rules in short form. This is not legal advice.
- **The owner controls it.** Only a confirmation link or code shows that, and only for the person who used it.

## How does Enrich.chat handle email validation?

Enrich.chat is not an email validation API. It has no standalone endpoint for checking an address you already hold, and no bulk checker. What it does is attach a status to each work email it finds: `verified`, `catch_all` or `unknown`. The status is a label, not a delivery guarantee, and every contact is a strong lead, not a certainty.

| Question | Validation API | Enrich.chat |
| --- | --- | --- |
| You give it | An address you already have | A name and company website, a LinkedIn URL, or a work email to look up |
| You get back | A deliverability label and flags | The work email and a status: verified, catch_all or unknown |
| Typo, disposable and role flags | Yes, in most of the APIs above | Not returned |
| Charge | Per check, by each vendor's rules | Credits on a match only, 0 when nothing is found |

Here is a lookup for a fictional person on example.com. The response is illustrative.

```
GET https://enrich.chat/v1/email?name=Priya%20Nair&domain=example.com

{
  "found": true,
  "work_email": {"value": "priya.nair@example.com", "status": "verified"},
  "pattern": "first.last@example.com",
  "name": "Priya Nair",
  "title": "Head of Finance",
  "credits_used": 10,
  "free_lookups_remaining": 9
}
```

On a catch-all domain the same call returns the same shape with `"status": "catch_all"`, and a miss returns `{"found": false}` with nothing used. The same fields come back from `GET /v1/person` with a LinkedIn URL, or with a name and company website, and from the `find_work_email` tool on the MCP server. A work email found uses 10 credits. A list of 500 names needs 5,000 credits if every one matches, which fits the Growth plan at $29 a month.

The email input on `/v1/person` goes the other way: give it a work email and it looks up the person behind it. That tells you who, not whether the address delivers, and personal mailboxes such as Gmail are not looked up. Our [work-email lookup guide](https://enrich.chat/blog/who-owns-this-email-address/) covers it. To test a domain, use the free [catch-all checker](https://enrich.chat/tools/catch-all-checker/), which shows whether a domain accepts every address. The free [email finder](https://enrich.chat/tools/email-finder/) takes a name and company and returns an address with a status.

Know the gaps before you build on it:

- There is no standalone validation endpoint, and the self-serve plans have no bulk upload or export. To clean an existing list, use a verification API from the guides above.
- Responses carry no typo suggestion and no disposable or role flag.
- A search with `with_email=true` returns the work email with the status `unknown`. Use `/v1/person` or `/v1/email` when you need the status.
- A status is a label, not a delivery guarantee, so watch the bounce rate of your first batch.

This prompt sorts the results into send, hold and skip:

```text
Use www.enrich.chat to find the work email for each person in this list of names and company websites. Show the status exactly as returned. Put verified in a send group, catch_all and unknown in a hold group, and not found in a skip group. Never guess an address from a pattern.
```

Your agent gets 10 free lookups a day with no signup. After that, monthly plans start at $29 for 100,000 credits, as the [pricing page](https://enrich.chat/pricing/) shows. The [email finder API](https://enrich.chat/api/email-finder/) page covers the endpoint, the [install page](https://enrich.chat/install/) has steps for ChatGPT, Claude, Cursor and Codex, and the guide to [AI agents and contact data](https://enrich.chat/agents/) shows how an agent reads the API.

## Frequently asked questions

### What is the difference between email validation and email verification?

There is no standard split, and vendors use the words in opposite ways. [Mailtrap](https://mailtrap.io/blog/email-verification/) uses validation for format and typo checks and verification for proving a person controls the address with a link or code. [Abstract API](https://www.abstractapi.com/guides/email-validation/what-is-email-validation) puts syntax, domain and mail server checks under validation. This guide calls any automatic check validation and the click-a-link step confirmation. Read what a tool checks, not what it calls itself.

### How do you validate an email address without sending an email?

Run three checks in order. First test the syntax, loosely. Then look up the domain's MX records in DNS, as [RFC 5321](https://www.rfc-editor.org/rfc/rfc5321.html#section-5.1) describes. Then open an SMTP session, name the address in RCPT TO and read the reply, and quit before any message is sent. Treat the reply as a clue, because a catch-all server accepts every recipient. For sign-ups, add a confirmation link.

### Is a regex enough to validate an email address?

No. A regex tests shape only. The pattern in the [HTML Standard](https://html.spec.whatwg.org/multipage/input.html#email-state-%28type=email%29) is a willful violation of RFC 5322 and accepts jane@example and jane..doe@example.com, while a strict RFC pattern rejects addresses people really use. [OWASP](https://cheatsheetseries.owasp.org/cheatsheets/Email_Validation_and_Verification_Cheat_Sheet.html) advises well-tested libraries over custom regex. Use a loose pattern to catch typos, check the domain and mailbox, and confirm ownership with a link.

### Can you check whether an email address exists without sending mail?

Sometimes. An SMTP check names the address as a recipient and reads the reply, and a 550 with a 5.1.1 status means the mailbox is not there. But catch-all servers accept every recipient, some servers check only after the message arrives, and others delay or block checks. A good checker returns unknown instead of guessing. See the [free catch-all checker](https://enrich.chat/tools/catch-all-checker/).

### Why does an email validator say catch-all, accept-all or unknown?

Catch-all (accept-all) means the server said yes to every recipient, including one that cannot exist, so the mailbox cannot be confirmed. Unknown means the check could not finish: the server delayed it with a temporary reply, blocked it, timed out or refused the connection. Neither says the address is bad. Hold both back, send small batches if you must, and watch the [bounce rate](https://enrich.chat/blog/email-bounce-rate/).

### Does Enrich.chat validate email addresses?

No. Enrich.chat is not a validation API and has no standalone endpoint for testing an address you already hold. When it finds a work email for a person, the response carries a status: verified, catch_all or unknown. Its free [catch-all checker](https://enrich.chat/tools/catch-all-checker/) tests a domain. Treat every contact as a strong lead, not a guarantee. See the [email finder API](https://enrich.chat/api/email-finder/).

## Sources

1. [RFC 5322: Internet Message Format](https://www.rfc-editor.org/rfc/rfc5322.html)
2. [RFC 5321: Simple Mail Transfer Protocol](https://www.rfc-editor.org/rfc/rfc5321.html)
3. [RFC 3463: Enhanced Mail System Status Codes](https://www.rfc-editor.org/rfc/rfc3463.html)
4. [RFC 7505: A "Null MX" No Service Resource Record for Domains That Accept No Mail](https://www.rfc-editor.org/rfc/rfc7505.html)
5. [RFC 6647: Email Greylisting, an Applicability Statement for SMTP](https://www.rfc-editor.org/rfc/rfc6647.html)
6. [HTML Standard: the Email state (type=email)](https://html.spec.whatwg.org/multipage/input.html#email-state-%28type=email%29)
7. [input type="email"](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/input/email)
8. [Email Validation and Verification Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Email_Validation_and_Verification_Cheat_Sheet.html)
9. [Single Validation](https://documentation.mailgun.com/docs/validate/single-valid-ir)
10. [API Status Codes (v2)](https://www.zerobounce.net/docs/email-validation-api-quickstart/v2-status-codes)
11. [Email Verifier, Hunter API v2](https://hunter.io/api-documentation/v2#email-verifier)
12. [Email Validation API](https://docs.abstractapi.com/api/email-validation)
13. [Email Verifier](https://emailable.com/email-verifier)
14. [Mailcheck README](https://github.com/mailcheck/mailcheck)
15. [disposable-email-domains](https://github.com/disposable-email-domains/disposable-email-domains)
16. [Spamtraps: fix the problem, not the symptom](https://www.spamhaus.org/resource-hub/deliverability/spamtraps-fix-the-problem-not-the-symptom/)
17. [Sender best practices](https://senders.yahooinc.com/best-practices/)
18. [Sending email from an instance](https://docs.cloud.google.com/compute/docs/tutorials/sending-mail)
19. [Email Verification Explained](https://mailtrap.io/blog/email-verification/)
20. [What Is Email Validation and Verification?](https://www.abstractapi.com/guides/email-validation/what-is-email-validation)
21. [Email validator](https://www.knock.app/tools/email-validator)

## Try this prompt

Sort work emails into send, hold and skip

```text
Use www.enrich.chat to find the work email for each person in this list of names and company websites. Show the status exactly as returned. Put verified in a send group, catch_all and unknown in a hold group, and not found in a skip group. Never guess an address from a pattern.
```

## Related

- [Email verification API buyer's guide: responses, errors, limits and billing](https://enrich.chat/blog/email-verification-api/)
- [Email bounce rate: what is good](https://enrich.chat/blog/email-bounce-rate/)
- [Catch-all email checker](https://enrich.chat/tools/catch-all-checker/)
