Email Intelligence

4 endpoints for deep email and domain intelligence beyond basic validation.

Method Endpoint Purpose
GET /v1/email/catch-all Detect whether a domain accepts all addresses
GET /v1/email/role-check Identify role/group accounts vs personal mailboxes
GET /v1/email/normalize Normalize Gmail dots, plus-aliases, and case
GET /v1/email/provider Identify the email provider from MX records

Python SDK Examples

Detect catch-all domains

catch_all probes a domain's mail server with a randomly generated address. If accepted, the server is a catch-all — meaning SMTP probes during validation are unreliable for that domain.

from toolkitapi import Email

domains = [
    "toolkitapi.io",
    "gmail.com",
    "outlook.com",
    "mailinator.com",
]

with Email(api_key="tk_...") as email:
    for domain in domains:
        result = email.catch_all(domain)
        status = "catch-all" if result["is_catch_all"] else "normal"
        mx = result["mx_records"][0] if result["mx_records"] else "no MX"
        print(f"{domain:20} → {status:10}  [{mx}]")

Flag catch-all domains before bulk SMTP validation

from toolkitapi import Email

def needs_catch_all_warning(domain: str) -> bool:
    """Return True if the domain is a catch-all; SMTP validation will be unreliable."""
    with Email(api_key="tk_...") as email:
        result = email.catch_all(domain)
    return bool(result["is_catch_all"])

if needs_catch_all_warning("company.com"):
    print("Warning: this domain accepts all addresses — SMTP probes may give false positives.")

Identify role accounts

role_check classifies the local part of an email against 60+ known role patterns, returning a role_type category.

from toolkitapi import Email

addresses = [
    "[email protected]",
    "[email protected]",
    "[email protected]",
    "[email protected]",
    "[email protected]",
    "[email protected]",
]

with Email(api_key="tk_...") as email:
    for addr in addresses:
        result = email.role_check(addr)
        tag = f"[{result['role_type']}]" if result["is_role"] else "[personal]"
        print(f"{addr:30} {tag}")

Output:

[email protected]              [personal]
[email protected]            [support]
[email protected]            [automated]
[email protected]            [finance]
[email protected]                [executive]
[email protected]               [human_resources]

Filter role accounts from a mailing list

Role inboxes are typically shared mailboxes; personalised marketing sent to them usually yields low engagement and may trigger spam filters:

from toolkitapi import Email

def split_personal_role(addresses: list[str]) -> tuple[list[str], list[str]]:
    """Return (personal_addresses, role_addresses)."""
    personal, role = [], []
    with Email(api_key="tk_...") as email:
        for addr in addresses:
            result = email.role_check(addr)
            (role if result["is_role"] else personal).append(addr)
    return personal, role

leads = ["[email protected]", "[email protected]", "[email protected]", "[email protected]"]
personal, role = split_personal_role(leads)
print("Personal:", personal)   # ["[email protected]", "[email protected]"]
print("Role:",     role)        # ["[email protected]", "[email protected]"]

Normalize email addresses

normalize handles Gmail dot-insensitivity, plus-alias stripping, googlemail.com → gmail.com canonicalization, and general case normalization.

from toolkitapi import Email

test_cases = [
    "[email protected]",
    "[email protected]",
    "[email protected]",
    "[email protected]",
]

with Email(api_key="tk_...") as email:
    for addr in test_cases:
        result = email.normalize(addr)
        changes = ", ".join(result["changes"]) or "none"
        print(f"{addr}")
        print(f"  → {result['normalized']}  ({changes})\n")

Output:

[email protected][email protected]  (gmail_dots_removed, plus_alias_removed, local_part_lowercased)

[email protected][email protected]  (gmail_dots_removed, googlemail_to_gmail)

[email protected][email protected]  (plus_alias_removed, local_part_lowercased)

[email protected][email protected]  (local_part_lowercased)

Deduplicate sign-ups by canonical address

from toolkitapi import Email

def deduplicate_emails(addresses: list[str]) -> list[str]:
    """Return a deduplicated list using normalized canonical forms."""
    seen: set[str] = set()
    unique: list[str] = []
    with Email(api_key="tk_...") as email:
        for addr in addresses:
            result = email.normalize(addr)
            canonical = result["normalized"]
            if canonical not in seen:
                seen.add(canonical)
                unique.append(addr)  # Keep the original form, just deduplicate
    return unique

raw = [
    "[email protected]",
    "[email protected]",       # same Gmail inbox
    "[email protected]",      # same Gmail inbox
    "[email protected]",
]
print(deduplicate_emails(raw))
# ["[email protected]", "[email protected]"]

Identify email provider

provider resolves MX records and maps them to known providers. Useful for routing, compliance checks, or adjusting validation strategy per provider.

from toolkitapi import Email

domains = [
    "gmail.com",
    "outlook.com",
    "yahoo.com",
    "company-using-gsuite.com",
    "unknown-domain.example",
]

with Email(api_key="tk_...") as email:
    for domain in domains:
        result = email.provider(domain)
        print(f"{domain:35} → {result['provider']} ({result['provider_type']})")

Response Fields

catch-all response:

Field Type Description
domain string Input domain
is_catch_all bool | null true = catch-all, null = could not determine
mx_records list MX hostnames for the domain
method string How the check was performed (smtp_probe or no_mx_records)

role-check response:

Field Type Description
email string Input email
local_part string Part before @
domain string Domain part
is_role bool Whether the address is a role/group account
role_type string | null Category: support, automated, finance, executive, human_resources, technical, security, general, etc.

normalize response:

Field Type Description
original string Input email
normalized string Canonical normalized form
local_part string Normalized local part
domain string Normalized domain
changes list Applied transformations: gmail_dots_removed, plus_alias_removed, googlemail_to_gmail, local_part_lowercased, domain_lowercased

provider response:

Field Type Description
domain string Queried domain
provider string Provider name (e.g. Google, Microsoft, Yahoo)
provider_type string Category of provider
mx_records list MX records used for identification

Tip

Use normalize before storing email addresses to prevent duplicate accounts. Two users signing up as [email protected] and [email protected] are the same Gmail inbox — normalizing to [email protected] catches both. Combine with catch_all to flag domains where SMTP probes can't be trusted.