Skip to main content
Glama
Email Validator for Agents

Email Validator for Agents

Validate email addresses (syntax, MX, disposable, typo)

validate_emails
Read-onlyIdempotent

Screen signup and lead lists for email deliverability risk: checks syntax, DNS/MX, disposable domains, role accounts, typos, and SPF/DMARC, with valid/risky/invalid verdicts.

Instructions

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: 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.00079 per email row with a verdict; error rows are free. 100 emails ~ $0.08. RETURNS: one email row per unique address; verdict follows reasons[]: INVALID_SYNTAX, DOMAIN_NOT_FOUND, NULL_MX, NO_MAIL_SERVER -> invalid; DISPOSABLE_DOMAIN, ROLE_ACCOUNT, FREE_PROVIDER (per allow* flags), POSSIBLE_TYPO, IMPLICIT_MX_ONLY -> risky; DNS_NOT_CHECKED -> unknown. Error rows are free and never sit next to an email row for the same address: INPUT_EMPTY (nothing to check), MAX_EMAILS_EXCEEDED (once, for the overflow), DNS_LOOKUP_FAILED (one per address whose domain lookup failed, instead of its email row; retryable=true for transient DNS errors, so resend only those addresses). PARAMETERS: emails: entries are split on commas, semicolons and newlines, trimmed, reduced from "Name " to addr, and case-insensitive duplicates are skipped before checking, so a pasted list in one element works and you pay once per unique address; maxEmails caps that unique count (extras get one free MAX_EMAILS_EXCEEDED row), which makes it your spend cap. checkDns=false skips all DNS lookups: domain_exists / has_mx stay null and an address that is otherwise clean gets verdict "unknown" (DNS_NOT_CHECKED) instead of "valid" - it is still billed. checkSpfDmarc only adds has_spf / has_dmarc / dmarc_policy and never changes the verdict; it is ignored when checkDns=false. The three allow* flags only decide whether a condition downgrades an otherwise valid address to "risky": the reason code (ROLE_ACCOUNT, DISPOSABLE_DOMAIN, FREE_PROVIDER) is listed in reasons[] either way, and no flag can rescue an "invalid" address (bad syntax, DOMAIN_NOT_FOUND, NULL_MX, NO_MAIL_SERVER). POSSIBLE_TYPO and IMPLICIT_MX_ONLY are always "risky". Presets: B2B lead list = allowFreeProviders false + allowRoleAccounts false; consumer signups = defaults. EXAMPLE: {"emails":["someone@gamil.com"]} -> verdict "risky", reasons ["POSSIBLE_TYPO"], did_you_mean "someone@gmail.com".

Input 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@gamil.com"]
checkDnsNoOptional boolean, default true. true looks up MX/A records (DNS-over-HTTPS) to confirm the domain can receive mail; false = syntax/list checks only, clean addresses then get verdict "unknown". Example: false
maxEmailsNoOptional integer 1-100000, default 10000. Safety/spend cap on unique emails per run; addresses beyond it are skipped with one free MAX_EMAILS_EXCEEDED error row. Example: 500
checkSpfDmarcNoOptional boolean, default true. true adds has_spf, has_dmarc and dmarc_policy (none|quarantine|reject) per domain; never changes the verdict; needs checkDns=true
allowDisposableNoOptional boolean, default false = disposable/temporary-inbox domains (mailinator.com, ...) get "risky"; true stops penalising them (DISPOSABLE_DOMAIN still reported)
allowRoleAccountsNoOptional boolean, default true. false downgrades role mailboxes (info@, sales@, support@, ...; +tags ignored) from "valid" to "risky"; ROLE_ACCOUNT is reported in reasons either way
allowFreeProvidersNoOptional boolean, default true. false downgrades free webmail (gmail.com, outlook.com, yahoo.com, ...) to "risky" - recommended for B2B lead lists

