truemail 2.2.2 → 2.3.3
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 +4 -4
- data/.codeclimate.yml +1 -1
- data/.reek.yml +8 -0
- data/.rubocop.yml +42 -0
- data/CHANGELOG.md +68 -0
- data/Gemfile.lock +55 -42
- data/LICENSE.txt +1 -1
- data/README.md +49 -20
- data/bin/console +3 -10
- data/{.circleci/config.yml → circle.yml} +26 -3
- data/lib/truemail.rb +1 -1
- data/lib/truemail/audit/base.rb +0 -1
- data/lib/truemail/audit/dns.rb +1 -1
- data/lib/truemail/audit/ip.rb +1 -1
- data/lib/truemail/audit/ptr.rb +4 -3
- data/lib/truemail/auditor.rb +1 -1
- data/lib/truemail/configuration.rb +38 -30
- data/lib/truemail/core.rb +11 -15
- data/lib/truemail/dns/punycode_representer.rb +16 -0
- data/lib/truemail/dns/resolver.rb +17 -0
- data/lib/truemail/dns/worker.rb +52 -0
- data/lib/truemail/log/serializer/auditor_json.rb +1 -1
- data/lib/truemail/log/serializer/base.rb +2 -1
- data/lib/truemail/log/serializer/validator_base.rb +1 -1
- data/lib/truemail/log/serializer/validator_text.rb +2 -2
- data/lib/truemail/logger.rb +1 -1
- data/lib/truemail/validate/mx.rb +7 -9
- data/lib/truemail/validate/smtp/request.rb +11 -7
- data/lib/truemail/validate/smtp/response.rb +1 -1
- data/lib/truemail/validator.rb +2 -2
- data/lib/truemail/version.rb +1 -1
- data/lib/truemail/wrapper.rb +3 -3
- data/truemail.gemspec +11 -9
- metadata +69 -26
@@ -20,8 +20,8 @@ module Truemail
|
|
20
20
|
enumerable_object.inject([]) do |formatted_data, (key, value)|
|
21
21
|
data =
|
22
22
|
case
|
23
|
-
when value.is_a?(Hash) then "\n#{printer(value)}"
|
24
|
-
when value.is_a?(Array) then value.join(', ')
|
23
|
+
when value.is_a?(::Hash) then "\n#{printer(value)}"
|
24
|
+
when value.is_a?(::Array) then value.join(', ')
|
25
25
|
else value
|
26
26
|
end
|
27
27
|
formatted_data << "#{key.to_s.tr('_', ' ')}: #{data}".chomp << "\n"
|
data/lib/truemail/logger.rb
CHANGED
@@ -23,7 +23,7 @@ module Truemail
|
|
23
23
|
def init_log_file
|
24
24
|
output_file = Pathname(file)
|
25
25
|
return output_file if output_file.exist?
|
26
|
-
output_file.parent.mkpath && FileUtils.touch(output_file)
|
26
|
+
output_file.parent.mkpath && ::FileUtils.touch(output_file)
|
27
27
|
output_file
|
28
28
|
end
|
29
29
|
|
data/lib/truemail/validate/mx.rb
CHANGED
@@ -3,8 +3,6 @@
|
|
3
3
|
module Truemail
|
4
4
|
module Validate
|
5
5
|
class Mx < Truemail::Validate::Base
|
6
|
-
require 'resolv'
|
7
|
-
|
8
6
|
ERROR = 'target host(s) not found'
|
9
7
|
NULL_MX_RECORD = 'null_mx_record'
|
10
8
|
|
@@ -43,11 +41,11 @@ module Truemail
|
|
43
41
|
end
|
44
42
|
|
45
43
|
def mx_records(hostname)
|
46
|
-
domain_mx_records =
|
44
|
+
domain_mx_records = Truemail::Dns::Resolver.mx_records(hostname, configuration: configuration)
|
47
45
|
return [Truemail::Validate::Mx::NULL_MX_RECORD] if null_mx?(domain_mx_records)
|
48
|
-
domain_mx_records.sort_by(&:preference).
|
49
|
-
|
50
|
-
end
|
46
|
+
domain_mx_records.sort_by(&:preference).flat_map do |mx_record|
|
47
|
+
Truemail::Dns::Resolver.a_records(mx_record.exchange.to_s, configuration: configuration)
|
48
|
+
end
|
51
49
|
end
|
52
50
|
|
53
51
|
def mail_servers_found?
|
@@ -64,15 +62,15 @@ module Truemail
|
|
64
62
|
end
|
65
63
|
|
66
64
|
def a_record(hostname)
|
67
|
-
|
65
|
+
Truemail::Dns::Resolver.a_record(hostname, configuration: configuration)
|
68
66
|
end
|
69
67
|
|
70
68
|
def hosts_from_cname_records?
|
71
|
-
cname_records =
|
69
|
+
cname_records = Truemail::Dns::Resolver.cname_records(domain, configuration: configuration)
|
72
70
|
return if cname_records.empty?
|
73
71
|
cname_records.each do |cname_record|
|
74
72
|
host = a_record(cname_record.name.to_s)
|
75
|
-
hostname =
|
73
|
+
hostname = Truemail::Dns::Resolver.dns_lookup(host, configuration: configuration)
|
76
74
|
found_hosts = mx_records(hostname)
|
77
75
|
fetch_target_hosts(found_hosts.empty? ? [host] : found_hosts)
|
78
76
|
end
|
@@ -13,20 +13,24 @@ module Truemail
|
|
13
13
|
|
14
14
|
attr_reader :configuration, :host, :email, :response
|
15
15
|
|
16
|
-
def initialize(configuration:, host:, email:, attempts: nil)
|
16
|
+
def initialize(configuration:, host:, email:, attempts: nil, port_open_status: proc { true })
|
17
17
|
@configuration = Truemail::Validate::Smtp::Request::Configuration.new(configuration)
|
18
18
|
@response = Truemail::Validate::Smtp::Response.new
|
19
19
|
@host = host
|
20
20
|
@email = email
|
21
21
|
@attempts = attempts
|
22
|
+
@port_open_status = port_open_status
|
22
23
|
end
|
23
24
|
|
24
25
|
def check_port
|
25
|
-
|
26
|
-
|
27
|
-
|
26
|
+
response.port_opened = ::Socket.tcp(
|
27
|
+
host,
|
28
|
+
Truemail::Validate::Smtp::Request::SMTP_PORT,
|
29
|
+
connect_timeout: configuration.connection_timeout,
|
30
|
+
&port_open_status
|
31
|
+
)
|
28
32
|
rescue => error
|
29
|
-
retry if attempts_exist? && error.is_a?(
|
33
|
+
retry if attempts_exist? && error.is_a?(::Errno::ETIMEDOUT)
|
30
34
|
response.port_opened = false
|
31
35
|
end
|
32
36
|
|
@@ -53,7 +57,7 @@ module Truemail
|
|
53
57
|
end
|
54
58
|
end
|
55
59
|
|
56
|
-
attr_reader :attempts
|
60
|
+
attr_reader :attempts, :port_open_status
|
57
61
|
|
58
62
|
def attempts_exist?
|
59
63
|
return false unless attempts
|
@@ -61,7 +65,7 @@ module Truemail
|
|
61
65
|
end
|
62
66
|
|
63
67
|
def session
|
64
|
-
Net::SMTP.new(host, Truemail::Validate::Smtp::Request::SMTP_PORT).tap do |settings|
|
68
|
+
::Net::SMTP.new(host, Truemail::Validate::Smtp::Request::SMTP_PORT).tap do |settings|
|
65
69
|
settings.open_timeout = configuration.connection_timeout
|
66
70
|
settings.read_timeout = configuration.response_timeout
|
67
71
|
end
|
@@ -5,7 +5,7 @@ module Truemail
|
|
5
5
|
class Smtp
|
6
6
|
RESPONSE_ATTRS = %i[port_opened connection helo mailfrom rcptto errors].freeze
|
7
7
|
|
8
|
-
Response = Struct.new(*RESPONSE_ATTRS, keyword_init: true) do
|
8
|
+
Response = ::Struct.new(*RESPONSE_ATTRS, keyword_init: true) do
|
9
9
|
def initialize(errors: {}, **args)
|
10
10
|
super
|
11
11
|
end
|
data/lib/truemail/validator.rb
CHANGED
@@ -5,13 +5,13 @@ module Truemail
|
|
5
5
|
RESULT_ATTRS = %i[success email domain mail_servers errors smtp_debug configuration].freeze
|
6
6
|
VALIDATION_TYPES = %i[regex mx smtp].freeze
|
7
7
|
|
8
|
-
Result = Struct.new(*RESULT_ATTRS, keyword_init: true) do
|
8
|
+
Result = ::Struct.new(*RESULT_ATTRS, keyword_init: true) do
|
9
9
|
def initialize(mail_servers: [], errors: {}, **args)
|
10
10
|
super
|
11
11
|
end
|
12
12
|
|
13
13
|
def punycode_email
|
14
|
-
@punycode_email ||= Truemail::PunycodeRepresenter.call(email)
|
14
|
+
@punycode_email ||= Truemail::Dns::PunycodeRepresenter.call(email)
|
15
15
|
end
|
16
16
|
alias_method :valid?, :success
|
17
17
|
end
|
data/lib/truemail/version.rb
CHANGED
data/lib/truemail/wrapper.rb
CHANGED
@@ -15,10 +15,10 @@ module Truemail
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def call(&block)
|
18
|
-
Timeout.timeout(timeout, &block)
|
19
|
-
rescue Resolv::ResolvError, IPAddr::InvalidAddressError
|
18
|
+
::Timeout.timeout(timeout, &block)
|
19
|
+
rescue ::Resolv::ResolvError, ::IPAddr::InvalidAddressError
|
20
20
|
false
|
21
|
-
rescue Timeout::Error
|
21
|
+
rescue ::Timeout::Error
|
22
22
|
retry unless (self.attempts -= 1).zero?
|
23
23
|
false
|
24
24
|
end
|
data/truemail.gemspec
CHANGED
@@ -31,21 +31,23 @@ Gem::Specification.new do |spec|
|
|
31
31
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
32
32
|
spec.require_paths = ['lib']
|
33
33
|
|
34
|
-
spec.add_runtime_dependency 'simpleidn', '~> 0.
|
34
|
+
spec.add_runtime_dependency 'simpleidn', '~> 0.2.1'
|
35
35
|
|
36
36
|
spec.add_development_dependency 'bundler', '~> 1.16'
|
37
|
-
spec.add_development_dependency 'bundler-audit', '~> 0.
|
38
|
-
spec.add_development_dependency '
|
39
|
-
spec.add_development_dependency '
|
37
|
+
spec.add_development_dependency 'bundler-audit', '~> 0.8.0'
|
38
|
+
spec.add_development_dependency 'dns_mock', '~> 1.2', '>= 1.2.1'
|
39
|
+
spec.add_development_dependency 'faker', '~> 2.17'
|
40
|
+
spec.add_development_dependency 'fasterer', '~> 0.9.0'
|
40
41
|
spec.add_development_dependency 'json_matchers', '~> 0.11.1'
|
41
42
|
spec.add_development_dependency 'overcommit', '~> 0.57.0'
|
42
43
|
spec.add_development_dependency 'pry-byebug', '~> 3.9'
|
43
44
|
spec.add_development_dependency 'rake', '~> 13.0', '>= 13.0.3'
|
44
|
-
spec.add_development_dependency 'reek', '~> 6.0', '>= 6.0.
|
45
|
+
spec.add_development_dependency 'reek', '~> 6.0', '>= 6.0.3'
|
45
46
|
spec.add_development_dependency 'rspec', '~> 3.10'
|
46
|
-
spec.add_development_dependency 'rubocop', '~> 1.
|
47
|
-
spec.add_development_dependency 'rubocop-performance', '~> 1.
|
48
|
-
spec.add_development_dependency 'rubocop-rspec', '~> 2.
|
47
|
+
spec.add_development_dependency 'rubocop', '~> 1.12', '>= 1.12.1'
|
48
|
+
spec.add_development_dependency 'rubocop-performance', '~> 1.10', '>= 1.10.2'
|
49
|
+
spec.add_development_dependency 'rubocop-rspec', '~> 2.2'
|
49
50
|
spec.add_development_dependency 'simplecov', '~> 0.17.1'
|
50
|
-
spec.add_development_dependency 'truemail-rspec', '~> 0.
|
51
|
+
spec.add_development_dependency 'truemail-rspec', '~> 0.4'
|
52
|
+
spec.add_development_dependency 'webmock', '~> 3.12', '>= 3.12.2'
|
51
53
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: truemail
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.3.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Vladislav Trotsenko
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-04-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: simpleidn
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.
|
19
|
+
version: 0.2.1
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.
|
26
|
+
version: 0.2.1
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -44,48 +44,62 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: 0.
|
47
|
+
version: 0.8.0
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: 0.
|
54
|
+
version: 0.8.0
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: dns_mock
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '2
|
61
|
+
version: '1.2'
|
62
62
|
- - ">="
|
63
63
|
- !ruby/object:Gem::Version
|
64
|
-
version: 2.
|
64
|
+
version: 1.2.1
|
65
65
|
type: :development
|
66
66
|
prerelease: false
|
67
67
|
version_requirements: !ruby/object:Gem::Requirement
|
68
68
|
requirements:
|
69
69
|
- - "~>"
|
70
70
|
- !ruby/object:Gem::Version
|
71
|
-
version: '2
|
71
|
+
version: '1.2'
|
72
72
|
- - ">="
|
73
73
|
- !ruby/object:Gem::Version
|
74
|
-
version: 2.
|
74
|
+
version: 1.2.1
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: faker
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - "~>"
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '2.17'
|
82
|
+
type: :development
|
83
|
+
prerelease: false
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - "~>"
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '2.17'
|
75
89
|
- !ruby/object:Gem::Dependency
|
76
90
|
name: fasterer
|
77
91
|
requirement: !ruby/object:Gem::Requirement
|
78
92
|
requirements:
|
79
93
|
- - "~>"
|
80
94
|
- !ruby/object:Gem::Version
|
81
|
-
version: 0.
|
95
|
+
version: 0.9.0
|
82
96
|
type: :development
|
83
97
|
prerelease: false
|
84
98
|
version_requirements: !ruby/object:Gem::Requirement
|
85
99
|
requirements:
|
86
100
|
- - "~>"
|
87
101
|
- !ruby/object:Gem::Version
|
88
|
-
version: 0.
|
102
|
+
version: 0.9.0
|
89
103
|
- !ruby/object:Gem::Dependency
|
90
104
|
name: json_matchers
|
91
105
|
requirement: !ruby/object:Gem::Requirement
|
@@ -157,7 +171,7 @@ dependencies:
|
|
157
171
|
version: '6.0'
|
158
172
|
- - ">="
|
159
173
|
- !ruby/object:Gem::Version
|
160
|
-
version: 6.0.
|
174
|
+
version: 6.0.3
|
161
175
|
type: :development
|
162
176
|
prerelease: false
|
163
177
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -167,7 +181,7 @@ dependencies:
|
|
167
181
|
version: '6.0'
|
168
182
|
- - ">="
|
169
183
|
- !ruby/object:Gem::Version
|
170
|
-
version: 6.0.
|
184
|
+
version: 6.0.3
|
171
185
|
- !ruby/object:Gem::Dependency
|
172
186
|
name: rspec
|
173
187
|
requirement: !ruby/object:Gem::Requirement
|
@@ -188,48 +202,54 @@ dependencies:
|
|
188
202
|
requirements:
|
189
203
|
- - "~>"
|
190
204
|
- !ruby/object:Gem::Version
|
191
|
-
version: '1.
|
205
|
+
version: '1.12'
|
206
|
+
- - ">="
|
207
|
+
- !ruby/object:Gem::Version
|
208
|
+
version: 1.12.1
|
192
209
|
type: :development
|
193
210
|
prerelease: false
|
194
211
|
version_requirements: !ruby/object:Gem::Requirement
|
195
212
|
requirements:
|
196
213
|
- - "~>"
|
197
214
|
- !ruby/object:Gem::Version
|
198
|
-
version: '1.
|
215
|
+
version: '1.12'
|
216
|
+
- - ">="
|
217
|
+
- !ruby/object:Gem::Version
|
218
|
+
version: 1.12.1
|
199
219
|
- !ruby/object:Gem::Dependency
|
200
220
|
name: rubocop-performance
|
201
221
|
requirement: !ruby/object:Gem::Requirement
|
202
222
|
requirements:
|
203
223
|
- - "~>"
|
204
224
|
- !ruby/object:Gem::Version
|
205
|
-
version: '1.
|
225
|
+
version: '1.10'
|
206
226
|
- - ">="
|
207
227
|
- !ruby/object:Gem::Version
|
208
|
-
version: 1.
|
228
|
+
version: 1.10.2
|
209
229
|
type: :development
|
210
230
|
prerelease: false
|
211
231
|
version_requirements: !ruby/object:Gem::Requirement
|
212
232
|
requirements:
|
213
233
|
- - "~>"
|
214
234
|
- !ruby/object:Gem::Version
|
215
|
-
version: '1.
|
235
|
+
version: '1.10'
|
216
236
|
- - ">="
|
217
237
|
- !ruby/object:Gem::Version
|
218
|
-
version: 1.
|
238
|
+
version: 1.10.2
|
219
239
|
- !ruby/object:Gem::Dependency
|
220
240
|
name: rubocop-rspec
|
221
241
|
requirement: !ruby/object:Gem::Requirement
|
222
242
|
requirements:
|
223
243
|
- - "~>"
|
224
244
|
- !ruby/object:Gem::Version
|
225
|
-
version: '2.
|
245
|
+
version: '2.2'
|
226
246
|
type: :development
|
227
247
|
prerelease: false
|
228
248
|
version_requirements: !ruby/object:Gem::Requirement
|
229
249
|
requirements:
|
230
250
|
- - "~>"
|
231
251
|
- !ruby/object:Gem::Version
|
232
|
-
version: '2.
|
252
|
+
version: '2.2'
|
233
253
|
- !ruby/object:Gem::Dependency
|
234
254
|
name: simplecov
|
235
255
|
requirement: !ruby/object:Gem::Requirement
|
@@ -250,14 +270,34 @@ dependencies:
|
|
250
270
|
requirements:
|
251
271
|
- - "~>"
|
252
272
|
- !ruby/object:Gem::Version
|
253
|
-
version: 0.
|
273
|
+
version: '0.4'
|
274
|
+
type: :development
|
275
|
+
prerelease: false
|
276
|
+
version_requirements: !ruby/object:Gem::Requirement
|
277
|
+
requirements:
|
278
|
+
- - "~>"
|
279
|
+
- !ruby/object:Gem::Version
|
280
|
+
version: '0.4'
|
281
|
+
- !ruby/object:Gem::Dependency
|
282
|
+
name: webmock
|
283
|
+
requirement: !ruby/object:Gem::Requirement
|
284
|
+
requirements:
|
285
|
+
- - "~>"
|
286
|
+
- !ruby/object:Gem::Version
|
287
|
+
version: '3.12'
|
288
|
+
- - ">="
|
289
|
+
- !ruby/object:Gem::Version
|
290
|
+
version: 3.12.2
|
254
291
|
type: :development
|
255
292
|
prerelease: false
|
256
293
|
version_requirements: !ruby/object:Gem::Requirement
|
257
294
|
requirements:
|
258
295
|
- - "~>"
|
259
296
|
- !ruby/object:Gem::Version
|
260
|
-
version:
|
297
|
+
version: '3.12'
|
298
|
+
- - ">="
|
299
|
+
- !ruby/object:Gem::Version
|
300
|
+
version: 3.12.2
|
261
301
|
description: Configurable framework agnostic plain Ruby email validator. Verify email
|
262
302
|
via Regex, DNS and SMTP.
|
263
303
|
email:
|
@@ -266,7 +306,6 @@ executables: []
|
|
266
306
|
extensions: []
|
267
307
|
extra_rdoc_files: []
|
268
308
|
files:
|
269
|
-
- ".circleci/config.yml"
|
270
309
|
- ".codeclimate.yml"
|
271
310
|
- ".github/BRANCH_NAMING_CONVENTION.md"
|
272
311
|
- ".github/ISSUE_TEMPLATE/bug_report.md"
|
@@ -291,6 +330,7 @@ files:
|
|
291
330
|
- Rakefile
|
292
331
|
- bin/console
|
293
332
|
- bin/setup
|
333
|
+
- circle.yml
|
294
334
|
- lib/truemail.rb
|
295
335
|
- lib/truemail/audit/base.rb
|
296
336
|
- lib/truemail/audit/dns.rb
|
@@ -299,6 +339,9 @@ files:
|
|
299
339
|
- lib/truemail/auditor.rb
|
300
340
|
- lib/truemail/configuration.rb
|
301
341
|
- lib/truemail/core.rb
|
342
|
+
- lib/truemail/dns/punycode_representer.rb
|
343
|
+
- lib/truemail/dns/resolver.rb
|
344
|
+
- lib/truemail/dns/worker.rb
|
302
345
|
- lib/truemail/executor.rb
|
303
346
|
- lib/truemail/log/event.rb
|
304
347
|
- lib/truemail/log/serializer/auditor_json.rb
|