Mailvett
Free API + MCP server · no key

Catch bad email addresses before you send

Paste addresses and get a clear verdict for each: syntax, domain and mail server (MX), mail provider, disposable, role (info@, sales@), free provider and likely typos (gmial.com → gmail.com), plus domain age, SPF and DMARC.

Who it's for

Anyone who needs this answer fast, from a person to an AI agent.

Sign-up forms and SaaS

Stop disposable and mistyped addresses at sign-up, with a "did you mean" suggestion.

Sales and marketing

Clean a small list before a send: drop dead domains, flag role and free addresses.

AI agents and CRMs

One tool call answers "is this email real enough to use?" with reasons.

Developers

Consistent JSON with machine-readable reason codes you can branch on.

Try it

Up to 10 addresses, one per line or comma separated.

Prefilled with a real example. Press Validate.

Real sample output

Captured from a live call to this API (trimmed for length).

{
  "results": [
    {
      "input": "jane.doe@gmial.com",
      "email": "jane.doe@gmial.com",
      "verdict": "risky",
      "score": 1,
      "reasons": [
        "mail_server_from_a_record",
        "disposable_domain",
        "possible_typo_of:gmail.com",
        "no_spf",
        "no_dmarc",
        "domain_age_years:23"
      ],
      "summary": "jane.doe@gmial.com: risky (score 1) - Implicit (A record), disposable domain, did you mean jane.doe@gmail.com?, domain 23y old.",
      "localPart": "jane.doe",
      "domain": "gmial.com",
      "syntax": {
        "valid": true,
        "error": null
      },
      "domainExists": true,
      "mx": {
        "present": true,
        "hosts": [],
        "provider": "Implicit (A record)",
        "implicit": true,
        "nullMx": false
      },
      "flags": {
        "disposable": true,
        "role": false,
        "roleType": null,
        "freeProvider": false,
        "typoSuggestion": "gmail.com",
        "parkedDomain": false
      },
      "suggestion": "jane.doe@gmail.com",
      "domainHealth": {
        "spf": null,
        "dmarc": null,
        "createdAt": "2003-05-12T18:26:31Z",
        "ageDays": 8537,
        "registrar": "GoDaddy.com, LLC",
        "parkedEvidence": null
      },
      "catchAll": "not_checked",
      "mailbox": "not_checked",
      "errors": [],
      "ms": 748,
      "checkedAt": "2026-09-25T23:03:27.011Z"
    },
    {
      "input": "info@stripe.com",
      "email": "info@stripe.com",
      "verdict": "deliverable_likely",
      "score": 78,
      "reasons": [
        "mx_present",
        "role_account:general",
        "spf_present",
        "dmarc:reject",
        "domain_age_years:31"
      ],
      "summary": "info@stripe.com: deliverable_likely (score 78) - Google Workspace, role account (general), domain 31y old.",
      "localPart": "info",
      "domain": "stripe.com",
      "syntax": {
        "valid": true,
        "error": null
      },
      "domainExists": true,
      "mx": {
        "present": true,
        "hosts": [
          "aspmx.l.google.com",
          "alt1.aspmx.l.google.com",
          "alt2.aspmx.l.google.com",
          "aspmx2.googlemail.com",
          "aspmx3.googlemail.com"
        ],
        "provider": "Google Workspace",
        "implicit": false,
        "nullMx": false
      },
      "flags": {
        "disposable": false,
        "role": true,
        "roleType": "general",
        "freeProvider": false,
        "typoSuggestion": null,
        "parkedDomain": false
      },
      "suggestion": null,
      "domainHealth": {
        "spf": "softfail",
        "dmarc": "reject",
        "createdAt": "1995-09-12T04:00:00Z",
        "ageDays": 11336,
        "registrar": "SafeNames Ltd.",
        "parkedEvidence": null
      },
      "catchAll": "not_checked",
      "mailbox": "not_checked",
      "errors": [],
      "ms": 107,
      "checkedAt": "2026-09-25T23:03:26.370Z"
    }
  ],
  "count": 4,
  "verdicts": {
    "deliverable_likely": 1,
    "risky": 2,
    "undeliverable": 1,
    "invalid": 0
  },
  "checks": {
    "domainAge": true,
    "parkedWebsite": true,
    "mailbox": "never probed (no SMTP)"
  }
}

Limits, plainly

Free and rate limited so it stays fast for everyone. A bulk and scheduled version for big lists is coming to the Apify Store.

  • 20 calls per minute per IP address.
  • Up to 10 emails per call.
  • Domain age and parked-site checks run in full for up to 5 different domains per call.
  • Mailboxes are never probed (no SMTP), so the top score is 90.
  • Free, no key.

Use the API

JSON over HTTPS, CORS enabled, no key. GET for quick calls, POST a JSON body for lists. Spec: openapi.json · llms.txt

cURL
curl -s "https://mailvett.cybermax-tools.workers.dev/api/validate?email=jane.doe%40gmial.com%0Ainfo%40stripe.com%0Atest%40mailinator.com%0Asales%40this-domain-does-not-exist-9x7q.com"

# lists: POST a JSON body
curl -s -X POST https://mailvett.cybermax-tools.workers.dev/api/validate \
  -H "content-type: application/json" \
  -d '{"emails":["jane.doe@gmial.com","info@stripe.com","test@mailinator.com"]}'
Python
import requests

r = requests.post("https://mailvett.cybermax-tools.workers.dev/api/validate",
                  json={"emails":["jane.doe@gmial.com","info@stripe.com","test@mailinator.com"]}, timeout=30)
r.raise_for_status()
for row in r.json()["results"]:
    print(row)

Endpoints: /api/validate validate up to 10 email addresses

Add it to your AI agent (MCP)

A remote MCP server at https://mailvett.cybermax-tools.workers.dev/mcp (streamable HTTP, no auth). Read-only tools with JSON schemas, so agents know exactly what to send.

MCP config
// Claude Desktop, Cursor, VS Code, any MCP client (remote, no key)
{
  "mcpServers": {
    "mailvett": { "type": "http", "url": "https://mailvett.cybermax-tools.workers.dev/mcp" }
  }
}

# Claude Code
claude mcp add --transport http mailvett https://mailvett.cybermax-tools.workers.dev/mcp

# Tools: validate_emails
# e.g. validate_emails({"emails":["jane.doe@gmial.com"]})
  • validate_emails
    Check up to 10 email addresses: syntax, whether the domain exists and has mail servers (MX), mail provider, disposable, role account (info@, sales@), free provider, likely typo with a suggested fix, domain age, SPF and DMARC. Returns verdict (deliverable_likely/risky/undeliverable/invalid), score 0-100 and reason codes per address. Does not verify that the mailbox itself exists.

FAQ

Why not an SMTP "mailbox exists" check?

Probing mail servers is slow, often blocked or answered with fake "OK"s (catch-all servers), and can hurt the reputation of the IP doing it. Mailvett never probes mailboxes and says so (mailbox: "not_checked"); it tells you everything that can be known safely.

What do the verdicts mean?

deliverable_likely: real domain with mail servers and no warning signs. risky: works but disposable, parked, very new, a likely typo or unusual. undeliverable: the domain does not exist or accepts no mail. invalid: bad syntax.

Where does the disposable list come from?

The community-maintained disposable-email-domains list (CC0), plus our own role, free-provider and typo rules.

Do you store the addresses?

No. Addresses are checked live and not saved. Only DNS, RDAP and the domain's homepage are queried, never the mailbox.

Can I clean a big list?

The free API takes 10 addresses per call. A bulk version for large lists is coming to the Apify Store.