emailverify 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 81ab97eed6690176d532cd155fe2d5952ab4cf47887b8c0a16d0ff0605faf9c1
4
+ data.tar.gz: ed2cd57e4596d1977b90941c259aa4e9444171ddb2978c4dfb144266201d1e1b
5
+ SHA512:
6
+ metadata.gz: 9ae75962bb1ce322a1776bf17a59f6d56dc9fdc97ffe20c81c49dd43807ec9facf07a7712e75396ade2584653504ef4e79a0fbe3ad8f3d2865e75b973da64eea
7
+ data.tar.gz: dd366392f16f460abc192d1c02c9598005b85b92fcb0ad9923e7788b3b820736b4fa78ecc6bced3dcd5c1abdae502b2c62ffea00c8865a539fbb00dcda15eb2e
data/LICENSE ADDED
@@ -0,0 +1,18 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Your Name
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
15
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
18
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,81 @@
1
+ # Emailverify Ruby Gem
2
+
3
+ emailverify is a small, object-oriented Ruby client for the EmailVerify.io API.
4
+
5
+ Features
6
+ - Simple configuration (only the API key is required by default)
7
+ - Clean wrapper methods: validate, valid?, and check_balance
8
+ - Abstracts HTTP details using Faraday
9
+
10
+ Quick start
11
+
12
+ 1) Add to your Gemfile or install locally
13
+
14
+ ```ruby
15
+ gem "emailverify", git: "https://github.com/Clustox/emailverify-ruby.git"
16
+ ```
17
+
18
+
19
+ 2) Configure (only api_key is strictly required)
20
+
21
+ ```ruby
22
+ Emailverify.configure do |config|
23
+ config.api_key = "YOUR_API_KEY"
24
+ end
25
+
26
+ request = Emailverify::Request.new
27
+ result = request.validate("jane@example.com")
28
+
29
+ if request.valid?("jane@example.com")
30
+ puts "valid"
31
+ else
32
+ puts "invalid"
33
+ end
34
+
35
+ balance = request.check_balance # or client.check_balance(batch_id)
36
+
37
+ # Validate example (EmailVerify.io v1)
38
+ # The gem will call:
39
+ # https://app.emailverify.io/api/v1/validate?key=<YOUR_API_KEY>&email=valid@example.com
40
+ # and return parsed JSON, for example:
41
+ # {
42
+ # "email": "jhon123@gmail.com",
43
+ # "status": "valid",
44
+ # "sub_status": "permitted"
45
+ # }
46
+
47
+ # Modern usage (Response objects)
48
+ # The client now returns an `Emailverify::Response` wrapper with helper accessors.
49
+ Emailverify.configure do |c|
50
+ c.apikey = ENV['EMAILVERIFY_API_KEY']
51
+ end
52
+
53
+ # Module-level convenience
54
+ resp = Emailverify.validate(email: 'jane@example.com')
55
+ puts resp.status # => 'valid' (string)
56
+ puts resp.sub_status # => 'permitted' or nil
57
+ puts resp.to_h # => raw Hash if you need it
58
+
59
+ balance = Emailverify.check_balance
60
+ puts balance.api_status # => 'enabled'
61
+ puts balance.available_credits
62
+
63
+ # Balance example (EmailVerify.io v2)
64
+ # The gem will call:
65
+ # https://app.emailverify.io/api/v2/check-account-balance?key=<YOUR_API_KEY>
66
+ # and return the parsed JSON, for example:
67
+ # {
68
+ # "api_status": "enabled",
69
+ # "available_credits": 16750
70
+ # }
71
+
72
+ ```
73
+
74
+ Notes on endpoints
75
+ The gem ships with sensible defaults for endpoints, but your service may have different paths. You can pass an `endpoint:` option to each method or override the configured endpoints via `Emailverify.configure`.
76
+
77
+ Security
78
+ - The client will send the API key in an Authorization header for endpoints that expect it. The EmailVerify.io endpoints used by this gem (v1 validate and v2 check-account-balance) use the `key` query parameter, and the client passes this automatically for those methods.
79
+
80
+ Contributing
81
+ Pull requests welcome. Run tests with `bundle install && bundle exec rake`.
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require "rake/testtask"
2
+ require "rspec/core/rake_task"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.test_files = Dir["spec/**/*_spec.rb"]
7
+ end
8
+
9
+ RSpec::Core::RakeTask.new(:spec)
10
+
11
+ task default: :spec
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "emailverify"
5
+ spec.version = Emailverify::VERSION rescue "0.1.0"
6
+ spec.authors = ["Salman Aslam"]
7
+ spec.email = ["you@example.com"]
8
+
9
+ spec.summary = "Ruby wrapper for the EmailVerify.io API"
10
+ spec.description = "A small, object-oriented Ruby client for the EmailVerify.io service."
11
+ spec.homepage = "https://github.com/yourname/emailverify"
12
+ spec.license = "MIT"
13
+
14
+ spec.required_ruby_version = '>= 2.7.0'
15
+
16
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
17
+ `git ls-files -z`.split("\x0").select { |f| f =~ /^(lib|README|LICENSE|Rakefile|emailverify\.gemspec)/ }
18
+ rescue
19
+ Dir["lib/**/*"] + %w[README.md LICENSE Rakefile emailverify.gemspec]
20
+ end
21
+
22
+ # 👉 Fix open-ended dependency warnings
23
+ spec.add_runtime_dependency "faraday", "~> 1.0"
24
+ spec.add_runtime_dependency "json", "~> 2.0"
25
+
26
+ # 👉 Dev dependency also fixed
27
+ spec.add_development_dependency "rspec", "~> 3.0"
28
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Emailverify
4
+ class Configuration
5
+ attr_accessor :api_key, :timeout, :logger, :endpoints
6
+ attr_reader :base_url
7
+
8
+ def initialize
9
+ @api_key = nil
10
+ # Base URL is fixed to the official EmailVerify.io host
11
+ @base_url = "https://app.emailverify.io"
12
+ @timeout = 10
13
+ @logger = nil
14
+ # endpoints can be overridden by the user to match their API paths
15
+ @endpoints = {
16
+ # EmailVerify.io single email validation endpoint (v1)
17
+ validate: "/api/v1/validate",
18
+ # EmailVerify.io check account balance endpoint (v2)
19
+ check_balance: "/api/v2/check-account-balance"
20
+ }
21
+ end
22
+
23
+ # ZeroBounce-style alias: allow `config.apikey = 'key'` to set api_key
24
+ def apikey=(val)
25
+ self.api_key = val
26
+ end
27
+
28
+ def apikey
29
+ api_key
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Emailverify
4
+ class Error < StandardError; end
5
+ class AuthenticationError < Error; end
6
+ class RequestError < Error; end
7
+ class UnexpectedResponseError < Error; end
8
+ end
@@ -0,0 +1,135 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "faraday"
4
+ require "json"
5
+
6
+ module Emailverify
7
+ class Request
8
+ DEFAULT_HEADERS = { "Content-Type" => "application/json" }.freeze
9
+
10
+ def initialize(api_key: nil, base_url: nil, timeout: nil)
11
+ @config = Emailverify.configuration
12
+ @api_key = api_key || @config.api_key
13
+ @base_url = base_url || @config.base_url
14
+ @timeout = timeout || @config.timeout
15
+
16
+ raise AuthenticationError, "API key missing" unless @api_key
17
+ raise RequestError, "base_url must be configured" unless @base_url
18
+
19
+ @conn = Faraday.new(url: @base_url) do |faraday|
20
+ faraday.request :url_encoded
21
+ faraday.adapter Faraday.default_adapter
22
+ faraday.options.timeout = @timeout
23
+ end
24
+ end
25
+
26
+ # Validate a single email address. Returns parsed JSON from the API.
27
+ # By default this uses EmailVerify.io's v1 endpoint which expects GET
28
+ # with query params `key` and `email`, e.g.:
29
+ # https://app.emailverify.io/api/v1/validate?key=yourapikey&email=valid@example.com
30
+ # You can override the endpoint path via `endpoint:` if the API differs.
31
+ def validate(email, endpoint: nil)
32
+ path = endpoint || @config.endpoints[:validate]
33
+ params = { key: @api_key, email: email }
34
+ request(:get, path, params: params)
35
+ end
36
+
37
+ # Return boolean true/false for whether the email is valid.
38
+ # For EmailVerify.io v1 the API returns `status` with values like
39
+ # "valid", "invalid" and may include `sub_status` such as "permitted".
40
+ # This method returns true when `status` equals "valid" (case-insensitive).
41
+ def valid?(email, endpoint: nil)
42
+ resp = validate(email, endpoint: endpoint)
43
+
44
+ # Support Response objects or raw Hashes
45
+ status_value = if resp.respond_to?(:status)
46
+ resp.status
47
+ elsif resp.is_a?(Hash)
48
+ resp["status"] || resp[:status]
49
+ else
50
+ nil
51
+ end
52
+
53
+ return false unless status_value
54
+ status_value.to_s.strip.downcase == "valid"
55
+ end
56
+
57
+ # Check balance or status of a completed batch. Accepts an id or options.
58
+ # Check account balance. By default this calls the EmailVerify.io endpoint
59
+ # /api/v2/check-account-balance and passes the API key as the `key` query param
60
+ # (https://app.emailverify.io/api/v2/check-account-balance?key=<Your_API_Key>)
61
+ # If your provider uses a different pattern you may pass `endpoint:` or
62
+ # override `Emailverify.configuration.endpoints[:check_balance]`.
63
+ def check_balance(batch_id = nil, endpoint: nil)
64
+ path = endpoint || @config.endpoints[:check_balance]
65
+
66
+ # If a batch_id is provided, append it to the path (useful for batch status
67
+ # endpoints that accept an id as part of the path).
68
+ if batch_id
69
+ path = File.join(path, batch_id.to_s)
70
+ end
71
+
72
+ # EmailVerify.io expects the API key as query param `key` for this endpoint.
73
+ params = { key: @api_key }
74
+
75
+ request(:get, path, params: params)
76
+ end
77
+
78
+ # (auth_check endpoint removed) If you need a custom check you can call
79
+ # `client.request(:get, path, params: { key: ... })` directly or supply the
80
+ # endpoint to the high-level methods.
81
+
82
+ private
83
+
84
+ def request(method, path, json: nil, params: nil)
85
+ raise RequestError, "path is required" unless path
86
+
87
+ headers = DEFAULT_HEADERS.merge("Authorization" => "Bearer #{@api_key}")
88
+
89
+ response = @conn.send(method) do |req|
90
+ req.url path
91
+ req.headers.update(headers)
92
+ req.params.update(params) if params
93
+ req.body = JSON.generate(json) if json
94
+ end
95
+
96
+ case response.status
97
+ when 200..299
98
+ parsed = parse_body(response.body)
99
+ # Wrap parsed JSON hashes in a Response object for a nicer API
100
+ return Emailverify::Response.new(parsed) if parsed.is_a?(Hash)
101
+ parsed
102
+ when 401, 403
103
+ raise AuthenticationError, "authentication failed (status=#{response.status})"
104
+ else
105
+ raise RequestError, "request failed (status=#{response.status}): #{response.body}"
106
+ end
107
+ rescue Faraday::TimeoutError => e
108
+ raise RequestError, "request timeout: #{e.message}"
109
+ rescue Faraday::ConnectionFailed => e
110
+ raise RequestError, "connection failed: #{e.message}"
111
+ end
112
+
113
+ def parse_body(body)
114
+ return {} if body.nil? || body.strip.empty?
115
+ JSON.parse(body)
116
+ rescue JSON::ParserError
117
+ raise UnexpectedResponseError, "Invalid JSON response"
118
+ end
119
+
120
+ def truthy_value?(val)
121
+ return true if val == true
122
+ return true if val.is_a?(String) && val.strip.downcase == "true"
123
+ return true if val.is_a?(Numeric) && val.to_f > 0
124
+ false
125
+ end
126
+
127
+ def falsy_value?(val)
128
+ return true if val == false
129
+ return true if val.nil?
130
+ return true if val.is_a?(String) && val.strip.empty?
131
+ return true if val.is_a?(Numeric) && val.to_f == 0
132
+ false
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "time"
4
+
5
+ module Emailverify
6
+ # Generic Response wrapper for Emailverify API responses.
7
+ #
8
+ # Provides a V1Response module with common helpers similar to
9
+ # the ZeroBounce response structure (status, sub_status, disposable?, ...).
10
+ # Use by wrapping a parsed JSON Hash:
11
+ #
12
+ # resp = Emailverify::Response.new(parsed_json)
13
+ # resp.status
14
+ class Response
15
+ attr_reader :body
16
+
17
+ def initialize(body)
18
+ # normalize keys to strings for convenient access
19
+ @body = (body || {}).each_with_object({}) { |(k, v), h| h[k.to_s] = v }
20
+ end
21
+
22
+ # Return underlying hash
23
+ def to_h
24
+ @body.dup
25
+ end
26
+
27
+ # Minimal EmailVerify-specific helpers. This gem's API response shape
28
+ # differs from ZeroBounce; expose small, explicit accessors instead of
29
+ # mirroring ZeroBounce internals.
30
+
31
+ # Email address returned by the API (if present)
32
+ def email
33
+ @email ||= @body["email"] || @body["email_address"]
34
+ end
35
+
36
+ # Status field as returned by the API (string)
37
+ def status
38
+ @status ||= @body["status"]
39
+ end
40
+
41
+ # Sub-status (string) if present
42
+ def sub_status
43
+ @sub_status ||= @body["sub_status"] || @body["sub-status"] || @body["substatus"]
44
+ end
45
+
46
+ # For balance responses: api_status
47
+ def api_status
48
+ @api_status ||= @body["api_status"]
49
+ end
50
+
51
+ # For balance responses: available_credits as Integer
52
+ def available_credits
53
+ val = @body["available_credits"] || @body["availableCredits"] || @body["credits"]
54
+ val.nil? ? nil : val.to_i
55
+ end
56
+
57
+ # Generic accessor by key
58
+ def [](key)
59
+ @body[key.to_s]
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Emailverify
4
+ VERSION = "0.1.0"
5
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "emailverify/version"
4
+ require_relative "emailverify/configuration"
5
+ require_relative "emailverify/errors"
6
+ require_relative "emailverify/request"
7
+ require_relative "emailverify/response"
8
+
9
+ module Emailverify
10
+ class << self
11
+ # Configure the gem using a block:
12
+ #
13
+ # Emailverify.configure do |config|
14
+ # config.apikey = "xxx"
15
+ # end
16
+ def configure
17
+ yield configuration if block_given?
18
+ configuration
19
+ end
20
+
21
+ def configuration
22
+ @configuration ||= Configuration.new
23
+ end
24
+
25
+ def reset!
26
+ @configuration = Configuration.new
27
+ end
28
+
29
+ # Convenience client helper — builds a client using current configuration
30
+ def request
31
+ @request ||= Request.new(api_key: configuration.api_key, base_url: configuration.base_url, timeout: configuration.timeout)
32
+ end
33
+
34
+ def validate(email:, endpoint: nil)
35
+ request.validate(email, endpoint: endpoint)
36
+ end
37
+
38
+ def valid?(email:, endpoint: nil)
39
+ request.valid?(email, endpoint: endpoint)
40
+ end
41
+
42
+ def check_balance(batch_id = nil, endpoint: nil)
43
+ request.check_balance(batch_id, endpoint: endpoint)
44
+ end
45
+
46
+ # Load configuration from environment variables; helpful for CLI/CI use.
47
+ # EMAILVERIFY_API_KEY and EMAILVERIFY_BASE_URL are supported, but base_url
48
+ # will be ignored and remain the fixed app.emailverify.io host per design.
49
+ def configure_from_env(env = ENV)
50
+ configuration.api_key ||= env["EMAILVERIFY_API_KEY"]
51
+ # ignore env base_url to keep fixed host; but store if present
52
+ configuration
53
+ end
54
+ end
55
+ end
56
+
metadata ADDED
@@ -0,0 +1,95 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: emailverify
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Salman Aslam
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2025-11-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: faraday
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: json
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ description: A small, object-oriented Ruby client for the EmailVerify.io service.
56
+ email:
57
+ - you@example.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - LICENSE
63
+ - README.md
64
+ - Rakefile
65
+ - emailverify.gemspec
66
+ - lib/emailverify.rb
67
+ - lib/emailverify/configuration.rb
68
+ - lib/emailverify/errors.rb
69
+ - lib/emailverify/request.rb
70
+ - lib/emailverify/response.rb
71
+ - lib/emailverify/version.rb
72
+ homepage: https://github.com/yourname/emailverify
73
+ licenses:
74
+ - MIT
75
+ metadata: {}
76
+ post_install_message:
77
+ rdoc_options: []
78
+ require_paths:
79
+ - lib
80
+ required_ruby_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: 2.7.0
85
+ required_rubygems_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ requirements: []
91
+ rubygems_version: 3.4.10
92
+ signing_key:
93
+ specification_version: 4
94
+ summary: Ruby wrapper for the EmailVerify.io API
95
+ test_files: []