truemail 2.2.3 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 57ce495b7ea8e70dc9788b5d5528f3386a57d69233f645ab665f1a187ca08e08
4
- data.tar.gz: e5696bb995de86253fec296cd6985ddb5a26f93ccc24e4a95a21b5f4ded05681
3
+ metadata.gz: 280b30990301626ac98d8017552dfb3980cdca25e0023905cf46fc47f5360f32
4
+ data.tar.gz: '009e89519a4bc12be4d2c3d2cb33a8571af146ffe0998b0559274b0cd5224d1e'
5
5
  SHA512:
6
- metadata.gz: 3ac657676afa3a27b5b2192ec7650fd742200fd4a0d5da7a21346f4a3fb75bc2038b1183d4ebdf63ad0fcd579f05169bff6bebdf1a9c2817092d634a7974a30f
7
- data.tar.gz: 3f7f43b6ee28ef483c5fdd9a31fb615f98c688e849e0363370e59d3818d3a572272c50daa7a4422dd1f12b0c5ada49e12468f8016e9a17144fc94354d6478eb7
6
+ metadata.gz: 15cad3cce31888d867608331a8907d4257220d0f18ddaf2d8f98c40b9f568bf410346fc69a77fc5cc8c69d340ab9fec7c6f99c25a5d6ffe6436297c3781dcd1d
7
+ data.tar.gz: 85b3f6aca2f21867b96fe6544e228aae369ed660bb3f886b4546f1fff76c99f2b8d4c1a324c4668bcf83e4b64bb91105531d0c272cec485edb56146568e8c92b
data/.codeclimate.yml CHANGED
@@ -7,7 +7,7 @@ checks:
7
7
  plugins:
8
8
  rubocop:
9
9
  enabled: true
10
- channel: rubocop-1-5
10
+ channel: rubocop-1-9
11
11
 
12
12
  reek:
13
13
  enabled: true
data/.reek.yml CHANGED
@@ -44,6 +44,8 @@ detectors:
44
44
  - Truemail::Configuration#logger_options
45
45
  - Truemail::Log::Serializer::Base#errors
46
46
  - Truemail::Log::Serializer::ValidatorBase#replace_invalid_chars
47
+ - Truemail::Dns::Worker#nameserver_port
48
+ - Truemail::Configuration#check_dns_settings
47
49
 
48
50
  ControlParameter:
49
51
  exclude:
@@ -73,5 +75,10 @@ detectors:
73
75
  exclude:
74
76
  - Truemail::Configuration#logger=
75
77
 
78
+ TooManyConstants:
79
+ exclude:
80
+ - Truemail::Configuration
81
+ - Truemail::RegexConstant
82
+
76
83
  exclude_paths:
77
84
  - spec/support/helpers
data/.rubocop.yml CHANGED
@@ -145,6 +145,9 @@ Style/HashExcept:
145
145
  Style/EndlessMethod:
146
146
  Enabled: true
147
147
 
148
+ Style/IfWithBooleanLiteralBranches:
149
+ Enabled: true
150
+
148
151
  Layout/LineLength:
149
152
  Max: 140
150
153
 
@@ -287,6 +290,18 @@ Lint/LambdaWithoutLiteralBlock:
287
290
  Lint/RedundantDirGlobSort:
288
291
  Enabled: true
289
292
 
293
+ Lint/NumberedParameterAssignment:
294
+ Enabled: true
295
+
296
+ Lint/OrAssignmentToConstant:
297
+ Enabled: true
298
+
299
+ Lint/SymbolConversion:
300
+ Enabled: true
301
+
302
+ Lint/TripleQuotes:
303
+ Enabled: true
304
+
290
305
  Performance/AncestorsInclude:
291
306
  Enabled: true
292
307
 
data/CHANGELOG.md CHANGED
@@ -2,6 +2,39 @@
2
2
 
3
3
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
4
4
 
