Class: VerifyAnyEmail::Client
- Inherits:
-
Object
- Object
- VerifyAnyEmail::Client
- Defined in:
- lib/verifyanyemail/client.rb
Overview
HTTP client for the VerifyAnyEmail API.
Constant Summary collapse
- DEFAULT_BASE_URL =
Default API base URL.
"https://api.verifyany.email"- DEFAULT_TIMEOUT =
Default per-request timeout, in seconds.
30
Instance Attribute Summary collapse
-
#base_url ⇒ String
readonly
Base URL (no trailing slash).
-
#timeout ⇒ Integer, Float
readonly
Request timeout in seconds.
Class Method Summary collapse
-
.secure_compare(a, b) ⇒ Boolean
Constant-time string comparison that is safe when lengths differ.
-
.verify_webhook_signature(raw_body, signature_header, secret) ⇒ Boolean
Verify a webhook signature using a length-safe, constant-time comparison.
Instance Method Summary collapse
-
#get_batch(id) ⇒ Hash
Fetch the status and summary of a batch.
-
#get_batch_results(id, page: 1, page_size: 100) ⇒ Hash
Fetch a page of batch results.
-
#initialize(api_key, base_url: DEFAULT_BASE_URL, timeout: DEFAULT_TIMEOUT) ⇒ Client
constructor
A new instance of Client.
-
#verify(email, smtp_probe: nil, catch_all_detection: nil) ⇒ VerifyAnyEmail::VerificationResult
Verify a single email address.
-
#verify_batch(emails, name: nil, webhook_url: nil) ⇒ Hash
Submit a batch of addresses for asynchronous verification.
Constructor Details
#initialize(api_key, base_url: DEFAULT_BASE_URL, timeout: DEFAULT_TIMEOUT) ⇒ Client
Returns a new instance of Client.
32 33 34 35 36 37 38 |
# File 'lib/verifyanyemail/client.rb', line 32 def initialize(api_key, base_url: DEFAULT_BASE_URL, timeout: DEFAULT_TIMEOUT) raise ArgumentError, "api_key is required" if api_key.nil? || api_key.to_s.empty? @api_key = api_key @base_url = base_url.to_s.sub(%r{/+\z}, "") @timeout = timeout end |
Instance Attribute Details
#base_url ⇒ String (readonly)
Returns Base URL (no trailing slash).
23 24 25 |
# File 'lib/verifyanyemail/client.rb', line 23 def base_url @base_url end |
#timeout ⇒ Integer, Float (readonly)
Returns Request timeout in seconds.
26 27 28 |
# File 'lib/verifyanyemail/client.rb', line 26 def timeout @timeout end |
Class Method Details
.secure_compare(a, b) ⇒ Boolean
Constant-time string comparison that is safe when lengths differ.
Uses OpenSSL.fixed_length_secure_compare when available (Ruby 2.6+), falling back to a manual constant-time XOR comparison.
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/verifyanyemail/client.rb', line 122 def self.secure_compare(a, b) a = a.to_s b = b.to_s if OpenSSL.respond_to?(:fixed_length_secure_compare) # fixed_length_secure_compare raises when lengths differ, so guard first. return false unless a.bytesize == b.bytesize begin return OpenSSL.fixed_length_secure_compare(a, b) rescue StandardError # Fall through to the manual comparison below. end end return false unless a.bytesize == b.bytesize diff = 0 a.bytes.each_with_index do |byte, i| diff |= byte ^ b.getbyte(i) end diff.zero? end |
.verify_webhook_signature(raw_body, signature_header, secret) ⇒ Boolean
Verify a webhook signature using a length-safe, constant-time comparison.
99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/verifyanyemail/client.rb', line 99 def self.verify_webhook_signature(raw_body, signature_header, secret) return false if signature_header.nil? || secret.nil? || secret.to_s.empty? provided = signature_header.to_s.strip provided = provided.sub(/\Asha256=/, "") expected = OpenSSL::HMAC.hexdigest( OpenSSL::Digest.new("sha256"), secret.to_s, raw_body.to_s ) secure_compare(expected, provided) end |
Instance Method Details
#get_batch(id) ⇒ Hash
Fetch the status and summary of a batch.
76 77 78 |
# File 'lib/verifyanyemail/client.rb', line 76 def get_batch(id) request(:get, "/v1/verify/batch/#{escape(id)}") end |
#get_batch_results(id, page: 1, page_size: 100) ⇒ Hash
Fetch a page of batch results.
87 88 89 90 |
# File 'lib/verifyanyemail/client.rb', line 87 def get_batch_results(id, page: 1, page_size: 100) query = { "page" => page, "pageSize" => page_size } request(:get, "/v1/verify/batch/#{escape(id)}/results", query: query) end |
#verify(email, smtp_probe: nil, catch_all_detection: nil) ⇒ VerifyAnyEmail::VerificationResult
Verify a single email address.
47 48 49 50 51 52 53 54 |
# File 'lib/verifyanyemail/client.rb', line 47 def verify(email, smtp_probe: nil, catch_all_detection: nil) body = { "email" => email } body["smtpProbe"] = smtp_probe unless smtp_probe.nil? body["catchAllDetection"] = catch_all_detection unless catch_all_detection.nil? response = request(:post, "/v1/verify", body: body) VerificationResult.new(response["result"] || {}) end |
#verify_batch(emails, name: nil, webhook_url: nil) ⇒ Hash
Submit a batch of addresses for asynchronous verification.
63 64 65 66 67 68 69 |
# File 'lib/verifyanyemail/client.rb', line 63 def verify_batch(emails, name: nil, webhook_url: nil) body = { "emails" => Array(emails) } body["name"] = name unless name.nil? body["webhookUrl"] = webhook_url unless webhook_url.nil? request(:post, "/v1/verify/batch", body: body) end |