Skip to main content
Glama
fairquery

Email Validator for Agents

Email Validator for Agents (MX, Disposable, Typo)

Fairquery Apify Actor that validates email addresses without sending any email or probing SMTP servers: syntax, DNS/MX, null MX, disposable-domain and role-account detection, free-provider flag, typo suggestions ("gmial.com" → "gmail.com"), mail provider, and SPF/DMARC. Each address gets a clear valid / risky / invalid / unknown verdict with machine-readable reason codes.

When to use this Actor (LLM / tool selection)

Use it when an agent needs to:

  • Clean a lead / CRM / signup list before outreach or import

  • Decide whether an address can receive mail (domain exists, has MX, no null MX)

  • Flag disposable/temporary inboxes, role addresses (info@, sales@) or free webmail on B2B forms

  • Suggest a fix for a mistyped domain

  • See which mail provider (Google Workspace, Microsoft 365, …) and DMARC policy a domain uses

Do not use it to confirm a specific mailbox exists — that requires SMTP probing, which this Actor deliberately avoids (privacy, IP reputation and ToS reasons). valid means "well-formed, deliverable domain, no risk flags", not "mailbox confirmed".

Related MCP server: inboxvalid-mcp

How it works

Check

Source

Syntax

RFC 5321/5322 pragmatic subset, IDN domains → punycode

MX / A / AAAA / TXT

DNS-over-HTTPS https://cloudflare-dns.com/dns-query (cached per domain, 10 domains in parallel)

Disposable domains

Bundled CC0 list from disposable-email-domains (~9.9k domains, subdomains matched)

Role / free provider / typo

Built-in lists + edit-distance against popular providers

Input

Field

Type

Default

Description

emails

string[]

6 sample addresses

Addresses; entries may be comma/semicolon/newline lists or Name <addr>

checkDns

bool

true

MX/A lookups (turn off for syntax-only)

checkSpfDmarc

bool

true

Report SPF/DMARC presence and DMARC policy

allowRoleAccounts

bool

true

If false, role addresses → risky

allowDisposable

bool

false

If true, disposable domains are not risky

allowFreeProviders

bool

true

If false, free webmail → risky (B2B lists)

maxEmails

int

10000

Safety cap per run

{ "emails": ["jane@acme.com", "info@apify.com", "bob@gmial.com"], "allowFreeProviders": false }

Output

Every row has schema_version (1.0.0), type (email | error), source_url (the DoH MX query URL), checked_at.

{
  "type": "email", "input": "someone@gmial.com", "email": "someone@gmial.com", "domain": "gmial.com",
  "verdict": "risky", "reasons": ["DISPOSABLE_DOMAIN", "POSSIBLE_TYPO", "IMPLICIT_MX_ONLY"],
  "syntax_valid": true, "is_disposable": true, "is_role_account": false, "is_free_provider": false,
  "did_you_mean": "someone@gmail.com", "domain_exists": true, "has_mx": false, "null_mx": false,
  "implicit_mx": true, "mx_records": [], "mail_provider": null, "has_spf": false, "has_dmarc": false, "dmarc_policy": null,
  "source_url": "https://cloudflare-dns.com/dns-query?name=gmial.com&type=MX"
}

Reason codes: INVALID_SYNTAX, DOMAIN_NOT_FOUND, NULL_MX, NO_MAIL_SERVER (→ invalid); DISPOSABLE_DOMAIN, ROLE_ACCOUNT, FREE_PROVIDER, POSSIBLE_TYPO, IMPLICIT_MX_ONLY (→ risky depending on the allow* flags); DNS_NOT_CHECKED (→ unknown).

Error rows (machine-readable, never charged)

{ "type": "error", "code": "DNS_LOOKUP_FAILED", "message": "DoH MX acme.com -> HTTP 503", "retryable": true, "input": "jane@acme.com", "domain": "acme.com" }

Codes: INPUT_EMPTY, MAX_EMAILS_EXCEEDED, DNS_LOOKUP_FAILED. Duplicate addresses (case-insensitive) are skipped and counted in the summary.

Run summary

Key-value store record RUN_SUMMARY: emails checked, duplicates skipped, verdict counts, domains checked, DNS request count, echoed input.

Pricing

Pay per event: email-checked per email row. Error rows are never charged. See the Store pricing tab.

Memory / runtime

Default 256 MB. No browser, no proxy. ~1,000 emails across a few hundred domains finish in well under a minute.

MCP / Apify tools

