truelist-rails 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: 8d9bf2a865512806998948b308b302c98a30edab2919c23ad3bd6c3b22d93191
4
+ data.tar.gz: 382931bfc3208ad233801783b070d92c998d529f6d7bdc7863b8292422471b4d
5
+ SHA512:
6
+ metadata.gz: '085a171c764b96fc40dbfb188f4391fca2e4be34195cbf98f9ef6f297a9642e955f035dd8a6b533e04f9d9bc165a5ee9698ae6817448b9c7ea5c3a295021d006'
7
+ data.tar.gz: e178b7747e44a6efcc31565f42fda5d0d2e23dd4922dcb4d0978dd6602190d978492b62ece467dfe63c8704c95390793777361e7566cdad16ff445b4f6249270
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Truelist
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 above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,261 @@
1
+ # truelist-rails
2
+
3
+ [![Free tier](https://img.shields.io/badge/free_plan-100_validations-4A7C59?style=flat-square)](https://truelist.io/pricing)
4
+ Email validation for Rails, powered by [Truelist.io](https://truelist.io).
5
+
6
+ [![Gem Version](https://badge.fury.io/rb/truelist-rails.svg)](https://badge.fury.io/rb/truelist-rails)
7
+ [![CI](https://github.com/Truelist-io-Email-Validation/truelist-rails/actions/workflows/ci.yml/badge.svg)](https://github.com/Truelist-io-Email-Validation/truelist-rails/actions/workflows/ci.yml)
8
+
9
+ Validate email deliverability in your Rails models with a single line:
10
+
11
+ ```ruby
12
+ validates :email, deliverable: true
13
+ ```
14
+
15
+ Truelist checks whether an email address actually exists and can receive mail, catching typos, disposable addresses, and invalid mailboxes before they hit your database.
16
+
17
+ > **Start free** — 100 validations + 10 enhanced credits, no credit card required.
18
+ > [Get your API key →](https://app.truelist.io/signup?utm_source=github&utm_medium=readme&utm_campaign=free-plan&utm_content=truelist-rails)
19
+
20
+ ## Installation
21
+
22
+ Add to your Gemfile:
23
+
24
+ ```ruby
25
+ gem "truelist-rails"
26
+ ```
27
+
28
+ Then run:
29
+
30
+ ```bash
31
+ bundle install
32
+ ```
33
+
34
+ ## Quick Start
35
+
36
+ ### 1. Configure your API key
37
+
38
+ Set the `TRUELIST_API_KEY` environment variable, or run the install generator:
39
+
40
+ ```bash
41
+ rails generate truelist:install
42
+ ```
43
+
44
+ This creates `config/initializers/truelist.rb` where you can configure the gem.
45
+
46
+ ### 2. Add the validator
47
+
48
+ ```ruby
49
+ class User < ApplicationRecord
50
+ validates :email, presence: true, deliverable: true
51
+ end
52
+ ```
53
+
54
+ That's it. Invalid emails will now fail validation with a clear error message.
55
+
56
+ ## Configuration
57
+
58
+ ```ruby
59
+ Truelist.configure do |config|
60
+ # Your Truelist API key (required).
61
+ # Defaults to ENV["TRUELIST_API_KEY"].
62
+ config.api_key = ENV["TRUELIST_API_KEY"]
63
+
64
+ # API base URL. Change only for testing or proxying.
65
+ config.base_url = "https://api.truelist.io"
66
+
67
+ # Request timeout in seconds.
68
+ config.timeout = 10
69
+
70
+ # When true, raises Truelist::Error on API failures.
71
+ # When false (default), returns an "unknown" result on errors,
72
+ # allowing the validation to pass gracefully.
73
+ config.raise_on_error = false
74
+
75
+ # Whether "accept_all" emails (domains that accept all addresses) pass validation.
76
+ config.allow_risky = true
77
+
78
+ # Optional cache store for validation results.
79
+ # Accepts any Rails-compatible cache store.
80
+ config.cache_store = Rails.cache
81
+
82
+ # How long to cache validation results (in seconds).
83
+ config.cache_ttl = 1.hour
84
+ end
85
+ ```
86
+
87
+ ## Validator Options
88
+
89
+ ### Basic usage
90
+
91
+ ```ruby
92
+ validates :email, deliverable: true
93
+ ```
94
+
95
+ ### Reject accept_all emails
96
+
97
+ ```ruby
98
+ validates :email, deliverable: { allow_risky: false }
99
+ ```
100
+
101
+ ### Custom error message
102
+
103
+ ```ruby
104
+ validates :email, deliverable: { message: "is not a valid email address" }
105
+ ```
106
+
107
+ ### Combine options
108
+
109
+ ```ruby
110
+ validates :email, deliverable: { allow_risky: false, message: "doesn't look right" }
111
+ ```
112
+
113
+ ### Use with other validators
114
+
115
+ ```ruby
116
+ validates :email, presence: true,
117
+ format: { with: URI::MailTo::EMAIL_REGEXP },
118
+ deliverable: true
119
+ ```
120
+
121
+ The `deliverable` validator skips blank values, so pair it with `presence: true` if the field is required.
122
+
123
+ ## Working with Results Directly
124
+
125
+ Use the client to validate emails outside of model validations:
126
+
127
+ ```ruby
128
+ result = Truelist.validate("user@example.com")
129
+
130
+ result.state # => "ok", "email_invalid", "accept_all", or "unknown"
131
+ result.sub_state # => "email_ok", "is_disposable", "is_role", etc.
132
+ result.valid? # => true when state is "ok" (or "accept_all" with allow_risky)
133
+ result.invalid? # => true when state is "email_invalid"
134
+ result.accept_all? # => true when state is "accept_all"
135
+ result.unknown? # => true when state is "unknown"
136
+
137
+ result.email # => the validated email address
138
+ result.suggestion # => suggested correction, if available
139
+ result.domain # => email domain
140
+ result.canonical # => local part of the email
141
+ result.mx_record # => MX record for the domain
142
+ result.first_name # => first name, if available
143
+ result.last_name # => last name, if available
144
+ result.verified_at # => timestamp of verification
145
+ result.disposable? # => whether it's a disposable/temporary address (sub_state)
146
+ result.role? # => whether it's a role address (sub_state)
147
+ ```
148
+
149
+ ### Account Info
150
+
151
+ ```ruby
152
+ client = Truelist::Client.new
153
+ account = client.account
154
+
155
+ account["email"] # => "team@company.com"
156
+ account["name"] # => "Team Lead"
157
+ account["uuid"] # => "a3828d19-..."
158
+ account["account"]["payment_plan"] # => "pro"
159
+ ```
160
+
161
+ ### Sub-states
162
+
163
+ | Sub-state | Meaning |
164
+ |-----------|---------|
165
+ | `email_ok` | Email is valid and deliverable |
166
+ | `is_disposable` | Disposable/temporary email |
167
+ | `is_role` | Role-based address (info@, admin@) |
168
+ | `failed_smtp_check` | SMTP check failed |
169
+ | `failed_mx_check` | Domain has no mail server |
170
+ | `failed_spam_trap` | Known spam trap address |
171
+ | `failed_no_mailbox` | Mailbox does not exist |
172
+ | `failed_greylisted` | Server temporarily rejected (greylisting) |
173
+ | `failed_syntax_check` | Email format is invalid |
174
+ | `unknown_error` | Could not determine status |
175
+
176
+ ## Caching
177
+
178
+ Enable caching to avoid redundant API calls for recently validated emails:
179
+
180
+ ```ruby
181
+ Truelist.configure do |config|
182
+ config.cache_store = Rails.cache
183
+ config.cache_ttl = 1.hour
184
+ end
185
+ ```
186
+
187
+ The cache key is based on the lowercase, stripped email address. Any Rails-compatible cache store works (Redis, Memcached, file store, etc.).
188
+
189
+ ## Error Handling
190
+
191
+ By default, API errors (timeouts, rate limits, server errors) return an `unknown` result, allowing validation to pass. This prevents your forms from breaking when the API is unreachable.
192
+
193
+ To raise exceptions instead:
194
+
195
+ ```ruby
196
+ Truelist.configure do |config|
197
+ config.raise_on_error = true
198
+ end
199
+ ```
200
+
201
+ Exception classes:
202
+
203
+ - `Truelist::Error` -- base error class
204
+ - `Truelist::ApiError` -- unexpected API responses
205
+ - `Truelist::AuthenticationError` -- invalid API key (401)
206
+ - `Truelist::RateLimitError` -- rate limit exceeded (429)
207
+
208
+ ## Testing
209
+
210
+ Stub the API in your tests to avoid real HTTP calls. With WebMock:
211
+
212
+ ```ruby
213
+ # spec/support/truelist.rb
214
+ RSpec.configure do |config|
215
+ config.before do
216
+ stub_request(:post, "https://api.truelist.io/api/v1/verify_inline")
217
+ .with(query: hash_including(email: /.+/))
218
+ .to_return(
219
+ status: 200,
220
+ body: {
221
+ emails: [{
222
+ address: "user@example.com",
223
+ email_state: "ok",
224
+ email_sub_state: "email_ok"
225
+ }]
226
+ }.to_json,
227
+ headers: { "Content-Type" => "application/json" }
228
+ )
229
+ end
230
+ end
231
+ ```
232
+
233
+ Or stub at the client level:
234
+
235
+ ```ruby
236
+ allow(Truelist::Client).to receive(:new).and_return(
237
+ instance_double(Truelist::Client, validate: Truelist::Result.new(email: "user@example.com", state: "ok"))
238
+ )
239
+ ```
240
+
241
+ ## Requirements
242
+
243
+ - Ruby >= 3.0
244
+ - Rails >= 7.0 (ActiveModel / ActiveSupport)
245
+
246
+ ## Development
247
+
248
+ ```bash
249
+ git clone https://github.com/Truelist-io-Email-Validation/truelist-rails.git
250
+ cd truelist-rails
251
+ bundle install
252
+ bundle exec rspec
253
+ ```
254
+
255
+
256
+ ## Getting Started
257
+
258
+ Sign up for a [free Truelist account](https://app.truelist.io/signup?utm_source=github&utm_medium=readme&utm_campaign=free-plan&utm_content=truelist-rails) to get your API key. The free plan includes 100 validations and 10 enhanced credits — no credit card required.
259
+ ## License
260
+
261
+ Released under the [MIT License](LICENSE).
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Truelist
4
+ module Generators
5
+ class InstallGenerator < Rails::Generators::Base
6
+ source_root File.expand_path('templates', __dir__)
7
+
8
+ desc 'Creates a Truelist initializer in config/initializers'
9
+
10
+ def create_initializer
11
+ template 'initializer.rb', 'config/initializers/truelist.rb'
12
+ end
13
+
14
+ def show_instructions
15
+ say ''
16
+ say 'Truelist initializer created at config/initializers/truelist.rb', :green
17
+ say ''
18
+ say 'Next steps:'
19
+ say ' 1. Set your API key via TRUELIST_API_KEY environment variable'
20
+ say ' or uncomment the api_key line in the initializer'
21
+ say ' 2. Add `validates :email, deliverable: true` to your models'
22
+ say ''
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ Truelist.configure do |config|
4
+ # Your Truelist API key. Defaults to ENV["TRUELIST_API_KEY"].
5
+ # config.api_key = ENV["TRUELIST_API_KEY"]
6
+
7
+ # API base URL (change only for testing/proxying).
8
+ # config.base_url = "https://api.truelist.io"
9
+
10
+ # Request timeout in seconds.
11
+ # config.timeout = 10
12
+
13
+ # When true, raises Truelist::Error on API failures.
14
+ # When false (default), returns an "unknown" result on errors.
15
+ # config.raise_on_error = false
16
+
17
+ # Whether "accept_all" emails pass validation.
18
+ # config.allow_risky = true
19
+
20
+ # Optional cache store for validation results.
21
+ # Uses any Rails-compatible cache store (e.g., Rails.cache).
22
+ # config.cache_store = Rails.cache
23
+
24
+ # How long to cache validation results.
25
+ # config.cache_ttl = 1.hour
26
+ end
@@ -0,0 +1,125 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'net/http'
4
+ require 'uri'
5
+ require 'json'
6
+
7
+ module Truelist
8
+ class Client
9
+ def initialize(config: Truelist.configuration)
10
+ @config = config
11
+ end
12
+
13
+ def validate(email)
14
+ cached = read_cache(email)
15
+ return cached if cached
16
+
17
+ result = perform_request(email)
18
+ write_cache(email, result) unless result.unknown?
19
+ result
20
+ end
21
+
22
+ def account
23
+ uri = URI("#{@config.base_url}/me")
24
+ http = build_http(uri)
25
+
26
+ request = Net::HTTP::Get.new(uri)
27
+ request['Authorization'] = "Bearer #{@config.api_key!}"
28
+ request['Accept'] = 'application/json'
29
+
30
+ response = http.request(request)
31
+ handle_status!(response)
32
+ JSON.parse(response.body)
33
+ rescue Truelist::AuthenticationError
34
+ raise
35
+ rescue StandardError => e
36
+ raise e if @config.raise_on_error
37
+
38
+ nil
39
+ end
40
+
41
+ private
42
+
43
+ def perform_request(email)
44
+ uri = URI("#{@config.base_url}/api/v1/verify_inline")
45
+ uri.query = URI.encode_www_form(email: email)
46
+ http = build_http(uri)
47
+
48
+ request = Net::HTTP::Post.new(uri)
49
+ request['Authorization'] = "Bearer #{@config.api_key!}"
50
+ request['Accept'] = 'application/json'
51
+
52
+ response = http.request(request)
53
+ handle_response(email, response)
54
+ rescue Truelist::AuthenticationError
55
+ raise
56
+ rescue StandardError => e
57
+ handle_error(email, e)
58
+ end
59
+
60
+ def build_http(uri)
61
+ http = Net::HTTP.new(uri.host, uri.port)
62
+ http.use_ssl = uri.scheme == 'https'
63
+ http.open_timeout = @config.timeout
64
+ http.read_timeout = @config.timeout
65
+ http
66
+ end
67
+
68
+ def handle_status!(response)
69
+ case response.code.to_i
70
+ when 200 then nil
71
+ when 401
72
+ raise Truelist::AuthenticationError, 'Invalid API key. Check your Truelist API key configuration.'
73
+ else
74
+ raise Truelist::ApiError, "API returned #{response.code}: #{response.body}"
75
+ end
76
+ end
77
+
78
+ def handle_response(email, response)
79
+ case response.code.to_i
80
+ when 200
81
+ parse_success(email, response.body)
82
+ when 401
83
+ raise Truelist::AuthenticationError, 'Invalid API key. Check your Truelist API key configuration.'
84
+ when 429
85
+ handle_error(email, Truelist::RateLimitError.new('Rate limit exceeded'))
86
+ else
87
+ handle_error(email, Truelist::ApiError.new("API returned #{response.code}: #{response.body}"))
88
+ end
89
+ end
90
+
91
+ def parse_success(email, body)
92
+ d = JSON.parse(body).dig('emails', 0) || {}
93
+ Result.new(
94
+ email: d['address'] || email, state: d['email_state'] || 'unknown',
95
+ sub_state: d['email_sub_state'], suggestion: d['did_you_mean'],
96
+ domain: d['domain'], canonical: d['canonical'], mx_record: d['mx_record'],
97
+ first_name: d['first_name'], last_name: d['last_name'], verified_at: d['verified_at']
98
+ )
99
+ rescue JSON::ParserError => e
100
+ handle_error(email, e)
101
+ end
102
+
103
+ def handle_error(email, error)
104
+ raise error if @config.raise_on_error
105
+
106
+ Result.new(email: email, state: 'unknown', error: true)
107
+ end
108
+
109
+ def cache_key(email)
110
+ "truelist:validation:#{email.downcase.strip}"
111
+ end
112
+
113
+ def read_cache(email)
114
+ return nil unless @config.cache_store
115
+
116
+ @config.cache_store.read(cache_key(email))
117
+ end
118
+
119
+ def write_cache(email, result)
120
+ return unless @config.cache_store
121
+
122
+ @config.cache_store.write(cache_key(email), result, expires_in: @config.cache_ttl)
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Truelist
4
+ class Configuration
5
+ attr_accessor :api_key, :base_url, :timeout, :raise_on_error,
6
+ :allow_risky, :cache_store, :cache_ttl
7
+
8
+ def initialize
9
+ @api_key = ENV.fetch('TRUELIST_API_KEY', nil)
10
+ @base_url = 'https://api.truelist.io'
11
+ @timeout = 10
12
+ @raise_on_error = false
13
+ @allow_risky = true
14
+ @cache_store = nil
15
+ @cache_ttl = 3600 # 1 hour in seconds
16
+ end
17
+
18
+ def api_key!
19
+ api_key || raise(Truelist::AuthenticationError,
20
+ 'Truelist API key is not configured. Set TRUELIST_API_KEY or use Truelist.configure.')
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Truelist
4
+ class Railtie < Rails::Railtie
5
+ initializer 'truelist.configure' do
6
+ Truelist.configure do |config|
7
+ config.api_key ||= ENV.fetch('TRUELIST_API_KEY', nil)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Truelist
4
+ class Result
5
+ attr_reader :email, :state, :sub_state, :suggestion, :domain, :canonical,
6
+ :mx_record, :first_name, :last_name, :verified_at, :error
7
+
8
+ def initialize(email:, state:, sub_state: nil, suggestion: nil, domain: nil, canonical: nil,
9
+ mx_record: nil, first_name: nil, last_name: nil, verified_at: nil, error: false)
10
+ @email = email
11
+ @state = state.to_s
12
+ @sub_state = sub_state&.to_s
13
+ @suggestion = suggestion
14
+ @domain = domain
15
+ @canonical = canonical
16
+ @mx_record = mx_record
17
+ @first_name = first_name
18
+ @last_name = last_name
19
+ @verified_at = verified_at
20
+ @error = error
21
+ end
22
+
23
+ def valid?
24
+ state == 'ok' || (state == 'accept_all' && Truelist.configuration.allow_risky)
25
+ end
26
+
27
+ def invalid?
28
+ state == 'email_invalid'
29
+ end
30
+
31
+ def accept_all?
32
+ state == 'accept_all'
33
+ end
34
+
35
+ def unknown?
36
+ state == 'unknown'
37
+ end
38
+
39
+ def disposable?
40
+ sub_state == 'is_disposable'
41
+ end
42
+
43
+ def role?
44
+ sub_state == 'is_role'
45
+ end
46
+
47
+ def error?
48
+ @error
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ class DeliverableValidator < ActiveModel::EachValidator
4
+ def validate_each(record, attribute, value)
5
+ return if value.blank?
6
+
7
+ result = Truelist::Client.new.validate(value)
8
+
9
+ allow_risky = if options.key?(:allow_risky)
10
+ options[:allow_risky]
11
+ else
12
+ Truelist.configuration.allow_risky
13
+ end
14
+
15
+ # Fail open for transient errors (timeouts, 500s) so forms still work when API is down
16
+ return if result.error?
17
+
18
+ deliverable = result.state == 'ok' || (result.state == 'accept_all' && allow_risky) || result.unknown?
19
+
20
+ return if deliverable
21
+
22
+ message = options[:message] || :invalid_email
23
+ record.errors.add(attribute, message)
24
+ end
25
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Truelist
4
+ VERSION = '0.1.0'
5
+ end
data/lib/truelist.rb ADDED
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'truelist/version'
4
+ require_relative 'truelist/configuration'
5
+ require_relative 'truelist/result'
6
+ require_relative 'truelist/client'
7
+
8
+ module Truelist
9
+ class Error < StandardError; end
10
+ class ApiError < Error; end
11
+ class AuthenticationError < Error; end
12
+ class RateLimitError < Error; end
13
+
14
+ class << self
15
+ def configuration
16
+ @configuration ||= Configuration.new
17
+ end
18
+
19
+ def configure
20
+ yield(configuration)
21
+ end
22
+
23
+ def reset_configuration!
24
+ @configuration = Configuration.new
25
+ end
26
+
27
+ def validate(email)
28
+ Client.new.validate(email)
29
+ end
30
+ end
31
+ end
32
+
33
+ require_relative 'truelist/railtie' if defined?(Rails::Railtie)
34
+ require_relative 'truelist/validators/deliverable_validator'
metadata ADDED
@@ -0,0 +1,87 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: truelist-rails
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Truelist
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2026-04-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activemodel
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '7.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '7.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activesupport
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '7.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '7.0'
41
+ description: Rails integration for the Truelist.io email validation API. Validate
42
+ email deliverability with a simple ActiveModel validator.
43
+ email:
44
+ - support@truelist.io
45
+ executables: []
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - LICENSE
50
+ - README.md
51
+ - lib/generators/truelist/install_generator.rb
52
+ - lib/generators/truelist/templates/initializer.rb
53
+ - lib/truelist.rb
54
+ - lib/truelist/client.rb
55
+ - lib/truelist/configuration.rb
56
+ - lib/truelist/railtie.rb
57
+ - lib/truelist/result.rb
58
+ - lib/truelist/validators/deliverable_validator.rb
59
+ - lib/truelist/version.rb
60
+ homepage: https://github.com/Truelist-io-Email-Validation/truelist-rails
61
+ licenses:
62
+ - MIT
63
+ metadata:
64
+ homepage_uri: https://github.com/Truelist-io-Email-Validation/truelist-rails
65
+ source_code_uri: https://github.com/Truelist-io-Email-Validation/truelist-rails
66
+ changelog_uri: https://github.com/Truelist-io-Email-Validation/truelist-rails/blob/main/CHANGELOG.md
67
+ rubygems_mfa_required: 'true'
68
+ post_install_message:
69
+ rdoc_options: []
70
+ require_paths:
71
+ - lib
72
+ required_ruby_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '3.0'
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ requirements: []
83
+ rubygems_version: 3.4.10
84
+ signing_key:
85
+ specification_version: 4
86
+ summary: Email validation for Rails, powered by Truelist.io
87
+ test_files: []