Skip to main content
Glama
askeleven

send-guard

by askeleven

send-guard

send-guard: check an email list before your agent sends to it

Check an email list before your agent sends to it, and find out whether it is safe to.

npx @askeleven/send-guard leads.csv

An agent that sends to a bad list does not notice. It gets bounces nobody reads, lands on a spam trap, and the domain's reputation is gone before a person looks at a dashboard. send-guard is the check that runs first: a CLI for pipelines, an MCP server for agents, and a library for everything else. It returns a pass or a fail, the addresses to keep, and the reason for every one it removes.

Zero dependencies. The local checks need no signup and no account, and nothing leaves your machine except DNS lookups for the domains in the list.


What it checks

Check

Where it runs

Verdict

Syntax

Local, free

Remove

Duplicates, case-insensitive

Local, free

Remove

Domain cannot receive mail: no MX, no A record, or a null MX

Local, free

Remove

Parked domains, on known parking nameservers

Local, free

Remove

Disposable inboxes

Local, free

Remove

Typos of major providers, with a suggestion (gmial.com, hotmial.com)

Local, free

Remove

Role accounts (info@, sales@, support@)

Local, free

Review

Free providers

Local, free

Informational

Mailbox exists, over SMTP

Analyzemail API key

Remove if not

Catch-all domains

Analyzemail API key

Review

Spam traps

Analyzemail API key

Remove

Known litigators

Analyzemail API key

Remove

Security gateways hiding mailbox status

Analyzemail API key

Review

Keep means nothing was found. Review means a person should decide. Remove means sending will bounce, or will arrive somewhere that hurts you.

The list fails when more than 2% of its distinct addresses should be removed (--max-remove to change it). Duplicates are left out of that share: sending twice is wasteful, not dangerous.

Related MCP server: mailverdict

Why the mailbox check needs a key

Most cloud hosts block outbound port 25 by default, so an agent running on one cannot ask a mail server whether a mailbox exists. Even where it can, probing from an IP with no reputation gets refused or blocklisted. That check needs infrastructure, so it runs on Analyzemail, which we also make.

Set ANALYZEMAIL_API_KEY (get one here) and send-guard checks every address that passed the local checks. It never spends a credit on an address it has already ruled out, or on a duplicate. One credit per address, and a check the mail server does not answer is refunded.

250 mailbox checks a month are free on any Analyzemail account with a confirmed email address. They reset at 00:00 UTC on the 1st, do not roll over, and are spent before any credits you buy. Until an account has bought credits, it is limited to 2 checks a second and 500 a day; send-guard waits out the per-second limit on its own. AskEleven customers get 25,000 a month.

Before spending anything it checks your balance and refuses to start if the list would cost more than --max-credits (default 1,000), so an agent cannot spend more than you expect.

What it does not do

Without a key, it cannot tell you a mailbox exists. A list can pass every local check and still bounce 20% when the people on it left their jobs. The report says so when mailboxes were not checked, rather than letting a pass imply more than it means.

It does not send anything, or fix anything. A probable typo comes with a suggestion, not a correction. Whether bob@gmial.com meant bob@gmail.com is for a person to confirm.

It does not treat a DNS failure as a dead domain. If the resolver does not answer, those addresses are marked review, not remove.


Example

$ npx @askeleven/send-guard leads.csv --out clean.csv

FAIL  50% of the list should be removed (limit 2%)

           4 checked
           1 keep
           1 review
           2 remove

REMOVE
  Disposable inbox (1)
      al@sharklasers.com
  Probable typo (1)
      bob@hotmial.com  did you mean bob@hotmail.com?