Call from agents via Apify MCP (https://mcp.apify.com, authenticated with your Apify token), Actor fairquery/email-validator-mx-disposable:

{ "actor": "fairquery/email-validator-mx-disposable", "input": { "emails": ["jane@acme.com"] } }

Read dataset items (type == "email") and the RUN_SUMMARY record. A standalone stdio MCP server lives in the GitHub repo under mcp/.

Local stdio MCP server

This repo ships a stdio MCP server (TypeScript, @modelcontextprotocol/sdk) under mcp/ exposing validate_emails (runs this Actor through the Apify API) and the free offline check_email_syntax. initialize and tools/list work without a token; tool calls require APIFY_TOKEN (billed per the Store pricing).

cd mcp && npm install && npm run build
node scripts/smoke-test.mjs                          # initialize + tools/list, no token
APIFY_TOKEN=... node scripts/smoke-test.mjs --call   # real tool call
{ "mcpServers": { "fairquery-email": { "command": "node", "args": ["/path/to/email-validator-mx-disposable/mcp/dist/index.js"], "env": { "APIFY_TOKEN": "<your Apify token>" } } } }

Docker: docker build -t fairquery-email-mcp . (the repo-root Dockerfile builds this MCP server and is what Glama uses; the Apify Actor image is built from .actor/Dockerfile). glama.json lists fairquery as maintainer.

Local development

npm install
npx apify run      # uses input defaults, or storage/key_value_stores/default/INPUT.json
npm test

Kits & templates

Optional guides from Fairquery for wiring this Actor into agents and automations (the Actor works fine without them):

Disclaimer

DNS-based validation cannot guarantee a mailbox exists or accepts mail. Use results to reduce bounces, not as proof of deliverability. Comply with anti-spam law (CAN-SPAM, GDPR/ePrivacy) when emailing.

Available Tools

2 tools
check_email_syntaxCheck email syntax offline (free)A
Read-onlyIdempotent

WHAT: Check whether strings are syntactically valid email addresses and normalize them (extracts "Name ", lowercases the domain), entirely locally. WHEN TO USE: fast pre-filtering or parsing before calling validate_emails, or when only the format matters. WHEN NOT TO USE: it does not check that the domain exists, has MX records, is disposable, a role account or a typo - use validate_emails (paid) for deliverability. COST: free; pure local function, no network, no APIFY_TOKEN, deterministic. RETURNS: {count, items}: one "email_syntax" row per input with input, email (normalized), syntax_valid, local_part, domain, reason (null or INVALID_SYNTAX). EXAMPLE: {"emails":["Jane jane@Example.com"]} -> email "jane@example.com", syntax_valid true, domain "example.com".

ParametersJSON Schema
NameRequiredDescriptionDefault
emailsYesRequired. 1-10000 strings to check; each may be a bare address or "Name <addr>" form. Example: ["Jane <jane@Example.com>","not-an-email"]

Output Schema

ParametersJSON Schema
NameRequiredDescription
countYesNumber of rows returned
itemsYesResult rows; each has a "type" field (data rows or machine-readable "error" rows)

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent, non-destructive and closed-world, so the bar is lower, yet the description adds substantial value: cost is free, execution is pure local with no network and no APIFY_TOKEN, results are deterministic, and it discloses the normalization behavior (extracting 'Name <addr>', lowercasing the domain). That goes well beyond the structured hints.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The WHAT/WHEN TO USE/WHEN NOT TO USE/COST/RETURNS/EXAMPLE structure is tightly front-loaded, with the purpose and routing condition in the first two blocks and no filler sentences. Every section carries distinct information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter, read-only, local tool the description covers purpose, exclusions, cost, determinism, normalization semantics and the return shape, even though an output schema exists. An agent has everything needed to call it correctly and interpret results.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the schema already documents the emails array, its 1-10000 bounds and the 'Name <addr>' form, so the baseline is 3. The description adds real semantic detail by explaining what normalization is applied to each input and the per-item reason value, which is more than the schema conveys.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a precise verb+resource (check syntactic validity of email strings) plus the scope ('entirely locally') and even names the normalization side effect. It explicitly contrasts itself with the validate_emails sibling, so an agent can distinguish them without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The WHEN TO USE / WHEN NOT TO USE blocks are explicit: use for fast pre-filtering or parsing before validate_emails, and do not use when domain existence, MX, disposable/role detection or typo checks are needed. It names the exact alternative and the condition that selects it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

validate_emailsValidate email addresses (syntax, MX, disposable, typo)A
Read-onlyIdempotent

WHAT: Validate email addresses for deliverability risk: RFC-style syntax, domain existence and MX records (DNS-over-HTTPS), null MX, disposable/temporary inbox domains, role accounts (info@, sales@), free webmail providers, common domain typos with a "did you mean" suggestion, and optional SPF/DMARC presence and policy. WHEN TO USE: cleaning signup or lead lists, checking an address before sending, flagging throwaway or typo signups. WHEN NOT TO USE: for a quick offline format check or parsing "Name " strings use check_email_syntax (free). Does NOT send email or do SMTP mailbox probing, so it cannot confirm that a specific mailbox exists. BEHAVIOR: read-only; runs the Fairquery Apify Actor fairquery/email-validator-mx-disposable via the Apify API (DNS lookups via Cloudflare DoH). Requires APIFY_TOKEN. Duplicates (case-insensitive) are skipped. Typical run 3-30 s. COST: paid (billed to your Apify account, pay-per-event): $0.00005 per run + $0.002 per email row with a verdict; error rows are free. 100 emails ~ $0.20. RETURNS: {count, items}. email rows: input, email, domain, verdict (valid | risky | invalid | unknown), reasons[] (INVALID_SYNTAX, DOMAIN_NOT_FOUND, NULL_MX, NO_MAIL_SERVER -> invalid; DISPOSABLE_DOMAIN, ROLE_ACCOUNT, FREE_PROVIDER, POSSIBLE_TYPO, IMPLICIT_MX_ONLY -> risky depending on allow* flags; DNS_NOT_CHECKED -> unknown), syntax_valid, is_disposable, is_role_account, is_free_provider, did_you_mean, domain_exists, has_mx, mx_records, mail_provider, has_spf, has_dmarc, dmarc_policy, source_url, checked_at. error rows: code (INPUT_EMPTY, MAX_EMAILS_EXCEEDED, DNS_LOOKUP_FAILED), message, retryable. EXAMPLE: {"emails":["someone@gmial.com"]} -> verdict "risky", reasons ["POSSIBLE_TYPO"], did_you_mean "someone@gmail.com".

ParametersJSON Schema
NameRequiredDescriptionDefault
emailsYesRequired. 1-10000 email addresses to validate. Entries may also be comma/semicolon/newline-separated lists or "Name <addr>" forms. Example: ["john.doe@gmail.com","someone@gmial.com"]
checkDnsNoLook up MX/A records to confirm the domain can receive mail (default true). false = syntax/list checks only, verdict may be "unknown".
maxEmailsNoSafety cap on unique emails per run (1-100000, default 10000); extras produce a MAX_EMAILS_EXCEEDED error row
checkSpfDmarcNoAlso report SPF and DMARC presence and DMARC policy per domain (default true)
allowDisposableNoDefault false (disposable domains are "risky"). Set true to not penalize disposable domains.
allowRoleAccountsNoDefault true. If false, role addresses (info@, sales@, support@...) get verdict "risky".
allowFreeProvidersNoDefault true. If false, free webmail (gmail.com, outlook.com...) gets "risky" - useful for B2B lead lists.

Output Schema

ParametersJSON Schema
NameRequiredDescription
countYesNumber of rows returned
itemsYesResult rows; each has a "type" field (data rows or machine-readable "error" rows)

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare read-only, idempotent, non-destructive, open-world. The description adds significant context beyond annotations: it explains the Apify Actor dependency, the APIFY_TOKEN requirement, duplicate skipping, typical run time (3-30s), and crucially the full cost model ($0.00005/run + $0.002/row). The only gap is not detailing the exact error row semantics, though these are partially listed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the WHAT, WHEN TO USE, and BEHAVIOR sections, making it easy to parse. However, the RETURNS section is quite verbose, listing all possible fields and their values, which duplicates information likely available in the output schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (external API, cost, multiple verdicts, error handling), the description provides a complete picture. It covers purpose, usage, behavior, cost, return values, and an example, leaving no major gaps for an agent to call it correctly. With an output schema present, the RETURNS detail is somewhat redundant but not harmful.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already documents all seven parameters in detail. The description provides minimal additional parameter meaning beyond what the schema already specifies, particularly for the allow* flags. Baseline 3 is appropriate when the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The WHAT line states a specific verb (validate) and resource (email addresses) and enumerates the exact dimensions checked (syntax, MX, disposable, typo, role accounts, SPF/DMARC). It explicitly names the sibling check_email_syntax and distinguishes itself via the 'WHEN NOT TO USE' line.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit WHEN TO USE scenarios (cleaning lists, checking before sending, flagging signups) and an explicit WHEN NOT TO USE with the named alternative check_email_syntax. It also clarifies what it cannot do (no SMTP mailbox probing).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 2 tool updatesv1.0.1
    • Addedcheck_email_syntax
    • Changedvalidate_emails9 fields changed
      • changedInput schema / properties / allowDisposable / description
        Previous value: -"If true, disposable domains are not risky"New value: +"Default false (disposable domains are \"risky\"). Set true to not penalize disposable domains."
      • changedInput schema / properties / allowFreeProviders / description
        Previous value: -"If false, free webmail becomes risky"New value: +"Default true. If false, free webmail (gmail.com, outlook.com...) gets \"risky\" - useful for B2B lead lists."
      • changedInput schema / properties / allowRoleAccounts / description
        Previous value: -"If false, info@/sales@ etc. become risky"New value: +"Default true. If false, role addresses (info@, sales@, support@...) get verdict \"risky\"."
      • changedInput schema / properties / checkDns / description
        Previous value: -"MX/A lookups (default true)"New value: +"Look up MX/A records to confirm the domain can receive mail (default true). false = syntax/list checks only, verdict may be \"unknown\"."
      • changedInput schema / properties / checkSpfDmarc / description
        Previous value: -"Report SPF/DMARC (default true)"New value: +"Also report SPF and DMARC presence and DMARC policy per domain (default true)"
      • changedInput schema / properties / emails / description
        Previous value: -"Email addresses to validate"New value: +"Required. 1-10000 email addresses to validate. Entries may also be comma/semicolon/newline-separated lists or \"Name <addr>\" forms. Example: [\"john.doe@gmail.com\",\"someone@gmial.com\"]"
      • addedInput schema / properties / emails / maxItems
        Added value: +10000
      • addedInput schema / properties / maxEmails / description
        Added value: +"Safety cap on unique emails per run (1-100000, default 10000); extras produce a MAX_EMAILS_EXCEEDED error row"
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": false,
        +  "properties": {
        +    "count": {
        +      "description": "Number of rows returned",
        +      "type": "integer"
        +    },
        +    "items": {
        +      "description": "Result rows; each has a \"type\" field (data rows or machine-readable \"error\" rows)",
        +      "items": {
        +        "additionalProperties": {},
        +        "type": "object"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "count",
        +    "items"
        +  ],
        +  "type": "object"
        +}
  2. 1 tool updatev0.1.0
    • First observedvalidate_emails

TDQS

A4.5/5.0

Scored across 2 tools

Disambiguation5/5

The two tools are clearly delineated: validate_emails does paid network/DNS deliverability checks, while check_email_syntax is a free local syntax/normalization pass. Their descriptions explicitly cross-reference each other with WHEN TO USE and WHEN NOT TO USE guidance, so an agent can reliably pick the right one.

Naming Consistency4/5

Both names use consistent snake_case verb_noun form (validate_emails, check_email_syntax). Minor deviation: the noun phrasing differs slightly ('emails' vs 'email_syntax'), and the verbs differ (validate vs check), but the pattern remains predictable.

Tool Count4/5

Two tools is on the thin side, but the server has a narrow, well-defined purpose (email validation), and each tool earns its place: a free local pre-filter and a paid deliverability check. No obviously redundant or missing sibling tool within the stated scope.

Completeness4/5

The surface covers the two core validation stages: syntax parsing/normalization and deliverability risk (MX, disposable, role, typo, SPF/DMARC). Mailbox existence (SMTP probing) is explicitly excluded, and there is no domain-only MX lookup tool, but these are minor gaps agents can work around.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    Comprehensive email validation MCP server that checks syntax, MX records, disposable domains, role-based accounts, SPF/DKIM, typo suggestions, and risk scoring.
    -
  • F
    license
    A
    quality
    B
    maintenance
    An MCP server that exposes a verify_email tool for checking email syntax, disposable domains, and MX records, returning a structured validity result.
    1
    -
  • F
    license
    B
    quality
    C
    maintenance
    An MCP server that provides email verification, returning valid, invalid, or risky status with detailed checks and metadata. It enables verifying email addresses via a simple tool interface.
    3
    -
  • F
    license
    A
    quality
    C
    maintenance
    An MCP server that exposes a mock email verification tool over stdio transport, providing structured JSON results with statuses valid, invalid, or risky.
    1
    -