# smtp-probe [![Go Version](https://img.shields.io/github/go-mod/go-version/monto-fe/smtp-probe)](go.mod) [![License](https://img.shields.io/github/license/monto-fe/smtp-probe)](LICENSE) [![Release](https://img.shields.io/github/v/release/monto-fe/smtp-probe)](https://github.com/monto-fe/smtp-probe/releases) [中文文档](README_CN.md) **Powered by [uSpeedo](https://uspeedo.com/?channal_code=GITHUB)** — production-ready global email delivery API.
WeChat Work
Enterprise WeChat
WhatsApp
WhatsApp
Telegram
Telegram
- Email: support@mail-uspeedo.com - WhatsApp: [+52 8123200311](https://wa.me/528123200311) - Telegram: [@uSpeedo_Admin](https://t.me/uSpeedo_Admin) --- An open-source email deliverability diagnostic tool. Check SPF/DKIM/DMARC configuration, verify email addresses via SMTP, and scan IPs against 29 RBL blacklists — all from a single CLI or HTTP API. ## Features - **Domain Health Check** — SPF, DKIM, DMARC, MX, PTR records with 0–100 scoring - **SMTP Email Verification** — RCPT TO check via MX servers with bind-IP support - **IP Pool Management** — Multiple bind IPs with health checks and automatic failover - **Multi-Node Coordination** — GeoIP-based routing across distributed nodes - **Disposable Email Detection** — Detect temporary email providers with 4 upstream data sources (~8k–74k domains each) - **Free Email Detection** — Detect free email providers (Gmail, Outlook, Yahoo, etc.) with auto-downloaded blocklist - **RBL Blacklist Scan** — Check IPs against 29 blacklists (Spamhaus, Barracuda, SpamCop, etc.) - **Latency Probing** — Measure connection latency from each pool IP to target domains - **HTTP API** — RESTful JSON API for programmatic integration - **Multiple Output Formats** — text (CLI table), JSON, Markdown ## Installation ### Quick Install (Recommended) ```bash bash <(curl -fsSL https://raw.githubusercontent.com/monto-fe/smtp-probe/main/install.sh) ``` Or specify a version: ```bash VERSION=v0.1.0 bash <(curl -fsSL https://raw.githubusercontent.com/monto-fe/smtp-probe/main/install.sh) ``` ### From Source ```bash go install github.com/monto-fe/smtp-probe@latest ``` ## Usage ### Check Domain Configuration ```bash smtp-probe check gmail.com smtp-probe check example.com ``` ### Verify Email Address (requires outbound port 25) ```bash smtp-probe verify user@example.com smtp-probe verify user@example.com --bind-ip 1.2.3.4 --timeout 30s ``` > [!NOTE] > SMTP verification requires outbound access to port 25, which is commonly blocked by ISPs and cloud providers. The `check` command (DNS-based) works without port 25 and covers SPF/DKIM/DMARC/MX/PTR diagnostics. ### Verify with Disposable Email Detection ```bash smtp-probe verify user@mailinator.com --disposable ``` On first use with `--disposable`, the default blocklist (martenson, ~8k domains, CC0) is downloaded automatically. If the email domain is disposable, SMTP verification is skipped. ### Verify with Free Email Detection ```bash smtp-probe verify user@gmail.com --free ``` On first use with `--free`, the default free email list (dpup/freemail, ~4.5k domains, ISC) is downloaded automatically. Unlike disposable detection, SMTP verification **proceeds** after free email detection — it only annotates the result. ### Verify with IP Pool and Automatic Failover ```bash # Add IPs to pool smtp-probe pool add 1.2.3.4 --domain mail-a.example.com smtp-probe pool add 1.2.3.5 --domain mail-b.example.com # Verify with pool (auto-failover on blacklist/timeout) smtp-probe verify user@example.com --pool # Check pool health smtp-probe pool list smtp-probe pool check ``` When `--pool` is used, smtp-probe selects a healthy IP from the pool. If an IP gets blacklisted (5xx response), it's automatically marked and the next healthy IP is tried (up to 3 retries). ### Measure SMTP Latency ```bash # Single probe from default outbound IP smtp-probe probe gmail.com # Probe from each IP in the pool smtp-probe probe gmail.com --pool ``` ### Multi-Node Deployment Deploy multiple smtp-probe servers across different regions and coordinate them: ```bash # Start node A in Singapore smtp-probe serve --port 8080 \ --node-id sg-01 --region asia-southeast1 \ --lat 1.35 --lon 103.82 \ --peers http://us-node:8080,http://eu-node:8080 # Start node B in US West smtp-probe serve --port 8080 \ --node-id us-01 --region us-west1 \ --lat 37.77 --lon -122.42 \ --peers http://sg-node:8080,http://eu-node:8080 ``` Each node automatically: - Registers with all peers via heartbeat (every 30s) - Routes verification requests to the geographically closest node (based on MX server location) - Falls back to local execution if remote node is unavailable ### Check IP Against Blacklists ```bash smtp-probe blacklist 1.2.3.4 ``` ### Generate Full Report ```bash smtp-probe report example.com smtp-probe report example.com --format json smtp-probe report example.com --format md > report.md ``` ### Start HTTP Server ```bash smtp-probe serve smtp-probe serve --port 9090 # Multi-node with peers: smtp-probe serve --port 8080 --node-id node-01 --peers http://10.0.0.2:8080 ``` ## HTTP API | Endpoint | Method | Parameters | |---|---|---| | `/v1/health` | GET | — | | `/v1/check` | GET | `domain=example.com` | | `/v1/verify` | GET | `email=user@example.com`, `bind_ip=1.2.3.4`, `timeout=60s`, `disposable=true`, `free=true`, `pool=true` | | `/v1/blacklist` | GET | `ip=1.2.3.4` | | `/v1/report` | GET | `domain=example.com` | | `/v1/peer/register` | POST | `{node_id, addr, region, lat, lon, pool_size}` (multi-node) | | `/v1/peer/peers` | GET | — (list registered peers) | | `/v1/peer/heartbeat` | POST | `{node_id, ...}` (multi-node heartbeat) | | `/v1/peer/geo` | GET | `ip=1.2.3.4` (GeoIP lookup) | ```bash curl http://localhost:8080/v1/check?domain=gmail.com curl "http://localhost:8080/v1/verify?email=user@example.com" curl http://localhost:8080/v1/blacklist?ip=1.2.3.4 ``` ## Scoring System | Check | Deduction | |---|---| | No SPF | -20 | | Invalid SPF | -10 | | No DKIM | -15 | | No DMARC | -20 | | Weak DMARC (p=none) | -10 | | No MX | -30 | ## Architecture ``` smtp-probe/ ├── main.go # Entry point ├── cmd/ # Cobra CLI commands ├── pkg/ # Core packages │ ├── probe/ # Orchestrator and scoring │ ├── dnscheck/ # DNS record checks (SPF/DKIM/DMARC/MX/PTR) │ ├── disposable/ # Disposable email domain detection │ ├── freemail/ # Free email provider domain detection │ ├── pool/ # IP pool management and health checks │ ├── node/ # Multi-node coordination (GeoIP, routing, heartbeat) │ ├── rbl/ # RBL blacklist queries │ ├── smtpclient/ # SMTP RCPT TO verification │ └── types/ # Shared type definitions └── server/ # HTTP API (Gin) ``` ## Configuration ### Verification Flags | Flag | Default | Description | |---|---|---| | `--bind-ip` | (outbound IP) | Source IP for SMTP connections | | `--timeout` | 60s | SMTP/DNS timeout | | `--port` | 8080 | HTTP server port | | `--format` | text | Output format: `json`, `md`, `text` | | `--disposable` | false | Enable disposable email provider check | | `--free` | false | Enable free email provider check | | `--pool` | false | Use IP pool with automatic failover | ### IP Pool Management ```bash # Add IP to pool smtp-probe pool add 1.2.3.4 --domain mail-a.example.com # Remove IP from pool smtp-probe pool remove 1.2.3.4 # List all IPs and their status smtp-probe pool list # Check health of all IPs (RBL scan) smtp-probe pool check # Check health of a specific IP smtp-probe pool check 1.2.3.4 ``` Pool is persisted at `~/.smtp-probe/pool.json`. ### Multi-Node Flags | Flag | Default | Description | |---|---|---| | `--node-id` | (auto) | Unique identifier for this node | | `--region` | — | Region name (e.g., `asia-southeast1`, `us-west1`) | | `--lat` | 0 | Node latitude | | `--lon` | 0 | Node longitude | | `--peers` | — | Initial peer addresses (comma-separated) | | `--heartbeat` | 30s | Heartbeat interval for peer nodes | ### Managing Disposable Email Lists ```bash # List all sources and their status smtp-probe disposable list # Download specific sources smtp-probe disposable download disposable fakefilter # Download all available sources smtp-probe disposable download --all # Update stale lists (re-downloads if older than 7 days) smtp-probe disposable update # Install daily auto-update via crontab smtp-probe disposable update --install-cron ``` | Source | Domains | Default | Description | |---|---|---|---| | `martenson` | ~8k | Yes | CC0 blocklist used by PyPI | | `disposable` | ~74k | No | Multi-source aggregation | | `tompec` | ~20k | No | Successor to ivolo (suffix mode) | | `fakefilter` | ~10k | No | Automated monitoring | ### Managing Free Email Lists ```bash # List all sources and their status smtp-probe freemail list # Download the default source smtp-probe freemail download # Download all available sources smtp-probe freemail download --all # Update stale lists (re-downloads if older than 7 days) smtp-probe freemail update # Install daily auto-update via crontab smtp-probe freemail update --install-cron ``` | Source | Domains | Default | Description | |---|---|---|---| | `dpup` | ~4.5k | Yes | dpup/freemail community list | ## Development ```bash git clone https://github.com/monto-fe/smtp-probe.git cd smtp-probe go build -o smtp-probe . go test ./... ``` ## Contributing 1. Fork the repository 2. Create your feature branch (`git checkout -b feature/amazing`) 3. Run tests: `go test ./...` 4. Run linter: `golangci-lint run` 5. Commit your changes 6. Open a Pull Request ## License MIT — see [LICENSE](LICENSE)