Verify an email address in Ruby
To verify an email in Ruby, check its format with a regex, then call https://simpleverifier.com/api/v1/verify with Net::HTTP and a Bearer token. The JSON status is valid, risky or invalid. Set open and read timeouts, rescue network errors, and treat a failed request as unknown rather than invalid.
By SimpleVerifier Team
Before you start
- Create a key on the API keys page. Keys start with
sv_live_and are shown once. - Set
SIMPLEVERIFIER_KEYin the environment.ENV.fetchraisesKeyErrorif it's missing, so a misconfigured server fails loudly. - API access is included in the Pro plan ($29.99/month) and the Email + Phone plan ($49.99/month). See pricing.
1. Add the helper
Standard library only. The method-level rescue turns timeouts and connection errors into nil.
# simple_verifier.rb — Ruby 2.7+, standard library only
require "json"
require "net/http"
require "openssl"
require "uri"
module SimpleVerifier
API_URL = "https://simpleverifier.com/api/v1/verify"
EMAIL_SHAPE = /\A[^@\s]+@[^@\s]+\.[^@\s]+\z/
# Returns "valid", "risky" or "invalid", or nil when the API could not answer.
def self.email_status(email)
address = email.to_s.strip
return "invalid" unless EMAIL_SHAPE.match?(address) # no API call made
uri = URI(API_URL)
uri.query = URI.encode_www_form(email: address)
request = Net::HTTP::Get.new(uri)
request["Authorization"] = "Bearer #{ENV.fetch("SIMPLEVERIFIER_KEY")}"
response = Net::HTTP.start(uri.host, uri.port, use_ssl: true, open_timeout: 5, read_timeout: 30) do |http|
http.request(request)
end
return nil unless response.is_a?(Net::HTTPOK) # 401, 402, 429, 503: fail open
JSON.parse(response.body)["status"]
rescue Net::OpenTimeout, Net::ReadTimeout, SocketError, SystemCallError,
OpenSSL::SSL::SSLError, JSON::ParserError => e
warn "SimpleVerifier unavailable: #{e.class}"
nil
end
end2. Act on the result
Only invalid should block a person.
require_relative "simple_verifier"
case SimpleVerifier.email_status("jane@company.com")
when "invalid" then puts "Rejected: this address cannot receive mail"
when "risky" then puts "Accepted, but delivery is not confirmed"
when "valid" then puts "Accepted: the mailbox exists"
else puts "API unavailable: accepted without a mailbox check"
endWhat the API returns
GET or POST https://simpleverifier.com/api/v1/verify with email runs the syntax, domain, disposable-domain and live mailbox checks in one call and returns:
{
"email": "jane@company.com",
"status": "valid",
"reason": "Mailbox exists",
"mailbox_checked": true
}Every snippet above follows the same rule: only a successful response with status set to invalid blocks a person.
| Result | What it means | What to do |
|---|---|---|
| valid | The mail server confirmed the mailbox exists. | Accept. |
| risky | The domain is real but the mailbox couldn't be confirmed: catch-all domains, role addresses like info@, providers that hide mailbox status. | Accept on signup forms. Store the status and keep these out of cold campaigns. |
| invalid | Bad format, no mail server, a disposable domain, or the mailbox doesn't exist. | Reject and ask the person to check the address. |
| timeout, 429 or 503 | The check didn't finish: a slow mail server, too many calls this minute, or a brief outage. | Accept (fail open) and log it. Re-check later if it matters. |
| 401 or 402 | The key is wrong or revoked, or the subscription isn't active. | Accept, and alert yourself: every check is being skipped until it's fixed. |
Errors return JSON with an error message. Each key can make 120 calls a minute; for thousands of addresses, upload a CSV in the dashboard instead.
Phone numbers and spreadsheets
The same key works with /api/v1/phone?phone=…&country=… to validate a phone number and normalise it to E.164, with live carrier lookups on the Email + Phone plan. The request and response are in the API reference. To check a column of addresses without code, use the Google Sheets add-on with the same key.
Common questions
- Can I use Faraday or HTTParty instead of Net::HTTP?
- Yes. Send GET https://simpleverifier.com/api/v1/verify with the email query parameter and an Authorization: Bearer header, set a 30-second timeout, and read status from the JSON body. The handling of the result is the same.
- Why does a timeout return nil instead of invalid?
- A timeout means the check didn't finish, not that the address is bad. Treating it as invalid would turn away real people whenever a mail server is slow.
- How much does the SimpleVerifier API cost?
- API access is included in the paid plans: Pro at $29.99/month and Email + Phone at $49.99/month. There are no per-call credits. Each key can make 120 calls a minute.
- Should I reject risky addresses?
- Not on a signup or contact form. Risky means the mailbox couldn't be confirmed, which includes every address at a catch-all company domain. Accept it, store the status, and leave risky addresses out of cold outreach.
- What if the API is slow or down?
- Let the address through. A mailbox check can take several seconds when a mail server is slow, so cap the wait at about 30 seconds (less on a busy form) and treat a timeout, a 429 or a 503 as unknown rather than invalid.