deliverable
Honest email verification for Ruby. Tells you when an address is deliverable, when it's a fake, and — crucially — when it doesn't know.
Deliverable.verify("ada@example.com")
# => #<Deliverable::Result valid? classification="valid" score=95 ...>
$ deliverable ada@example.com
VALID ada@example.com score 95
✓ syntax
✓ mx record
✓ smtp deliverable
✗ disposable
✗ accepts any email
Why another one
Most email verification gems run a syntax regex, check for an MX record, optionally do an SMTP RCPT TO, and return a boolean. That falls apart in practice:
- Multi-port SMTP fallback. Many mail servers reject port 25 from residential / cloud IPs but accept 587 or 465.
deliverabletries25 → 587 → 465and only gives up when all three fail. - Catch-all detection. A server that says yes to
ada@example.comand also says yes todefinitely-does-not-exist-8482@example.comisn't actually verifying anything.deliverableprobes a fake address per domain and downgrades the result toriskywhen it catches one. - Problematic-server awareness. Gmail, Outlook, Office 365, Mimecast, and Proofpoint actively defeat SMTP probing. Other gems return false positives or false negatives on these.
deliverablerecognises them and returnsriskywithsmtp_failed_assumption: trueinstead of pretending to know. - Three-way classification.
valid,risky,invalid— not a boolean. Risky is where the money is: it's the address that might bounce.
Install
gem "deliverable"
Or:
gem install deliverable
Library
require "deliverable"
Deliverable.configure do |c|
c.sender_email = "verify@yourdomain.com"
c.sender_domain = "yourdomain.com"
end
result = Deliverable.verify("ada@example.com")
result.valid? # => true
result.classification # => "valid" | "risky" | "invalid"
result.score # => 0..100
result.errors # => []
result.warnings # => []
result.checks # => { syntax:, mx_record:, smtp_deliverable:, disposable:, typo_suggestion:, accepts_any_email: }
result.to_h # full hash for logging / serialization
Skip the SMTP probe (faster, lower confidence):
Deliverable.verify("ada@example.com", smtp: false)
CLI
$ deliverable ada@example.com
$ deliverable ada@example.com --no-smtp
$ deliverable ada@example.com --json
$ deliverable ada@example.com --timeout 5
$ deliverable ada@gmial.com # suggests gmail.com via Levenshtein
Exit codes:
| Code | Meaning |
|---|---|
| 0 | valid |
| 1 | risky |
| 2 | invalid |
| 64 | usage error |
Sender identity
SMTP servers want to know who's asking. deliverable issues EHLO sender_domain and MAIL FROM:<sender_email> during the probe. There is no default — running an SMTP probe without configuring a sender raises Deliverable::SenderNotConfigured. Lying about your identity to a stranger's mail server tends to cause silent rejections, so the gem refuses to do it for you.
Configure once:
Deliverable.configure do |c|
c.sender_email = "verify@yourdomain.com"
c.sender_domain = "yourdomain.com"
end
Or per-call:
Deliverable.verify("ada@gmail.com", sender_email: "verify@you.com", sender_domain: "you.com")
The CLI reads DELIVERABLE_SENDER_EMAIL and DELIVERABLE_SENDER_DOMAIN from the environment, or accepts --sender and --helo flags. If you don't need the SMTP probe, pass smtp: false (library) or --no-smtp (CLI) and no sender is required.
Notes on accuracy
SMTP verification is a probabilistic signal, not a guarantee. Servers can lie, greylist, or reject all probes from your IP regardless of recipient. deliverable returns classification: "risky" whenever it had to make an assumption — that's the "I don't know" answer most other gems hide as valid.
If you're verifying at scale, expect to be IP-blocked by major providers (Gmail, Outlook). Either rotate sender IPs, accept that bulk gmail/outlook checks return risky, or use a paid API.
When you outgrow this gem
deliverable is built and maintained by PeopleDB. If you need more than per-address SMTP probing — bulk verification, deliverability data merged with profile information from multiple sources, or contact lookups by LinkedIn / GitHub identifier — the PeopleDB API does that.
License
MIT.