5
+ ## [2.3.0] - 2020.02.05
6
+
7
+ ### Added
8
+
9
+ - Ability to use custom DNS gateway. Thanks [@le0pard](https://github.com/le0pard) for the great idea and [@verdi8](https://github.com/verdi8) for feature [request](https://github.com/truemail-rb/truemail/issues/126).
10
+
11
+ ```ruby
12
+ Truemail.configure do |config|
13
+ # Optional parameter. This option will provide to use custom DNS gateway when Truemail interacts
14
+ # with DNS. If you won't specify nameserver's ports DNS validation layer will use default DNS
15
+ # TCP/UDP port 53. By default Truemail uses DNS gateway from system settings and this option
16
+ # is equal to empty array.
17
+ config.dns = ['10.0.0.1', '10.0.0.2:5300']
18
+ end
19
+ ```
20
+
21
+ - Added `Truemail::Dns::Resolver`
22
+ - Added `Truemail::Dns::Worker`
23
+
24
+ ### Changed
25
+
26
+ - Updated `Truemail::Configuration`, tests
27
+ - Updated `Truemail::Validate::Mx`, tests
28
+ - Updated `Truemail::Audit::Base`
29
+ - Updated `Truemail::Audit::Dns`, tests
30
+ - Updated `Truemail::Audit::Ptr`, tests
31
+ - Updated `Truemail::Log::Serializer::Base`, dependent tests
32
+ - Updated namespaces for stdlib classes
33
+ - Updated gem development dependencies
34
+ - Updated linters/codeclimate configs
35
+ - Updated gem runtime/development dependencies
36
+ - Updated gem documentation, changelog, version
37
+
5
38
  ## [2.2.3] - 2020.01.12
6
39
 
7
40
  ### Fixed
data/Gemfile.lock CHANGED
@@ -1,13 +1,15 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- truemail (2.2.3)
5
- simpleidn (~> 0.1.1)
4
+ truemail (2.3.0)
5
+ simpleidn (~> 0.2.1)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
- ast (2.4.1)
10
+ addressable (2.7.0)
11
+ public_suffix (>= 2.0.2, < 5.0)
12
+ ast (2.4.2)
11
13
  bundler-audit (0.7.0.1)
12
14
  bundler (>= 1.2.0, < 3)
13
15
  thor (>= 0.18, < 2)
@@ -15,15 +17,19 @@ GEM
15
17
  childprocess (4.0.0)
16
18
  coderay (1.1.3)
17
19
  colorize (0.8.1)
18
- concurrent-ruby (1.1.7)
20
+ concurrent-ruby (1.1.8)
21
+ crack (0.4.5)
22
+ rexml
19
23
  diff-lcs (1.4.4)
20
- docile (1.3.4)
24
+ dns_mock (1.2.0)
25
+ docile (1.3.5)
21
26
  faker (2.15.1)
22
27
  i18n (>= 1.6, < 2)
23
28
  fasterer (0.8.3)
24
29
  colorize (~> 0.7)
25
30
  ruby_parser (>= 3.14.1)
26
- i18n (1.8.7)
31
+ hashdiff (1.0.1)
32
+ i18n (1.8.8)
27
33
  concurrent-ruby (~> 1.0)
28
34
  iniparse (1.5.0)
29
35
  json (2.5.1)
@@ -45,6 +51,7 @@ GEM
45
51
  byebug (~> 11.0)
46
52
  pry (~> 0.13.0)
47
53
  psych (3.3.0)
54
+ public_suffix (4.0.6)
48
55
  rainbow (3.0.0)
49
56
  rake (13.0.3)
50
57
  reek (6.0.3)
@@ -63,11 +70,11 @@ GEM
63
70
  rspec-expectations (3.10.1)
64
71
  diff-lcs (>= 1.2.0, < 2.0)
65
72
  rspec-support (~> 3.10.0)
66
- rspec-mocks (3.10.1)
73
+ rspec-mocks (3.10.2)
67
74
  diff-lcs (>= 1.2.0, < 2.0)
68
75
  rspec-support (~> 3.10.0)
69
- rspec-support (3.10.1)
70
- rubocop (1.8.1)
76
+ rspec-support (3.10.2)
77
+ rubocop (1.9.1)
71
78
  parallel (~> 1.10)
72
79
  parser (>= 3.0.0.0)
73
80
  rainbow (>= 2.2.2, < 4.0)
@@ -76,12 +83,12 @@ GEM
76
83
  rubocop-ast (>= 1.2.0, < 2.0)
77
84
  ruby-progressbar (~> 1.7)
78
85
  unicode-display_width (>= 1.4.0, < 3.0)
79
- rubocop-ast (1.4.0)
86
+ rubocop-ast (1.4.1)
80
87
  parser (>= 2.7.1.5)
81
88
  rubocop-performance (1.9.2)
82
89
  rubocop (>= 0.90.0, < 2.0)
83
90
  rubocop-ast (>= 0.4.0)
84
- rubocop-rspec (2.1.0)
91
+ rubocop-rspec (2.2.0)
85
92
  rubocop (~> 1.0)
86
93
  rubocop-ast (>= 1.1.0)
87
94
  ruby-progressbar (1.11.0)
@@ -93,9 +100,9 @@ GEM
93
100
  json (>= 1.8, < 3)
94
101
  simplecov-html (~> 0.10.0)
95
102
  simplecov-html (0.10.2)
96
- simpleidn (0.1.1)
103
+ simpleidn (0.2.1)
97
104
  unf (~> 0.1.4)
98
- thor (1.0.1)
105
+ thor (1.1.0)
99
106
  truemail-rspec (0.3.3)
100
107
  faker (~> 2.15, >= 2.15.1)
101
108
  rspec (~> 3.10)
@@ -104,6 +111,10 @@ GEM
104
111
  unf_ext
105
112
  unf_ext (0.0.7.7)
106
113
  unicode-display_width (2.0.0)
114
+ webmock (3.11.2)
115
+ addressable (>= 2.3.6)
116
+ crack (>= 0.3.2)
117
+ hashdiff (>= 0.4.0, < 2.0.0)
107
118
 
108
119
  PLATFORMS
109
120
  ruby
@@ -111,6 +122,7 @@ PLATFORMS
111
122
  DEPENDENCIES
112
123
  bundler (~> 1.16)
113
124
  bundler-audit (~> 0.7.0.1)
125
+ dns_mock (~> 1.2)
114
126
  faker (~> 2.15, >= 2.15.1)
115
127
  fasterer (~> 0.8.3)
116
128
  json_matchers (~> 0.11.1)
@@ -119,12 +131,13 @@ DEPENDENCIES
119
131
  rake (~> 13.0, >= 13.0.3)
120
132
  reek (~> 6.0, >= 6.0.3)
121
133
  rspec (~> 3.10)
122
- rubocop (~> 1.8, >= 1.8.1)
134
+ rubocop (~> 1.9, >= 1.9.1)
123
135
  rubocop-performance (~> 1.9, >= 1.9.2)
124
- rubocop-rspec (~> 2.1)
136
+ rubocop-rspec (~> 2.2)
125
137
  simplecov (~> 0.17.1)
126
138
  truemail!
127
139
  truemail-rspec (~> 0.3.3)
140
+ webmock (~> 3.11, >= 3.11.2)
128
141
 
129
142
  BUNDLED WITH
130
143
  1.16.6
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2019-2020 Vladislav Trotsenko
3
+ Copyright (c) 2019-2021 Vladislav Trotsenko
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -132,6 +132,7 @@ You can use global gem configuration or custom independent configuration. Availa
132
132
  - whitelisted domains
133
133
  - whitelist validation
134
134
  - blacklisted domains
135
+ - custom DNS gateway(s)
135
136
  - RFC MX lookup flow
136
137
  - SMTP fail fast
137
138
  - SMTP safe check
@@ -201,6 +202,12 @@ Truemail.configure do |config|
201
202
  # It is equal to empty array by default.
202
203
  config.blacklisted_domains = ['somedomain1.com', 'somedomain2.com']
203
204
 
205
+ # Optional parameter. This option will provide to use custom DNS gateway when Truemail interacts
206
+ # with DNS. If you won't specify nameserver's ports DNS validation layer will use default DNS
207
+ # TCP/UDP port 53. By default Truemail uses DNS gateway from system settings and this option
208
+ # is equal to empty array.
209
+ config.dns = ['10.0.0.1', '10.0.0.2:54']
210
+
204
211
  # Optional parameter. This option will provide to use not RFC MX lookup flow.
205
212
  # It means that MX and Null MX records will be cheked on the DNS validation layer only.
206
213
  # By default this option is disabled.
@@ -242,6 +249,7 @@ Truemail.configuration
242
249
  @whitelisted_domains=[],
243
250
  @whitelist_validation=true,
244
251
  @blacklisted_domains=[],
252
+ @dns=[],
245
253
  @verifier_domain="somedomain.com",
246
254
  @verifier_email="verifier@example.com",
247
255
  @not_rfc_mx_lookup_flow=true,
@@ -272,6 +280,7 @@ Truemail.configuration
272
280
  @whitelisted_domains=[],
273
281
  @whitelist_validation=true,
274
282
  @blacklisted_domains=[],
283
+ @dns=[],
275
284
  @verifier_domain="somedomain.com",
276
285
  @verifier_email="verifier@example.com",
277
286
  @not_rfc_mx_lookup_flow=true,
@@ -352,6 +361,7 @@ Truemail.validate('email@white-domain.com')
352
361
  smtp_debug=nil>,
353
362
  configuration=#<Truemail::Configuration:0x00005629f801bd28
354
363
  @blacklisted_domains=["black-domain.com", "somedomain.com"],
364
+ @dns=[],
355
365
  @connection_attempts=2,
356
366
  @connection_timeout=2,
357
367
  @default_validation_type=:smtp,
@@ -399,6 +409,7 @@ Truemail.validate('email@white-domain.com', with: :regex)
399
409
  configuration=
400
410
  #<Truemail::Configuration:0x0000563f0d2605c8
401
411
  @blacklisted_domains=[],
412
+ @dns=[],
402
413
  @connection_attempts=2,
403
414
  @connection_timeout=2,
404
415
  @default_validation_type=:smtp,
@@ -432,6 +443,7 @@ Truemail.validate('email@domain.com', with: :regex)
432
443
  configuration=
433
444
  #<Truemail::Configuration:0x0000563f0cd82ab0
434
445
  @blacklisted_domains=[],
446
+ @dns=[],
435
447
  @connection_attempts=2,
436
448
  @connection_timeout=2,
437
449
  @default_validation_type=:smtp,
@@ -467,6 +479,7 @@ Truemail.validate('email@black-domain.com')
467
479
  configuration=
468
480
  #<Truemail::Configuration:0x0000563f0d36f4f0
469
481
  @blacklisted_domains=[],
482
+ @dns=[],
470
483
  @connection_attempts=2,
471
484
  @connection_timeout=2,
472
485
  @default_validation_type=:smtp,
@@ -502,6 +515,7 @@ Truemail.validate('email@somedomain.com')
502
515
  configuration=
503
516
  #<Truemail::Configuration:0x0000563f0d3f8fc0
504
517
  @blacklisted_domains=[],
518
+ @dns=[],
505
519
  @connection_attempts=2,
506
520
  @connection_timeout=2,
507
521
  @default_validation_type=:smtp,
@@ -553,6 +567,7 @@ Truemail.validate('email@example.com', with: :regex)
553
567
  configuration=
554
568
  #<Truemail::Configuration:0x000055aa56a54d48
555
569
  @blacklisted_domains=[],
570
+ @dns=[],
556
571
  @connection_attempts=2,
557
572
  @connection_timeout=2,
558
573
  @default_validation_type=:smtp,
@@ -596,6 +611,7 @@ Truemail.validate('email@example.com', with: :regex)
596
611
  configuration=
597
612
  #<Truemail::Configuration:0x0000560e58d80830
598
613
  @blacklisted_domains=[],
614
+ @dns=[],
599
615
  @connection_attempts=2,
600
616
  @connection_timeout=2,
601
617
  @default_validation_type=:smtp,
@@ -650,6 +666,7 @@ Truemail.validate('email@example.com', with: :mx)
650
666
  configuration=
651
667
  #<Truemail::Configuration:0x0000559b6e44af70
652
668
  @blacklisted_domains=[],
669
+ @dns=[],
653
670
  @connection_attempts=2,
654
671
  @connection_timeout=2,
655
672
  @default_validation_type=:smtp,
@@ -695,6 +712,7 @@ Truemail.validate('email@example.com', with: :mx)
695
712
  configuration=
696
713
  #<Truemail::Configuration:0x0000559b6e44af70
697
714
  @blacklisted_domains=[],
715
+ @dns=[],
698
716
  @connection_attempts=2,
699
717
  @connection_timeout=2,
700
718
  @default_validation_type=:smtp,
@@ -769,6 +787,7 @@ Truemail.validate('email@example.com')
769
787
  configuration=
770
788
  #<Truemail::Configuration:0x00007fdc4504f5c8
771
789
  @blacklisted_domains=[],
790
+ @dns=[],
772
791
  @connection_attempts=2,
773
792
  @connection_timeout=2,
774
793
  @default_validation_type=:smtp,
@@ -812,6 +831,7 @@ Truemail.validate('email@example.com')
812
831
  configuration=
813
832
  #<Truemail::Configuration:0x00005615e87b9298
814
833
  @blacklisted_domains=[],
834
+ @dns=[],
815
835
  @connection_attempts=2,
816
836
  @connection_timeout=2,
817
837
  @default_validation_type=:smtp,
@@ -862,6 +882,7 @@ Truemail.validate('email@example.com')
862
882
  configuration=
863
883
  #<Truemail::Configuration:0x00005615e87b9298
864
884
  @blacklisted_domains=[],
885
+ @dns=[],
865
886
  @connection_attempts=2,
866
887
  @connection_timeout=2,
867
888
  @default_validation_type=:smtp,
@@ -924,6 +945,7 @@ Truemail.validate('email@example.com')
924
945
  configuration=
925
946
  #<Truemail::Configuration:0x00005615e87b9298
926
947
  @blacklisted_domains=[],
948
+ @dns=[],
927
949
  @connection_attempts=2,
928
950
  @connection_timeout=2,
929
951
  @default_validation_type=:smtp,
@@ -971,6 +993,7 @@ Truemail.validate('email@example.com')
971
993
  configuration=
972
994
  #<Truemail::Configuration:0x00005615e87b9298
973
995
  @blacklisted_domains=[],
996
+ @dns=[],
974
997
  @connection_attempts=2,
975
998
  @connection_timeout=2,
976
999
  @default_validation_type=:smtp,
@@ -1019,6 +1042,7 @@ Truemail.host_audit
1019
1042
  configuration=
1020
1043
  #<Truemail::Configuration:0x00005615e86327a8
1021
1044
  @blacklisted_domains=[],
1045
+ @dns=[],
1022
1046
  @connection_attempts=2,
1023
1047
  @connection_timeout=2,
1024
1048
  @default_validation_type=:smtp,
@@ -1046,6 +1070,7 @@ Truemail.host_audit
1046
1070
  configuration=
1047
1071
  #<Truemail::Configuration:0x00005615e86327a8
1048
1072
  @blacklisted_domains=[],
1073
+ @dns=[],
1049
1074
  @connection_attempts=2,
1050
1075
  @connection_timeout=2,
1051
1076
  @default_validation_type=:smtp,
@@ -1101,6 +1126,7 @@ Truemail::Log::Serializer::AuditorJson.call(Truemail.host_audit)
1101
1126
  "whitelist_validation": false,
1102
1127
  "whitelisted_domains": null,
1103
1128
  "blacklisted_domains": null,
1129
+ "dns": null,
1104
1130
  "not_rfc_mx_lookup_flow": false,
1105
1131
  "smtp_fail_fast": false,
1106
1132
  "smtp_safe_check": false,
@@ -1140,6 +1166,7 @@ Truemail::Log::Serializer::ValidatorJson.call(Truemail.validate('nonexistent_ema
1140
1166
  "whitelist_validation": false,
1141
1167
  "whitelisted_domains": null,
1142
1168
  "blacklisted_domains": null,
1169
+ "dns": null,
1143
1170
  "not_rfc_mx_lookup_flow": false,
1144
1171
  "smtp_fail_fast": false,
1145
1172
  "smtp_safe_check": false,
@@ -1181,6 +1208,7 @@ Truemail.host_audit.as_json
1181
1208
  "whitelist_validation": false,
1182
1209
  "whitelisted_domains": null,
1183
1210
  "blacklisted_domains": null,
1211
+ "dns": null,
1184
1212
  "not_rfc_mx_lookup_flow": false,
1185
1213
  "smtp_fail_fast": false,
1186
1214
  "smtp_safe_check": false,
@@ -1217,6 +1245,7 @@ Truemail.validate('nonexistent_email@bestweb.com.ua').as_json
1217
1245
  "whitelist_validation": false,
1218
1246
  "whitelisted_domains": null,
1219
1247
  "blacklisted_domains": null,
1248
+ "dns": null,
1220
1249
  "not_rfc_mx_lookup_flow": false,
1221
1250
  "smtp_fail_fast": false,
1222
1251
  "smtp_safe_check": false,
data/lib/truemail.rb CHANGED
@@ -46,7 +46,7 @@ module Truemail
46
46
  end
47
47
 
48
48
  def check_argument_type(argument)
49
- raise_unless(argument.is_a?(String), Truemail::INVALID_TYPE, Truemail::TypeError)
49
+ raise_unless(argument.is_a?(::String), Truemail::INVALID_TYPE, Truemail::TypeError)
50
50
  end
51
51
 
52
52
  def determine_configuration(custom_configuration)
@@ -5,7 +5,6 @@ module Truemail
5
5
  class Base < Truemail::Worker
6
6
  require 'net/http'
7
7
  require 'ipaddr'
8
- require 'resolv'
9
8
 
10
9
  private
11
10
 
@@ -14,7 +14,7 @@ module Truemail
14
14
 
15
15
  def a_record
16
16
  Truemail::Wrapper.call(configuration: configuration) do
17
- Resolv::DNS.new.getaddress(verifier_domain).to_s
17
+ Truemail::Dns::Resolver.a_record(verifier_domain, configuration: configuration)
18
18
  end
19
19
  end
20
20
 
@@ -15,7 +15,7 @@ module Truemail
15
15
  private
16
16
 
17
17
  def detect_ip_via_ipify
18
- Net::HTTP.get(URI(Truemail::Audit::Ip::GET_MY_IP_URL))
18
+ ::Net::HTTP.get(URI(Truemail::Audit::Ip::GET_MY_IP_URL))
19
19
  end
20
20
 
21
21
  def detect_current_host_ip
@@ -15,13 +15,14 @@ module Truemail
15
15
  private
16
16
 
17
17
  def current_host_reverse_lookup
18
- IPAddr.new(current_host_ip).reverse
18
+ ::IPAddr.new(current_host_ip).reverse
19
19
  end
20
20
 
21
21
  def ptr_records
22
22
  @ptr_records ||= Truemail::Wrapper.call(configuration: configuration) do
23
- Resolv::DNS.new.getresources(
24
- current_host_reverse_lookup, Resolv::DNS::Resource::IN::PTR
23
+ Truemail::Dns::Resolver.ptr_records(
24
+ current_host_reverse_lookup,
25
+ configuration: configuration
25
26
  ).map { |ptr_record| ptr_record.name.to_s }
26
27
  end || []
27
28
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Truemail
4
4
  class Auditor < Truemail::Executor
5
- Result = Struct.new(:current_host_ip, :warnings, :configuration, keyword_init: true) do
5
+ Result = ::Struct.new(:current_host_ip, :warnings, :configuration, keyword_init: true) do
6
6
  def initialize(warnings: {}, **args)
7
7
  super
8
8
  end
@@ -7,19 +7,23 @@ module Truemail
7
7
  DEFAULT_CONNECTION_ATTEMPTS = 2
8
8
  DEFAULT_VALIDATION_TYPE = :smtp
9
9
  DEFAULT_LOGGER_OPTIONS = { tracking_event: :error, stdout: false, log_absolute_path: nil }.freeze
10
-
11
- attr_reader :email_pattern,
12
- :smtp_error_body_pattern,
13
- :verifier_email,
10
+ SETTERS = %i[
11
+ email_pattern
12
+ smtp_error_body_pattern
13
+ connection_timeout
14
+ response_timeout
15
+ connection_attempts
16
+ whitelisted_domains
17
+ blacklisted_domains
18
+ ].freeze
19
+
20
+ attr_reader :verifier_email,
14
21
  :verifier_domain,
15
- :connection_timeout,
16
- :response_timeout,
17
- :connection_attempts,
18
22
  :default_validation_type,
19
23
  :validation_type_by_domain,
20
- :whitelisted_domains,
21
- :blacklisted_domains,
22
- :logger
24
+ :dns,
25
+ :logger,
26
+ *Truemail::Configuration::SETTERS
23
27
 
24
28
  attr_accessor :whitelist_validation, :not_rfc_mx_lookup_flow, :smtp_fail_fast, :smtp_safe_check
25
29
 
@@ -30,13 +34,6 @@ module Truemail
30
34
  tap(&block) if block
31
35
  end
32
36
 
33
- %i[email_pattern smtp_error_body_pattern].each do |method|
34
- define_method("#{method}=") do |argument|
35
- raise_unless(argument, __method__, argument.is_a?(Regexp))
36
- instance_variable_set(:"@#{method}", argument)
37
- end
38
- end
39
-
40
37
  def verifier_email=(email)
41
38
  validate_arguments(email, __method__)
42
39
  @verifier_email = email.downcase
@@ -48,15 +45,8 @@ module Truemail
48
45
  @verifier_domain = domain.downcase
49
46
  end
50
47
 
51
- %i[connection_timeout response_timeout connection_attempts].each do |method|
52
- define_method("#{method}=") do |argument|
53
- raise_unless(argument, __method__, argument.is_a?(Integer) && argument.positive?)
54
- instance_variable_set(:"@#{method}", argument)
55
- end
56
- end
57
-
58
48
  def default_validation_type=(argument)
59
- raise_unless(argument, __method__, argument.is_a?(Symbol) && Truemail::Validator::VALIDATION_TYPES.include?(argument))
49
+ raise_unless(argument, __method__, argument.is_a?(::Symbol) && Truemail::Validator::VALIDATION_TYPES.include?(argument))
60
50
  @default_validation_type = argument
61
51
  end
62
52
 
@@ -65,18 +55,31 @@ module Truemail
65
55
  validation_type_by_domain.merge!(settings)
66
56
  end
67
57
 
68
- %i[whitelisted_domains blacklisted_domains].each do |method|
58
+ def argument_consistent?(argument)
59
+ case argument
60
+ when ::Array then check_domain_list(argument)
61
+ when ::Integer then argument.positive?
62
+ when ::Regexp then true
63
+ end
64
+ end
65
+
66
+ Truemail::Configuration::SETTERS.each do |method|
69
67
  define_method("#{method}=") do |argument|
70
- raise_unless(argument, __method__, argument.is_a?(Array) && check_domain_list(argument))
68
+ raise_unless(argument, __method__, argument_consistent?(argument))
71
69
  instance_variable_set(:"@#{method}", argument)
72
70
  end
73
71
  end
74
72
 
73
+ def dns=(argument)
74
+ raise_unless(argument, __method__, argument.is_a?(::Array) && check_dns_settings(argument))
75
+ @dns = argument
76
+ end
77
+
75
78
  def logger=(options)
76
79
  tracking_event, stdout, log_absolute_path = logger_options(options)
77
80
  valid_event = Truemail::Log::Event::TRACKING_EVENTS.key?(tracking_event)
78
81
  stdout_only = stdout && log_absolute_path.nil?
79
- file_only = log_absolute_path.is_a?(String)
82
+ file_only = log_absolute_path.is_a?(::String)
80
83
  both_types = stdout && file_only
81
84
  argument_info = valid_event ? log_absolute_path : tracking_event
82
85
  raise_unless(argument_info, __method__, valid_event && (stdout_only || file_only || both_types))
@@ -89,7 +92,7 @@ module Truemail
89
92
 
90
93
  private
91
94
 
92
- def instance_initializer
95
+ def instance_initializer # rubocop:disable Metrics/MethodLength
93
96
  {
94
97
  email_pattern: Truemail::RegexConstant::REGEX_EMAIL_PATTERN,
95
98
  smtp_error_body_pattern: Truemail::RegexConstant::REGEX_SMTP_ERROR_BODY_PATTERN,
@@ -101,6 +104,7 @@ module Truemail
101
104
  whitelisted_domains: [],
102
105
  whitelist_validation: false,
103
106
  blacklisted_domains: [],
107
+ dns: [],
104
108
  not_rfc_mx_lookup_flow: false,
105
109
  smtp_fail_fast: false,
106
110
  smtp_safe_check: false
@@ -137,13 +141,17 @@ module Truemail
137
141
  end
138
142
 
139
143
  def validate_validation_type(settings)
140
- raise_unless(settings, 'hash with settings', settings.is_a?(Hash))
144
+ raise_unless(settings, 'hash with settings', settings.is_a?(::Hash))
141
145
  settings.each do |domain, validation_type|
142
146
  check_domain(domain)
143
147
  check_validation_type(validation_type)
144
148
  end
145
149
  end
146
150
 
151
+ def check_dns_settings(dns_servers)
152
+ dns_servers.all? { |dns_server| Truemail::RegexConstant::REGEX_DNS_SERVER_ADDRESS_PATTERN.match?(dns_server.to_s) }
153
+ end
154
+
147
155
  def logger_options(current_options)
148
156
  Truemail::Configuration::DEFAULT_LOGGER_OPTIONS.merge(current_options).values
149
157
  end
data/lib/truemail/core.rb CHANGED
@@ -10,32 +10,28 @@ module Truemail
10
10
  require_relative '../truemail/validator'
11
11
  require_relative '../truemail/logger'
12
12
 
13
- ConfigurationError = Class.new(StandardError)
14
- TypeError = Class.new(StandardError)
15
-
16
- ArgumentError = Class.new(StandardError) do
13
+ ConfigurationError = ::Class.new(::StandardError)
14
+ TypeError = ::Class.new(::StandardError)
15
+ ArgumentError = ::Class.new(::StandardError) do
17
16
  def initialize(arg_value, arg_name)
18
17
  super("#{arg_value} is not a valid #{arg_name}")
19
18
  end
20
19
  end
21
20
 
22
- PunycodeRepresenter = Class.new do
23
- require 'simpleidn'
24
-
25
- def self.call(email)
26
- return unless email.is_a?(String)
27
- return email if email.ascii_only?
28
- user, domain = email.split('@')
29
- "#{user}@#{SimpleIDN.to_ascii(domain.downcase)}"
30
- end
31
- end
32
-
33
21
  module RegexConstant
34
22
  REGEX_DOMAIN = /[\p{L}0-9]+([\-.]{1}[\p{L}0-9]+)*\.\p{L}{2,63}/i.freeze
35
23
  REGEX_EMAIL_PATTERN = /(?=\A.{6,255}\z)(\A([\p{L}0-9]+[\w|\-.+]*)@(#{REGEX_DOMAIN})\z)/.freeze
36
24
  REGEX_DOMAIN_PATTERN = /(?=\A.{4,255}\z)(\A#{REGEX_DOMAIN}\z)/.freeze
37
25
  REGEX_DOMAIN_FROM_EMAIL = /\A.+@(.+)\z/.freeze
38
26
  REGEX_SMTP_ERROR_BODY_PATTERN = /(?=.*550)(?=.*(user|account|customer|mailbox)).*/i.freeze
27
+ REGEX_PORT_NUMBER = /(6553[0-5]|655[0-2][0-9]\d|65[0-4](\d){2}|6[0-4](\d){3}|[1-5](\d){4}|[1-9](\d){0,3})/.freeze
28
+ REGEX_DNS_SERVER_ADDRESS_PATTERN = /\A((1\d|[1-9]|2[0-4])?\d|25[0-5])(\.\g<1>){3}(:#{REGEX_PORT_NUMBER})?\z/.freeze
29
+ end
30
+
31
+ module Dns
32
+ require_relative '../truemail/dns/punycode_representer'
33
+ require_relative '../truemail/dns/worker'
34
+ require_relative '../truemail/dns/resolver'
39
35
  end
40
36
 
41
37
  module Audit
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Truemail
4
+ module Dns
5
+ PunycodeRepresenter = Class.new do
6
+ require 'simpleidn'
7
+
8
+ def self.call(email)
9
+ return unless email.is_a?(::String)
10
+ return email if email.ascii_only?
11
+ user, domain = email.split('@')
12
+ "#{user}@#{SimpleIDN.to_ascii(domain.downcase)}"
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Truemail
4
+ module Dns
5
+ class Resolver
6
+ WORKER_ACTIONS = %i[dns_lookup a_record a_records cname_records mx_records ptr_records].freeze
7
+
8
+ class << self
9
+ Truemail::Dns::Resolver::WORKER_ACTIONS.each do |worker_action|
10
+ define_method(worker_action) do |argument, configuration:|
11
+ Truemail::Dns::Worker.new(configuration.dns).public_send(worker_action, argument)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Truemail
4
+ module Dns
5
+ require 'resolv'
6
+
7
+ class Worker < ::Resolv::DNS
8
+ DEFAULT_DNS_PORT = 53
9
+
10
+ attr_reader :dns_gateway
11
+
12
+ def initialize(dns_servers)
13
+ super(dns_servers.empty? ? nil : config_info(dns_servers))
14
+ end
15
+
16
+ def dns_lookup(host_address)
17
+ getname(host_address).to_s
18
+ end
19
+
20
+ def a_record(host_name)
21
+ getaddress(host_name).to_s
22
+ end
23
+
24
+ def a_records(host_name)
25
+ getaddresses(host_name).map(&:to_s)
26
+ end
27
+
28
+ def cname_records(host_name)
29
+ getresources(host_name, ::Resolv::DNS::Resource::IN::CNAME)
30
+ end
31
+
32
+ def mx_records(host_name)
33
+ getresources(host_name, ::Resolv::DNS::Resource::IN::MX)
34
+ end
35
+
36
+ def ptr_records(host_address)
37
+ getresources(host_address, ::Resolv::DNS::Resource::IN::PTR)
38
+ end
39
+
40
+ private
41
+
42
+ def nameserver_port(server)
43
+ server_address, server_port = server.split(':')
44
+ [server_address, server_port ? server_port.to_i : Truemail::Dns::Worker::DEFAULT_DNS_PORT]
45
+ end
46
+
47
+ def config_info(dns_servers)
48
+ @dns_gateway = { nameserver_port: dns_servers.map { |server| nameserver_port(server) } }
49
+ end
50
+ end
51
+ end
52
+ end
@@ -13,7 +13,7 @@ module Truemail
13
13
  def result
14
14
  @result ||=
15
15
  {
16
- date: Time.now,
16
+ date: ::Time.now,
17
17
  current_host_ip: executor_result.current_host_ip,
18
18
  warnings: warnings(executor_result.warnings),
19
19
  configuration: configuration
@@ -30,7 +30,7 @@ module Truemail
30
30
 
31
31
  alias warnings errors
32
32
 
33
- %i[validation_type_by_domain whitelisted_domains blacklisted_domains].each do |method|
33
+ %i[validation_type_by_domain whitelisted_domains blacklisted_domains dns].each do |method|
34
34
  define_method(method) do
35
35
  value = executor_configuration.public_send(method)
36
36
  return if value.empty?
@@ -55,6 +55,7 @@ module Truemail
55
55
  whitelist_validation: executor_configuration.whitelist_validation,
56
56
  whitelisted_domains: whitelisted_domains,
57
57
  blacklisted_domains: blacklisted_domains,
58
+ dns: dns,
58
59
  not_rfc_mx_lookup_flow: executor_configuration.not_rfc_mx_lookup_flow,
59
60
  smtp_fail_fast: executor_configuration.smtp_fail_fast,
60
61
  smtp_safe_check: executor_configuration.smtp_safe_check,
@@ -34,7 +34,7 @@ module Truemail
34
34
  def result
35
35
  @result ||=
36
36
  {
37
- date: Time.now,
37
+ date: ::Time.now,
38
38
  email: executor_result.email,
39
39
  validation_type: validation_type,
40
40
  success: executor_result.success,
@@ -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"
@@ -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
 
@@ -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 = Resolv::DNS.new.getresources(hostname, Resolv::DNS::Resource::IN::MX)
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).map do |mx_record|
49
- Resolv.getaddresses(mx_record.exchange.to_s)
50
- end.flatten
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
- Resolv.getaddress(hostname)
65
+ Truemail::Dns::Resolver.a_record(hostname, configuration: configuration)
68
66
  end
69
67
 
70
68
  def hosts_from_cname_records?
71
- cname_records = Resolv::DNS.new.getresources(domain, Resolv::DNS::Resource::IN::CNAME)
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 = Resolv.getname(host)
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
@@ -23,14 +23,14 @@ module Truemail
23
23
  end
24
24
 
25
25
  def check_port
26
- response.port_opened = Socket.tcp(
26
+ response.port_opened = ::Socket.tcp(
27
27
  host,
28
28
  Truemail::Validate::Smtp::Request::SMTP_PORT,
29
29
  connect_timeout: configuration.connection_timeout,
30
30
  &port_open_status
31
31
  )
32
32
  rescue => error
33
- retry if attempts_exist? && error.is_a?(Errno::ETIMEDOUT)
33
+ retry if attempts_exist? && error.is_a?(::Errno::ETIMEDOUT)
34
34
  response.port_opened = false
35
35
  end
36
36
 
@@ -65,7 +65,7 @@ module Truemail
65
65
  end
66
66
 
67
67
  def session
68
- 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|
69
69
  settings.open_timeout = configuration.connection_timeout
70
70
  settings.read_timeout = configuration.response_timeout
71
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
@@ -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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Truemail
4
- VERSION = '2.2.3'
4
+ VERSION = '2.3.0'
5
5
  end
@@ -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,10 +31,11 @@ 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.1.1'
34
+ spec.add_runtime_dependency 'simpleidn', '~> 0.2.1'
35
35
 
36
36
  spec.add_development_dependency 'bundler', '~> 1.16'
37
37
  spec.add_development_dependency 'bundler-audit', '~> 0.7.0.1'
38
+ spec.add_development_dependency 'dns_mock', '~> 1.2'
38
39
  spec.add_development_dependency 'faker', '~> 2.15', '>= 2.15.1'
39
40
  spec.add_development_dependency 'fasterer', '~> 0.8.3'
40
41
  spec.add_development_dependency 'json_matchers', '~> 0.11.1'
@@ -43,9 +44,10 @@ Gem::Specification.new do |spec|
43
44
  spec.add_development_dependency 'rake', '~> 13.0', '>= 13.0.3'
44
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.8', '>= 1.8.1'
47
+ spec.add_development_dependency 'rubocop', '~> 1.9', '>= 1.9.1'
47
48
  spec.add_development_dependency 'rubocop-performance', '~> 1.9', '>= 1.9.2'
48
- spec.add_development_dependency 'rubocop-rspec', '~> 2.1'
49
+ spec.add_development_dependency 'rubocop-rspec', '~> 2.2'
49
50
  spec.add_development_dependency 'simplecov', '~> 0.17.1'
50
51
  spec.add_development_dependency 'truemail-rspec', '~> 0.3.3'
52
+ spec.add_development_dependency 'webmock', '~> 3.11', '>= 3.11.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.2.3
4
+ version: 2.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vladislav Trotsenko
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-01-12 00:00:00.000000000 Z
11
+ date: 2021-02-05 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.1.1
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.1.1
26
+ version: 0.2.1
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: 0.7.0.1
55
+ - !ruby/object:Gem::Dependency
56
+ name: dns_mock
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.2'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.2'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: faker
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -188,20 +202,20 @@ dependencies:
188
202
  requirements:
189
203
  - - "~>"
190
204
  - !ruby/object:Gem::Version
191
- version: '1.8'
205
+ version: '1.9'
192
206
  - - ">="
193
207
  - !ruby/object:Gem::Version
194
- version: 1.8.1
208
+ version: 1.9.1
195
209
  type: :development
196
210
  prerelease: false
197
211
  version_requirements: !ruby/object:Gem::Requirement
198
212
  requirements:
199
213
  - - "~>"
200
214
  - !ruby/object:Gem::Version
201
- version: '1.8'
215
+ version: '1.9'
202
216
  - - ">="
203
217
  - !ruby/object:Gem::Version
204
- version: 1.8.1
218
+ version: 1.9.1
205
219
  - !ruby/object:Gem::Dependency
206
220
  name: rubocop-performance
207
221
  requirement: !ruby/object:Gem::Requirement
@@ -228,14 +242,14 @@ dependencies:
228
242
  requirements:
229
243
  - - "~>"
230
244
  - !ruby/object:Gem::Version
231
- version: '2.1'
245
+ version: '2.2'
232
246
  type: :development
233
247
  prerelease: false
234
248
  version_requirements: !ruby/object:Gem::Requirement
235
249
  requirements:
236
250
  - - "~>"
237
251
  - !ruby/object:Gem::Version
238
- version: '2.1'
252
+ version: '2.2'
239
253
  - !ruby/object:Gem::Dependency
240
254
  name: simplecov
241
255
  requirement: !ruby/object:Gem::Requirement
@@ -264,6 +278,26 @@ dependencies:
264
278
  - - "~>"
265
279
  - !ruby/object:Gem::Version
266
280
  version: 0.3.3
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.11'
288
+ - - ">="
289
+ - !ruby/object:Gem::Version
290
+ version: 3.11.2
291
+ type: :development
292
+ prerelease: false
293
+ version_requirements: !ruby/object:Gem::Requirement
294
+ requirements:
295
+ - - "~>"
296
+ - !ruby/object:Gem::Version
297
+ version: '3.11'
298
+ - - ">="
299
+ - !ruby/object:Gem::Version
300
+ version: 3.11.2
267
301
  description: Configurable framework agnostic plain Ruby email validator. Verify email
268
302
  via Regex, DNS and SMTP.
269
303
  email:
@@ -305,6 +339,9 @@ files:
305
339
  - lib/truemail/auditor.rb
306
340
  - lib/truemail/configuration.rb
307
341
  - lib/truemail/core.rb
342
+ - lib/truemail/dns/punycode_representer.rb
343
+ - lib/truemail/dns/resolver.rb
344
+ - lib/truemail/dns/worker.rb
308
345
  - lib/truemail/executor.rb
309
346
  - lib/truemail/log/event.rb
310
347
  - lib/truemail/log/serializer/auditor_json.rb