CLI reference

The same library, driven from a shell. Useful for auditing a domain, checking a list, or sanity-checking a signup rule before wiring it into code.

Install

go install github.com/bakhod1r/emailx/cmd/emailx@latest
emailx <command> [flags] [arguments]

analyze  <email>     full intelligence profile for one address
validate <email>     syntax, domain, and DNS validation
domain   <domain>    SPF, DMARC, DKIM, MX and transport-security records
verify   <email>     SMTP mailbox probe
batch    <file|->    validate a list of addresses, one per line or CSV

Global flags

Every command accepts these.

FlagDefaultMeaning
-jsonoffemit JSON instead of text
-timeout10sdeadline per address
-dnssystemDNS server as host:port, queried directly so TTLs are visible
-cache5mcache DNS answers for this long; 0 disables

Ctrl-C cancels lookups in flight rather than leaving them hanging.

analyze

Everything the library knows about one address, in one pass.

$ emailx analyze john@example.com

Address:       john@example.com
Domain:        example.com
Valid:         yes
Disposable:    no
Role account:  no
Free provider: no

MX:        yes (mail.example.com.)
SPF:       yes (-all, 3 lookups)
DMARC:     yes (p=reject, pct=100, enforcing)
DKIM:      yes (selector selector1)
Protected: yes

Risk:          LOW (0)
Deliverability: 100/100

Every risk signal and every deliverability deduction is printed on its own line, so a score can always be traced back to its cause.

validate

A narrower check: syntax, domain, and whether the DNS backs it up. Exits non-zero when the address is not valid, so it drops into scripts.

$ emailx validate user@example.com -json
{
  "address": "user@example.com",
  "valid": true,
  "syntax": true,
  "domain": true,
  "mx": true,
  "spf": true,
  "dmarc": true,
  "dkim": false,
  "protected": false,
  "disposable": false,
  "role": false
}

domain

Audits a domain rather than an address. This is the command to reach for when someone asks whether a domain is configured correctly.

$ emailx domain google.com

Domain: google.com

MX:        yes (smtp.google.com.)
SPF:       yes (~all, 1 lookup)
DMARC:     yes (p=reject, pct=100, enforcing)
DKIM:      no key found on the common selectors
Protected: no
DNSSEC: no  BIMI: no  MTA-STS: yes  TLS-RPT: yes
FlagMeaning
-selectorscomma-separated DKIM selectors to probe instead of the common list

A "no key found" result does not prove there is no DKIM — it means none of the common selectors answered. If you know the selector, pass it.

verify

Opens an SMTP connection and asks the server about the mailbox.

$ emailx verify -skip-catch-all -timeout 5s postmaster@gmail.com

Address:  postmaster@gmail.com
Status:   valid
MX host:  gmail-smtp-in.l.google.com
Reply:    250
STARTTLS: yes
Took:     862ms
FlagDefaultMeaning
-helolocalhosthostname sent in EHLO; should resolve back to your IP
-fromemptyenvelope sender; empty sends the null sender <>
-rate0maximum probes per second; 0 is unthrottled
-skip-catch-alloffskip the second, random-address probe

This command sends real SMTP traffic to someone else's server. Most cloud providers block outbound port 25, so expect unknown unless the network allows it. Unthrottled probing gets the sending IP blocklisted — use -rate. A catch-all status means the server accepts every address, so acceptance says nothing about the mailbox, and a 4xx reply is greylisting reported as unknown, never as invalid.

batch

Runs analyze over a list and writes a table. Reads a file, or - for standard input.

$ emailx batch addresses.csv -column 1 -header

address,valid,mx,protected,disposable,role,risk,deliverability,error
ada@gmail.com,true,true,false,false,false,LOW,80,
bad-address,false,false,false,false,false,,0,emailx: invalid syntax
user@mailinator.com,true,true,true,true,false,MEDIUM,70,
FlagDefaultMeaning
-concurrency10addresses processed at once
-column0zero-based CSV column holding the address
-headeroffskip the first line

A plain list of addresses, one per line, needs no flags — rows with no comma are taken verbatim. Rows may have differing column counts.

Leave -cache at its default. A list with many addresses on the same domain then costs one set of lookups per domain rather than per address.

$ cat addresses.txt | emailx batch - -json -concurrency 25

Exit codes

CodeMeaning
0the command completed
1bad usage, a parse failure, an invalid address from validate, or an unreadable input file

batch reports per-address failures in the error column and still exits 0; one bad address in a list of thousands is data, not a command failure.