REVIEW
  Shared inbox (role account) (1)
      sales@acme.com

  Mailboxes were not checked. 2 addresses passed the local checks, which
  catch addresses that can never work but cannot tell whether a mailbox
  exists. Set ANALYZEMAIL_API_KEY to check them (one credit each; key at
  https://analyzemail.com/account/settings/api).
Wrote the addresses to keep to clean.csv

clean.csv keeps the header and every other column, so it drops straight back into whatever the list came from.

Options

--column <name|n>     Email column in a CSV. Found automatically otherwise.
--max-remove <pct>    Fail when more than this share should be removed. Default 2.
--max-credits <n>     Refuse to spend more than this on mailbox checks. Default 1000.
--out <file>          Write the addresses to keep, in the input's format.
--include-review      Also write addresses marked review to --out.
--no-mailbox          Local checks only, even with an API key set.
--no-dns              Skip DNS lookups. Syntax and list checks only.
--dns <ip>            Resolver to query. Repeatable.
--json                Machine-readable output.
--all                 List every flagged address, not the first ten per reason.
--no-colour           Plain text.

Input is a CSV (comma, semicolon or tab), a plain list with one address per line, addresses on the command line, or standard input.

Exit code 0 means safe to send, 1 means not safe as it stands, 2 means it could not run. So it gates a pipeline:

npx @askeleven/send-guard list.csv --out clean.csv && ./send-campaign clean.csv

For agents: MCP server

npx @askeleven/send-guard mcp

It serves two tools over stdio: check_emails (up to 5,000 addresses inline) and check_file (a CSV or text file on disk, optionally writing the clean list to out_path). Both return passed, the addresses to keep, and the remove and review lists, each with a reason code and a plain-English explanation.

Claude Code

claude mcp add send-guard -e ANALYZEMAIL_API_KEY=am_live_... -- npx -y @askeleven/send-guard mcp

Claude Desktop, Cursor, and other clients that take a JSON config:

{
  "mcpServers": {
    "send-guard": {
      "command": "npx",
      "args": ["-y", "@askeleven/send-guard", "mcp"],
      "env": { "ANALYZEMAIL_API_KEY": "am_live_..." }
    }
  }
}

Leave out the env block for local checks only.

The server tells the model how to use the result: do not send to a list that failed, send to keep, show review to a person rather than deciding, and never substitute a typo suggestion without asking.

As a library

import { checkList, createClient } from '@askeleven/send-guard'

const report = await checkList(addresses, {
  client: createClient({ apiKey: process.env.ANALYZEMAIL_API_KEY }), // optional
})

if (!report.summary.passed) {
  const keep = report.addresses.filter((a) => a.verdict === 'keep').map((a) => a.email)
  // send to keep, or stop and ask
}

Every reason has a stable code (syntax, disposable, mailbox_undeliverable, and so on) to match on, and a detail to show a person. createFixtureResolver() is exported so you can test without touching the network.

Privacy

With no API key, the only thing that leaves your machine is a DNS query for each distinct domain in the list. Addresses are not sent anywhere.

With a key, each address that passed the local checks is sent to Analyzemail to be verified, under its privacy policy. --no-mailbox (or check_mailboxes: false over MCP) turns that off for one run.

Requirements

Node 20 or newer. No dependencies.


Why we built it

AskEleven runs AI employees that send email on behalf of small businesses. The first time an agent is handed a spreadsheet and asked to "follow up with everyone", it will, including the 400 addresses that bounced two years ago. Nothing about the agent is broken. Nobody told it to check.

This is that check, made free wherever it can be. The disposable, role and parking lists are the ones Analyzemail uses server-side, so a local verdict and an API verdict agree.

Contributing

Issues and pull requests welcome, especially:

  • Disposable domains we are missing, with a link showing the service hands out inboxes.

  • Wrong verdicts. If an address is removed that should not be, open an issue with the domain (not the full address) and we will fix it.

  • MCP clients where the server does not work as documented.

Run the tests with npm test. They use fixture DNS and a fake API client, so they are offline and fast.

License

MIT. See LICENSE.

Removing a litigator or a spam trap from a list is risk reduction, not compliance. Consent is still yours to get.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables AI agents to verify email addresses through a multi-signal probabilistic pipeline, returning confidence scores and honest statuses (safe/risky/invalid/unknown) with evidence.
    Apache 2.0
  • A
    license
    Not graded
    quality
    B
    maintenance
    Keyless email validation: disposable/burner, role-account, and free-provider detection, MX checks, and typo suggestions. Tools: check_email, check_domain.
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Wraps the Emailable API for email verification, enabling AI agents to verify email addresses through natural language queries.
    135 npm
    MIT