Output Schema

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

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed7 schema fields changed
    • changedInput schema / properties / allowDisposable / description
      Previous value: -"Default false (disposable domains are \"risky\"). Set true to not penalize disposable domains."New value: +"Optional boolean, default false = disposable/temporary-inbox domains (mailinator.com, ...) get \"risky\"; true stops penalising them (DISPOSABLE_DOMAIN still reported)"
    • changedInput schema / properties / allowFreeProviders / description
      Previous value: -"Default true. If false, free webmail (gmail.com, outlook.com...) gets \"risky\" - useful for B2B lead lists."New value: +"Optional boolean, default true. false downgrades free webmail (gmail.com, outlook.com, yahoo.com, ...) to \"risky\" - recommended for B2B lead lists"
    • changedInput schema / properties / allowRoleAccounts / description
      Previous value: -"Default true. If false, role addresses (info@, sales@, support@...) get verdict \"risky\"."New value: +"Optional boolean, default true. false downgrades role mailboxes (info@, sales@, support@, ...; +tags ignored) from \"valid\" to \"risky\"; ROLE_ACCOUNT is reported in reasons either way"
    • changedInput schema / properties / checkDns / description
      Previous value: -"Look up MX/A records to confirm the domain can receive mail (default true). false = syntax/list checks only, verdict may be \"unknown\"."New value: +"Optional boolean, default true. true looks up MX/A records (DNS-over-HTTPS) to confirm the domain can receive mail; false = syntax/list checks only, clean addresses then get verdict \"unknown\". Example: false"
    • changedInput schema / properties / checkSpfDmarc / description
      Previous value: -"Also report SPF and DMARC presence and DMARC policy per domain (default true)"New value: +"Optional boolean, default true. true adds has_spf, has_dmarc and dmarc_policy (none|quarantine|reject) per domain; never changes the verdict; needs checkDns=true"
    • changedInput schema / properties / emails / description
      Previous 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\"]"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@gamil.com\"]"
    • changedInput schema / properties / maxEmails / description
      Previous value: -"Safety cap on unique emails per run (1-100000, default 10000); extras produce a MAX_EMAILS_EXCEEDED error row"New value: +"Optional integer 1-100000, default 10000. Safety/spend cap on unique emails per run; addresses beyond it are skipped with one free MAX_EMAILS_EXCEEDED error row. Example: 500"
  2. Changed9 schema fields changedv1.0.1
    • 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"
      +}
  3. First observedv0.1.0

TDQS

A4.9/5.0
Behavior5/5

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

Annotations cover only the safety profile (readOnly, idempotent, openWorld, non-destructive), leaving the description to carry the operational burden, which it does: APIFY_TOKEN requirement, external Actor invocation, case-insensitive dedup and skip behavior, 3-30s runtime, paid pay-per-event pricing model, and the fact that some checks are billed even when skipped. It also flags what can never be confirmed (mailbox existence) and which error rows are retryable.

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 headed WHAT/WHEN/BEHAVIOR/COST/RETURNS/PARAMETERS/EXAMPLE layout is front-loaded and scannable, and for a 7-parameter tool with billing, cost, and verdict-tier complexity the length is largely earned. It is nonetheless verbose and the RETURNS and PARAMETERS sections restate overlapping verdict/flag behavior, so it is not maximally tight.

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?

Even though an output schema exists and return fields need not be documented, the description still maps verdict values to reason codes and explains which error rows replace email rows and why, which is exactly what an agent needs to interpret partial failures. Everything needed to call the tool correctly and read its results is present.

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

Parameters5/5

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

Schema coverage is already 100%, yet the description still adds meaning the schema cannot express: allow* flags only downgrade an otherwise valid address to 'risky' and never rescue an 'invalid' one, the reason code is reported either way, checkDns=false still bills, checkSpfDmarc never alters the verdict and is ignored when checkDns=false, and maxEmails functions as the spend cap. It also supplies named presets (B2B vs consumer), which are not encoded anywhere in the schema.

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 section names a specific verb (validate) and resource (email addresses) and enumerates exactly which checks run: RFC syntax, MX/DNS-over-HTTPS, null MX, disposable domains, role accounts, free providers, typos, SPF/DMARC. It also draws an explicit boundary against the sibling check_email_syntax, so an agent can discriminate 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?

WHEN TO USE gives concrete scenarios (cleaning signup/lead lists, pre-send checks, throwaway/typo signups) and WHEN NOT TO USE names the exact alternative (check_email_syntax, free) plus its capability limits (no SMTP mailbox probing, cannot confirm a mailbox exists). Explicit and actionable.

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

Deploy Server

Other Tools