valid_email_checker 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 +7 -0
- data/CHANGELOG.md +24 -0
- data/Cargo.lock +2940 -0
- data/Cargo.toml +22 -0
- data/LICENSE.txt +661 -0
- data/NOTICE.md +56 -0
- data/README.md +316 -0
- data/exe/valid_email_checker +148 -0
- data/ext/valid_email_checker/Cargo.toml +27 -0
- data/ext/valid_email_checker/extconf.rb +26 -0
- data/ext/valid_email_checker/src/lib.rs +371 -0
- data/ext/valid_email_checker/src/nogvl.rs +64 -0
- data/ext/valid_email_checker/vendor/UPSTREAM.json +9 -0
- data/ext/valid_email_checker/vendor/check-if-email-exists/Cargo.toml +52 -0
- data/ext/valid_email_checker/vendor/check-if-email-exists/LICENSE.AGPL +661 -0
- data/ext/valid_email_checker/vendor/check-if-email-exists/LICENSE.md +11 -0
- data/ext/valid_email_checker/vendor/check-if-email-exists/README.md +175 -0
- data/ext/valid_email_checker/vendor/check-if-email-exists/src/haveibeenpwned.rs +70 -0
- data/ext/valid_email_checker/vendor/check-if-email-exists/src/lib.rs +281 -0
- data/ext/valid_email_checker/vendor/check-if-email-exists/src/misc/b2c.txt +96640 -0
- data/ext/valid_email_checker/vendor/check-if-email-exists/src/misc/gravatar.rs +60 -0
- data/ext/valid_email_checker/vendor/check-if-email-exists/src/misc/mod.rs +124 -0
- data/ext/valid_email_checker/vendor/check-if-email-exists/src/misc/roles.txt +944 -0
- data/ext/valid_email_checker/vendor/check-if-email-exists/src/mx/mod.rs +165 -0
- data/ext/valid_email_checker/vendor/check-if-email-exists/src/rules.json +28 -0
- data/ext/valid_email_checker/vendor/check-if-email-exists/src/rules.rs +105 -0
- data/ext/valid_email_checker/vendor/check-if-email-exists/src/smtp/connect.rs +396 -0
- data/ext/valid_email_checker/vendor/check-if-email-exists/src/smtp/error.rs +144 -0
- data/ext/valid_email_checker/vendor/check-if-email-exists/src/smtp/gmail.rs +99 -0
- data/ext/valid_email_checker/vendor/check-if-email-exists/src/smtp/headless.rs +82 -0
- data/ext/valid_email_checker/vendor/check-if-email-exists/src/smtp/http_api.rs +27 -0
- data/ext/valid_email_checker/vendor/check-if-email-exists/src/smtp/mod.rs +234 -0
- data/ext/valid_email_checker/vendor/check-if-email-exists/src/smtp/outlook/headless.rs +181 -0
- data/ext/valid_email_checker/vendor/check-if-email-exists/src/smtp/outlook/microsoft365.rs +109 -0
- data/ext/valid_email_checker/vendor/check-if-email-exists/src/smtp/outlook/mod.rs +2 -0
- data/ext/valid_email_checker/vendor/check-if-email-exists/src/smtp/parser.rs +291 -0
- data/ext/valid_email_checker/vendor/check-if-email-exists/src/smtp/verif_method.rs +531 -0
- data/ext/valid_email_checker/vendor/check-if-email-exists/src/smtp/yahoo/api.rs +174 -0
- data/ext/valid_email_checker/vendor/check-if-email-exists/src/smtp/yahoo/headless.rs +188 -0
- data/ext/valid_email_checker/vendor/check-if-email-exists/src/smtp/yahoo/mod.rs +62 -0
- data/ext/valid_email_checker/vendor/check-if-email-exists/src/syntax/mod.rs +199 -0
- data/ext/valid_email_checker/vendor/check-if-email-exists/src/syntax/normalize.rs +70 -0
- data/ext/valid_email_checker/vendor/check-if-email-exists/src/util/input_output.rs +353 -0
- data/ext/valid_email_checker/vendor/check-if-email-exists/src/util/mod.rs +20 -0
- data/ext/valid_email_checker/vendor/check-if-email-exists/src/util/sentry.rs +173 -0
- data/ext/valid_email_checker/vendor/check-if-email-exists/src/util/ser_with_display.rs +28 -0
- data/lib/valid_email_checker/configuration.rb +216 -0
- data/lib/valid_email_checker/errors.rb +32 -0
- data/lib/valid_email_checker/result.rb +241 -0
- data/lib/valid_email_checker/syntax.rb +72 -0
- data/lib/valid_email_checker/version.rb +5 -0
- data/lib/valid_email_checker.rb +217 -0
- metadata +118 -0
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "json"
|
|
4
|
+
|
|
5
|
+
require_relative "valid_email_checker/version"
|
|
6
|
+
require_relative "valid_email_checker/errors"
|
|
7
|
+
require_relative "valid_email_checker/configuration"
|
|
8
|
+
require_relative "valid_email_checker/syntax"
|
|
9
|
+
require_relative "valid_email_checker/result"
|
|
10
|
+
|
|
11
|
+
# The compiled extension. rake-compiler installs a per-version copy when
|
|
12
|
+
# several Ruby ABIs share a checkout, so prefer that when it is present.
|
|
13
|
+
begin
|
|
14
|
+
ruby_abi = RUBY_VERSION[/\d+\.\d+/]
|
|
15
|
+
require_relative "valid_email_checker/#{ruby_abi}/valid_email_checker"
|
|
16
|
+
rescue LoadError
|
|
17
|
+
require_relative "valid_email_checker/valid_email_checker"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Check whether an email address really exists, without sending mail.
|
|
21
|
+
#
|
|
22
|
+
# This gem embeds the Rust crate
|
|
23
|
+
# {https://github.com/reacherhq/check-if-email-exists check-if-email-exists}
|
|
24
|
+
# and calls it in-process. A full check validates the syntax, resolves the
|
|
25
|
+
# domain's MX records, opens an SMTP conversation with the mail exchanger and
|
|
26
|
+
# asks about the recipient without ever completing a message, then reports
|
|
27
|
+
# whether the address is disposable, role-based or catch-all.
|
|
28
|
+
#
|
|
29
|
+
# ValidEmailChecker.check("someone@gmail.com").safe? # => true
|
|
30
|
+
#
|
|
31
|
+
# == A note on what "exists" can mean
|
|
32
|
+
#
|
|
33
|
+
# SMTP verification is a best-effort signal, not a guarantee. Results come back
|
|
34
|
+
# as +:unknown+ more often than people expect, for reasons that have nothing to
|
|
35
|
+
# do with the address:
|
|
36
|
+
#
|
|
37
|
+
# * Most residential and cloud networks block outbound port 25. Without a
|
|
38
|
+
# SOCKS5 +proxy+, or a host that permits port 25, expect +:unknown+.
|
|
39
|
+
# * Mail exchangers rate-limit, greylist and blacklist aggressively. A server
|
|
40
|
+
# you are unknown to may simply refuse to answer.
|
|
41
|
+
# * Catch-all domains accept every recipient, so an individual address there
|
|
42
|
+
# can never be confirmed. Those come back +:risky+.
|
|
43
|
+
#
|
|
44
|
+
# Set +from_email+ and +hello_name+ to a domain you actually control, with
|
|
45
|
+
# matching forward and reverse DNS, for markedly better results.
|
|
46
|
+
module ValidEmailChecker
|
|
47
|
+
# Whether this platform's network stack deadlocks when a process verifies an
|
|
48
|
+
# address after forking from a parent that already had.
|
|
49
|
+
#
|
|
50
|
+
# True on macOS, whose Network.framework is not fork-safe. See
|
|
51
|
+
# {ForkAfterVerificationError} and the README's "Forking servers" section.
|
|
52
|
+
FORK_UNSAFE_NETWORK_STACK = RUBY_PLATFORM.include?("darwin")
|
|
53
|
+
|
|
54
|
+
class << self
|
|
55
|
+
# Process-wide defaults. See {Configuration} for every setting.
|
|
56
|
+
#
|
|
57
|
+
# @return [ValidEmailChecker::Configuration]
|
|
58
|
+
def configuration
|
|
59
|
+
@configuration ||= Configuration.new
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Set process-wide defaults.
|
|
63
|
+
#
|
|
64
|
+
# ValidEmailChecker.configure do |config|
|
|
65
|
+
# config.from_email = "verify@example.com"
|
|
66
|
+
# config.hello_name = "example.com"
|
|
67
|
+
# config.timeout = 15
|
|
68
|
+
# end
|
|
69
|
+
#
|
|
70
|
+
# @yieldparam config [ValidEmailChecker::Configuration]
|
|
71
|
+
# @return [ValidEmailChecker::Configuration]
|
|
72
|
+
def configure
|
|
73
|
+
yield configuration if block_given?
|
|
74
|
+
configuration.validate!
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Restore the default configuration. Mainly useful in tests.
|
|
78
|
+
#
|
|
79
|
+
# @return [ValidEmailChecker::Configuration]
|
|
80
|
+
def reset_configuration!
|
|
81
|
+
@configuration = Configuration.new
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Verify one address.
|
|
85
|
+
#
|
|
86
|
+
# Performs network I/O and takes seconds. The GVL is released for the
|
|
87
|
+
# duration, so other Ruby threads keep running.
|
|
88
|
+
#
|
|
89
|
+
# @param email [String] the address to check
|
|
90
|
+
# @param options [Hash] per-call overrides; any {Configuration} setting
|
|
91
|
+
# @return [ValidEmailChecker::Result]
|
|
92
|
+
# @raise [ArgumentError] if +email+ is not a non-empty String
|
|
93
|
+
# @raise [ValidEmailChecker::ConfigurationError] if the options are unusable
|
|
94
|
+
def check(email, **options)
|
|
95
|
+
address = coerce_email(email)
|
|
96
|
+
payload = configuration.merge(options).to_native_payload
|
|
97
|
+
check_fork_safety!
|
|
98
|
+
|
|
99
|
+
Result.from_json(Native.check(address, JSON.generate(payload)))
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Verify several addresses, several at a time.
|
|
103
|
+
#
|
|
104
|
+
# This is the reason to embed the crate rather than shell out to it: the
|
|
105
|
+
# whole batch runs on one async runtime under a single GVL release, so
|
|
106
|
+
# +concurrency+ verifications are in flight at once. Results come back in
|
|
107
|
+
# the same order as +emails+.
|
|
108
|
+
#
|
|
109
|
+
# results = ValidEmailChecker.check_many(addresses, concurrency: 20)
|
|
110
|
+
# results.select(&:safe?).map(&:email)
|
|
111
|
+
#
|
|
112
|
+
# Be careful raising +concurrency+ when the addresses share a domain: you
|
|
113
|
+
# are opening that many SMTP connections to one mail exchanger, which is a
|
|
114
|
+
# good way to get rate-limited or blacklisted.
|
|
115
|
+
#
|
|
116
|
+
# @param emails [Array<String>] the addresses to check
|
|
117
|
+
# @param options [Hash] per-call overrides; any {Configuration} setting,
|
|
118
|
+
# including +concurrency+
|
|
119
|
+
# @return [Array<ValidEmailChecker::Result>] in the order given
|
|
120
|
+
def check_many(emails, **options)
|
|
121
|
+
list = Array(emails).map { |email| coerce_email(email) }
|
|
122
|
+
return [] if list.empty?
|
|
123
|
+
|
|
124
|
+
config = configuration.merge(options)
|
|
125
|
+
payload = config.to_native_payload
|
|
126
|
+
concurrency = Integer(config.concurrency)
|
|
127
|
+
|
|
128
|
+
if concurrency < 1
|
|
129
|
+
raise ConfigurationError, "concurrency must be at least 1, got #{config.concurrency.inspect}"
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
check_fork_safety!
|
|
133
|
+
|
|
134
|
+
json = Native.check_many(list, JSON.generate(payload), concurrency)
|
|
135
|
+
JSON.parse(json, symbolize_names: true).map { |data| Result.new(data) }
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# Parse an address without touching the network.
|
|
139
|
+
#
|
|
140
|
+
# Instant and side-effect free, so it is safe to call on user input inline,
|
|
141
|
+
# including in a request cycle or a model validation.
|
|
142
|
+
#
|
|
143
|
+
# ValidEmailChecker.syntax("someone@gmail.co").suggestion
|
|
144
|
+
# # => "someone@gmail.com"
|
|
145
|
+
#
|
|
146
|
+
# Note that a suggestion is only offered for an address that parses.
|
|
147
|
+
# Well-known typo domains such as "gmial.com" are on upstream's blocklist
|
|
148
|
+
# and come back as simply invalid, with no domain and no suggestion.
|
|
149
|
+
#
|
|
150
|
+
# @param email [String]
|
|
151
|
+
# @return [ValidEmailChecker::Syntax]
|
|
152
|
+
def syntax(email)
|
|
153
|
+
Syntax.new(JSON.parse(Native.check_syntax(coerce_email(email)), symbolize_names: true))
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
# Whether an address is well-formed. No network access.
|
|
157
|
+
#
|
|
158
|
+
# @param email [String]
|
|
159
|
+
# @return [Boolean]
|
|
160
|
+
def syntax_valid?(email)
|
|
161
|
+
syntax(email).valid?
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# Which version of the embedded crate this gem was built against.
|
|
165
|
+
#
|
|
166
|
+
# @return [Hash] with +:name+, +:version+, +:commit+, +:repository+ and
|
|
167
|
+
# +:license+ keys
|
|
168
|
+
def upstream
|
|
169
|
+
@upstream ||= JSON.parse(Native.upstream, symbolize_names: true).freeze
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
private
|
|
173
|
+
|
|
174
|
+
# Apple's Network.framework is not fork-safe: once a process has resolved
|
|
175
|
+
# and connected, a child that inherits that state deadlocks inside the
|
|
176
|
+
# framework on its own first connection, ignoring our timeout entirely.
|
|
177
|
+
#
|
|
178
|
+
# We cannot fix the inherited state, so we refuse the call instead of
|
|
179
|
+
# hanging. The check is limited to platforms where the deadlock is
|
|
180
|
+
# demonstrable; see {FORK_UNSAFE_NETWORK_STACK}. Set
|
|
181
|
+
# VALID_EMAIL_CHECKER_ALLOW_FORK=1 to bypass it and take the risk.
|
|
182
|
+
def check_fork_safety!
|
|
183
|
+
pid = Process.pid
|
|
184
|
+
|
|
185
|
+
if FORK_UNSAFE_NETWORK_STACK &&
|
|
186
|
+
@verified_in_pid &&
|
|
187
|
+
@verified_in_pid != pid &&
|
|
188
|
+
ENV["VALID_EMAIL_CHECKER_ALLOW_FORK"] != "1"
|
|
189
|
+
raise ForkAfterVerificationError, <<~MSG.strip
|
|
190
|
+
Refusing to verify in process #{pid}: process #{@verified_in_pid} already
|
|
191
|
+
verified an address before this one forked from it.
|
|
192
|
+
|
|
193
|
+
macOS's Network.framework is not fork-safe, and continuing would deadlock
|
|
194
|
+
here indefinitely rather than time out.
|
|
195
|
+
|
|
196
|
+
Verify only in child processes: load this gem at boot if you like, but do
|
|
197
|
+
not call check/check_many in a parent that will later fork (for example,
|
|
198
|
+
during Puma's or Unicorn's preload phase). Set
|
|
199
|
+
VALID_EMAIL_CHECKER_ALLOW_FORK=1 to bypass this check.
|
|
200
|
+
MSG
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
@verified_in_pid = pid
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
def coerce_email(email)
|
|
207
|
+
unless email.is_a?(String)
|
|
208
|
+
raise ArgumentError, "expected an email address as a String, got #{email.class}"
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
stripped = email.strip
|
|
212
|
+
raise ArgumentError, "expected an email address, got an empty String" if stripped.empty?
|
|
213
|
+
|
|
214
|
+
stripped
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: valid_email_checker
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- J. Callahan
|
|
8
|
+
bindir: exe
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: rb_sys
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '0.9'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '0.9'
|
|
26
|
+
description: |
|
|
27
|
+
valid_email_checker embeds the Rust crate check-if-email-exists and exposes
|
|
28
|
+
it to Ruby as a native extension. It validates syntax, looks up MX records,
|
|
29
|
+
holds an SMTP conversation with the recipient's mail exchanger, and reports
|
|
30
|
+
disposable, role-based and catch-all addresses -- all in-process, with no
|
|
31
|
+
HTTP service to run and no mail actually sent.
|
|
32
|
+
email:
|
|
33
|
+
- jcallahan@acm.org
|
|
34
|
+
executables:
|
|
35
|
+
- valid_email_checker
|
|
36
|
+
extensions:
|
|
37
|
+
- ext/valid_email_checker/extconf.rb
|
|
38
|
+
extra_rdoc_files: []
|
|
39
|
+
files:
|
|
40
|
+
- CHANGELOG.md
|
|
41
|
+
- Cargo.lock
|
|
42
|
+
- Cargo.toml
|
|
43
|
+
- LICENSE.txt
|
|
44
|
+
- NOTICE.md
|
|
45
|
+
- README.md
|
|
46
|
+
- exe/valid_email_checker
|
|
47
|
+
- ext/valid_email_checker/Cargo.toml
|
|
48
|
+
- ext/valid_email_checker/extconf.rb
|
|
49
|
+
- ext/valid_email_checker/src/lib.rs
|
|
50
|
+
- ext/valid_email_checker/src/nogvl.rs
|
|
51
|
+
- ext/valid_email_checker/vendor/UPSTREAM.json
|
|
52
|
+
- ext/valid_email_checker/vendor/check-if-email-exists/Cargo.toml
|
|
53
|
+
- ext/valid_email_checker/vendor/check-if-email-exists/LICENSE.AGPL
|
|
54
|
+
- ext/valid_email_checker/vendor/check-if-email-exists/LICENSE.md
|
|
55
|
+
- ext/valid_email_checker/vendor/check-if-email-exists/README.md
|
|
56
|
+
- ext/valid_email_checker/vendor/check-if-email-exists/src/haveibeenpwned.rs
|
|
57
|
+
- ext/valid_email_checker/vendor/check-if-email-exists/src/lib.rs
|
|
58
|
+
- ext/valid_email_checker/vendor/check-if-email-exists/src/misc/b2c.txt
|
|
59
|
+
- ext/valid_email_checker/vendor/check-if-email-exists/src/misc/gravatar.rs
|
|
60
|
+
- ext/valid_email_checker/vendor/check-if-email-exists/src/misc/mod.rs
|
|
61
|
+
- ext/valid_email_checker/vendor/check-if-email-exists/src/misc/roles.txt
|
|
62
|
+
- ext/valid_email_checker/vendor/check-if-email-exists/src/mx/mod.rs
|
|
63
|
+
- ext/valid_email_checker/vendor/check-if-email-exists/src/rules.json
|
|
64
|
+
- ext/valid_email_checker/vendor/check-if-email-exists/src/rules.rs
|
|
65
|
+
- ext/valid_email_checker/vendor/check-if-email-exists/src/smtp/connect.rs
|
|
66
|
+
- ext/valid_email_checker/vendor/check-if-email-exists/src/smtp/error.rs
|
|
67
|
+
- ext/valid_email_checker/vendor/check-if-email-exists/src/smtp/gmail.rs
|
|
68
|
+
- ext/valid_email_checker/vendor/check-if-email-exists/src/smtp/headless.rs
|
|
69
|
+
- ext/valid_email_checker/vendor/check-if-email-exists/src/smtp/http_api.rs
|
|
70
|
+
- ext/valid_email_checker/vendor/check-if-email-exists/src/smtp/mod.rs
|
|
71
|
+
- ext/valid_email_checker/vendor/check-if-email-exists/src/smtp/outlook/headless.rs
|
|
72
|
+
- ext/valid_email_checker/vendor/check-if-email-exists/src/smtp/outlook/microsoft365.rs
|
|
73
|
+
- ext/valid_email_checker/vendor/check-if-email-exists/src/smtp/outlook/mod.rs
|
|
74
|
+
- ext/valid_email_checker/vendor/check-if-email-exists/src/smtp/parser.rs
|
|
75
|
+
- ext/valid_email_checker/vendor/check-if-email-exists/src/smtp/verif_method.rs
|
|
76
|
+
- ext/valid_email_checker/vendor/check-if-email-exists/src/smtp/yahoo/api.rs
|
|
77
|
+
- ext/valid_email_checker/vendor/check-if-email-exists/src/smtp/yahoo/headless.rs
|
|
78
|
+
- ext/valid_email_checker/vendor/check-if-email-exists/src/smtp/yahoo/mod.rs
|
|
79
|
+
- ext/valid_email_checker/vendor/check-if-email-exists/src/syntax/mod.rs
|
|
80
|
+
- ext/valid_email_checker/vendor/check-if-email-exists/src/syntax/normalize.rs
|
|
81
|
+
- ext/valid_email_checker/vendor/check-if-email-exists/src/util/input_output.rs
|
|
82
|
+
- ext/valid_email_checker/vendor/check-if-email-exists/src/util/mod.rs
|
|
83
|
+
- ext/valid_email_checker/vendor/check-if-email-exists/src/util/sentry.rs
|
|
84
|
+
- ext/valid_email_checker/vendor/check-if-email-exists/src/util/ser_with_display.rs
|
|
85
|
+
- lib/valid_email_checker.rb
|
|
86
|
+
- lib/valid_email_checker/configuration.rb
|
|
87
|
+
- lib/valid_email_checker/errors.rb
|
|
88
|
+
- lib/valid_email_checker/result.rb
|
|
89
|
+
- lib/valid_email_checker/syntax.rb
|
|
90
|
+
- lib/valid_email_checker/version.rb
|
|
91
|
+
homepage: https://github.com/johncallahan/valid_email_checker
|
|
92
|
+
licenses:
|
|
93
|
+
- AGPL-3.0-only
|
|
94
|
+
metadata:
|
|
95
|
+
homepage_uri: https://github.com/johncallahan/valid_email_checker
|
|
96
|
+
source_code_uri: https://github.com/johncallahan/valid_email_checker
|
|
97
|
+
changelog_uri: https://github.com/johncallahan/valid_email_checker/blob/main/CHANGELOG.md
|
|
98
|
+
bug_tracker_uri: https://github.com/johncallahan/valid_email_checker/issues
|
|
99
|
+
upstream_project_uri: https://github.com/reacherhq/check-if-email-exists
|
|
100
|
+
rubygems_mfa_required: 'true'
|
|
101
|
+
rdoc_options: []
|
|
102
|
+
require_paths:
|
|
103
|
+
- lib
|
|
104
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
105
|
+
requirements:
|
|
106
|
+
- - ">="
|
|
107
|
+
- !ruby/object:Gem::Version
|
|
108
|
+
version: 3.1.0
|
|
109
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
110
|
+
requirements:
|
|
111
|
+
- - ">="
|
|
112
|
+
- !ruby/object:Gem::Version
|
|
113
|
+
version: 3.3.11
|
|
114
|
+
requirements: []
|
|
115
|
+
rubygems_version: 3.6.9
|
|
116
|
+
specification_version: 4
|
|
117
|
+
summary: Check whether an email address really exists, without sending mail.
|
|
118
|
+
test_files: []
|