truemail 2.0.2 → 2.2.3

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: 6345fef51d5f38efde3065b8edb6d777f7c0cf9aec7a44b073da86bce5943c6a
4
- data.tar.gz: 6e55b56b4cb92143059ccd3263739e724ea29f118943546d6464af248951d0c6
3
+ metadata.gz: 57ce495b7ea8e70dc9788b5d5528f3386a57d69233f645ab665f1a187ca08e08
4
+ data.tar.gz: e5696bb995de86253fec296cd6985ddb5a26f93ccc24e4a95a21b5f4ded05681
5
5
  SHA512:
6
- metadata.gz: 451d5ee34a5eb52e5451017210bf6c4c5fe213f44cf7bc8b66221ab31fa202c682ecad99f810c571f430f4da0fa0c981958db694e929407ad268201bb60c0652
7
- data.tar.gz: 4210cf723bd90843ccf7d806b07563b4eff7bece40d361e35897316bb5c779eedd8a82e60d46948a0f419ea9ee5ed2bfc80fc67a4384dcc47de85d25326609ac
6
+ metadata.gz: 3ac657676afa3a27b5b2192ec7650fd742200fd4a0d5da7a21346f4a3fb75bc2038b1183d4ebdf63ad0fcd579f05169bff6bebdf1a9c2817092d634a7974a30f
7
+ data.tar.gz: 3f7f43b6ee28ef483c5fdd9a31fb615f98c688e849e0363370e59d3818d3a572272c50daa7a4422dd1f12b0c5ada49e12468f8016e9a17144fc94354d6478eb7
@@ -7,7 +7,7 @@ checks:
7
7
  plugins:
8
8
  rubocop:
9
9
  enabled: true
10
- channel: rubocop-1-3
10
+ channel: rubocop-1-5
11
11
 
12
12
  reek:
13
13
  enabled: true
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: Bug report
3
3
  about: Create a report to help us improve
4
- title: [BUG]
4
+ title: "[BUG] Your bug report title here"
5
5
  labels: bug
6
6
  assignees: bestwebua
7
7
 
@@ -16,6 +16,8 @@ assignees: bestwebua
16
16
  - [ ] I have read the [documentation](https://truemail-rb.org/truemail-gem)
17
17
  - [ ] I have searched for [existing GitHub issues](https://github.com/truemail-rb/truemail/issues)
18
18
 
19
+ <!-- Please use next pattern for your bug report title: [BUG] Your bug report title here -->
20
+
19
21
  ### Bug description
20
22
  <!-- Please include what's happening, expected behavior, and any relevant code samples -->
21
23
 
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: Feature request
3
3
  about: Suggest an idea for Truemail
4
- title: [FEATURE]
4
+ title: "[FEATURE] Your feature request title here"
5
5
  labels: enhancement
6
6
  assignees: bestwebua
7
7
 
@@ -16,6 +16,8 @@ assignees: bestwebua
16
16
  - [ ] I have read the [documentation](https://truemail-rb.org/truemail-gem)
17
17
  - [ ] I have searched for [existing GitHub issues](https://github.com/truemail-rb/truemail/issues)
18
18
 
19
+ <!-- Please use next pattern for your feature request title: [FEATURE] Your feature request title here -->
20
+
19
21
  ### Feature description
20
22
 
21
23
  <!-- Is your feature request related to a problem? Please describe. A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: Issue report
3
3
  about: Create a report to help us improve
4
- title: [ISSUE]
4
+ title: "[ISSUE] Your issue report title here"
5
5
  labels: ''
6
6
  assignees: bestwebua
7
7
 
@@ -16,6 +16,8 @@ assignees: bestwebua
16
16
  - [ ] I have read the [documentation](https://truemail-rb.org/truemail-gem)
17
17
  - [ ] I have searched for [existing GitHub issues](https://github.com/truemail-rb/truemail/issues)
18
18
 
19
+ <!-- Please use next pattern for your issue report title: [ISSUE] Your issue report title here -->
20
+
19
21
  ### Issue description
20
22
  <!-- Please include what's happening, expected behavior, and any relevant code samples -->
21
23
 
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: Question
3
3
  about: Ask your question to Truemail team
4
- title: [QUESTION]
4
+ title: "[QUESTION] Your question title here"
5
5
  labels: question
6
6
  assignees: bestwebua
7
7
 
@@ -15,6 +15,8 @@ assignees: bestwebua
15
15
  - [ ] I have read the [documentation](https://truemail-rb.org/truemail-gem)
16
16
  - [ ] I have searched for [existing GitHub issues](https://github.com/truemail-rb/truemail/issues)
17
17
 
18
+ <!-- Please use next pattern for your question title: [QUESTION] Your question title here -->
19
+
18
20
  ### Question
19
21
 
20
22
  <!-- Your question context here -->
data/.reek.yml CHANGED
@@ -13,6 +13,7 @@ detectors:
13
13
  - Truemail::Validate::Smtp#run
14
14
  - Truemail::Validate::Mx#hosts_from_cname_records
15
15
  - Truemail::Configuration#logger=
16
+ - Truemail::Validate::Smtp::Request#initialize
16
17
 
17
18
  TooManyInstanceVariables:
18
19
  exclude:
@@ -27,6 +28,7 @@ detectors:
27
28
  exclude:
28
29
  - Truemail::Configuration#whitelist_validation
29
30
  - Truemail::Configuration#not_rfc_mx_lookup_flow
31
+ - Truemail::Configuration#smtp_fail_fast
30
32
  - Truemail::Configuration#smtp_safe_check
31
33
  - Truemail::Wrapper#attempts
32
34
 
@@ -41,6 +43,7 @@ detectors:
41
43
  - Truemail::Configuration#domain_matcher
42
44
  - Truemail::Configuration#logger_options
43
45
  - Truemail::Log::Serializer::Base#errors
46
+ - Truemail::Log::Serializer::ValidatorBase#replace_invalid_chars
44
47
 
45
48
  ControlParameter:
46
49
  exclude:
@@ -136,6 +136,15 @@ Style/NilLambda:
136
136
  Style/SwapValues:
137
137
  Enabled: true
138
138
 
139
+ Style/RedundantArgument:
140
+ Enabled: true
141
+
142
+ Style/HashExcept:
143
+ Enabled: true
144
+
145
+ Style/EndlessMethod:
146
+ Enabled: true
147
+
139
148
  Layout/LineLength:
140
149
  Max: 140
141
150
 
@@ -167,6 +176,9 @@ Layout/EmptyLinesAroundAttributeAccessor:
167
176
  Layout/BeginEndAlignment:
168
177
  Enabled: true
169
178
 
179
+ Layout/SpaceBeforeBrackets:
180
+ Enabled: true
181
+
170
182
  Lint/NonDeterministicRequireOrder:
171
183
  Enabled: false
172
184
 
@@ -260,6 +272,21 @@ Lint/ToEnumArguments:
260
272
  Lint/UnmodifiedReduceAccumulator:
261
273
  Enabled: true
262
274
 
275
+ Lint/UnexpectedBlockArity:
276
+ Enabled: true
277
+
278
+ Lint/AmbiguousAssignment:
279
+ Enabled: true
280
+
281
+ Lint/DeprecatedConstants:
282
+ Enabled: true
283
+
284
+ Lint/LambdaWithoutLiteralBlock:
285
+ Enabled: true
286
+
287
+ Lint/RedundantDirGlobSort:
288
+ Enabled: true
289
+
263
290
  Performance/AncestorsInclude:
264
291
  Enabled: true
265
292
 
@@ -287,6 +314,18 @@ Performance/StringInclude:
287
314
  Performance/Sum:
288
315
  Enabled: true
289
316
 
317
+ Performance/BlockGivenWithExplicitBlock:
318
+ Enabled: true
319
+
320
+ Performance/CollectionLiteralInLoop:
321
+ Enabled: true
322
+
323
+ Performance/ConstantRegexp:
324
+ Enabled: true
325
+
326
+ Performance/MethodObjectAsBlock:
327
+ Enabled: true
328
+
290
329
  RSpec/ExampleLength:
291
330
  Enabled: false
292
331
 
@@ -2,6 +2,76 @@
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.2.3] - 2020.01.12
6
+
7
+ ### Fixed
8
+
9
+ Removed needless `Timeout.timeout` block in `Truemail::Validate::Smtp::Request#check_port`, replaced `TCPSocket` to `Socket` with native timeout detection. Thanks to [@wikiti](https://github.com/wikiti) for idea, testing on production and clean PR [#127](https://github.com/truemail-rb/truemail/pull/127).
10
+
11
+ ### Changed
12
+
13
+ - Updated `Truemail::Validate::Smtp::Request`
14
+ - Updated gem development dependencies
15
+ - Updated rubocop, reek configs
16
+
17
+ ## [2.2.2] - 2020.12.30
18
+
19
+ ### Changed
20
+
21
+ - Updated gem development dependencies
22
+ - Updated rubocop config
23
+
24
+ ## [2.2.1] - 2020.12.06
25
+
26
+ ### Fixed
27
+
28
+ - Filter out ASCII-8BIT chars for serialized SMTP response errors. Fixed `Encoding::UndefinedConversionError` in `Truemail::Log::Serializer::ValidatorJson#serialize`. Thanks to [@eni9889](https://github.com/eni9889) for report
29
+ - Added missed `smtp_fail_fast` attribute to serialized validator and auditor results
30
+
31
+ ### Added
32
+
33
+ - Added `Truemail::Log::Serializer::ValidatorBase#replace_invalid_chars`
34
+
35
+ ### Changed
36
+
37
+ - Updated `Truemail::Log::Serializer::Base`
38
+ - Updated `Truemail::Log::Serializer::ValidatorBase`
39
+ - Updated gem development dependencies
40
+
41
+ ## [2.2.0] - 2020.12.01
42
+
43
+ Ability to use fail fast behaviour for SMTP validation layer. When `smtp_fail_fast = true` it means that `truemail` ends smtp validation session after first attempt on the first mx server in any fail cases (network connection/timeout error, smtp validation error). This feature helps to reduce total time of SMTP validation session up to 1 second.
44
+
45
+ ### Added
46
+
47
+ - Added `Truemail::Configuration#smtp_fail_fast`
48
+ - Added `Truemail::Validate::Smtp#smtp_fail_fast?`
49
+ - Added `Truemail::Validate::Smtp#filtered_mail_servers_by_fail_fast_scenario`
50
+
51
+ ### Changed
52
+
53
+ - Updated `Truemail::Validate::Smtp#attempts`
54
+ - Updated `Truemail::Validate::Smtp#establish_smtp_connection`
55
+ - Updated gem documentation
56
+
57
+ It's a configurable and not required option:
58
+
59
+ ```ruby
60
+ Truemail.configure do |config|
61
+ config.smtp_fail_fast = true # by default it's equal to false
62
+ end
63
+ ```
64
+
65
+ Thanks to [@wikiti](https://github.com/wikiti) for timeout reports.
66
+
67
+ ## [2.1.0] - 2020.11.21
68
+
69
+ Collecting only unique ip-addresses for target mail servers. This update reduces email validation time for case when remote server have closed connection via avoiding connection attempt to server with the same ip address.
70
+
71
+ ### Changed
72
+
73
+ - Updated `Truemail::Validate::Mx#fetch_target_hosts`
74
+
5
75
  ## [2.0.2] - 2020.11.14
6
76
 
7
77
  ### Fixed
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- truemail (2.0.2)
4
+ truemail (2.2.3)
5
5
  simpleidn (~> 0.1.1)
6
6
 
7
7
  GEM
@@ -15,14 +15,18 @@ GEM
15
15
  childprocess (4.0.0)
16
16
  coderay (1.1.3)
17
17
  colorize (0.8.1)
18
+ concurrent-ruby (1.1.7)
18
19
  diff-lcs (1.4.4)
19
- docile (1.3.2)
20
+ docile (1.3.4)
21
+ faker (2.15.1)
22
+ i18n (>= 1.6, < 2)
20
23
  fasterer (0.8.3)
21
24
  colorize (~> 0.7)
22
25
  ruby_parser (>= 3.14.1)
23
- ffaker (2.17.0)
26
+ i18n (1.8.7)
27
+ concurrent-ruby (~> 1.0)
24
28
  iniparse (1.5.0)
25
- json (2.3.1)
29
+ json (2.5.1)
26
30
  json_matchers (0.11.1)
27
31
  json_schema
28
32
  json_schema (0.20.9)
@@ -31,8 +35,8 @@ GEM
31
35
  overcommit (0.57.0)
32
36
  childprocess (>= 0.6.3, < 5)
33
37
  iniparse (~> 1.4)
34
- parallel (1.20.0)
35
- parser (2.7.2.0)
38
+ parallel (1.20.1)
39
+ parser (3.0.0.0)
36
40
  ast (~> 2.4.1)
37
41
  pry (0.13.1)
38
42
  coderay (~> 1.1)
@@ -40,50 +44,50 @@ GEM
40
44
  pry-byebug (3.9.0)
41
45
  byebug (~> 11.0)
42
46
  pry (~> 0.13.0)
43
- psych (3.2.0)
47
+ psych (3.3.0)
44
48
  rainbow (3.0.0)
45
- rake (13.0.1)
46
- reek (6.0.2)
49
+ rake (13.0.3)
50
+ reek (6.0.3)
47
51
  kwalify (~> 0.7.0)
48
- parser (>= 2.5.0.0, < 2.8, != 2.5.1.1)
52
+ parser (~> 3.0.0)
49
53
  psych (~> 3.1)
50
54
  rainbow (>= 2.0, < 4.0)
51
- regexp_parser (1.8.2)
55
+ regexp_parser (2.0.3)
52
56
  rexml (3.2.4)
53
57
  rspec (3.10.0)
54
58
  rspec-core (~> 3.10.0)
55
59
  rspec-expectations (~> 3.10.0)
56
60
  rspec-mocks (~> 3.10.0)
57
- rspec-core (3.10.0)
61
+ rspec-core (3.10.1)
58
62
  rspec-support (~> 3.10.0)
59
- rspec-expectations (3.10.0)
63
+ rspec-expectations (3.10.1)
60
64
  diff-lcs (>= 1.2.0, < 2.0)
61
65
  rspec-support (~> 3.10.0)
62
- rspec-mocks (3.10.0)
66
+ rspec-mocks (3.10.1)
63
67
  diff-lcs (>= 1.2.0, < 2.0)
64
68
  rspec-support (~> 3.10.0)
65
- rspec-support (3.10.0)
66
- rubocop (1.3.0)
69
+ rspec-support (3.10.1)
70
+ rubocop (1.8.1)
67
71
  parallel (~> 1.10)
68
- parser (>= 2.7.1.5)
72
+ parser (>= 3.0.0.0)
69
73
  rainbow (>= 2.2.2, < 4.0)
70
- regexp_parser (>= 1.8)
74
+ regexp_parser (>= 1.8, < 3.0)
71
75
  rexml
72
- rubocop-ast (>= 1.1.1)
76
+ rubocop-ast (>= 1.2.0, < 2.0)
73
77
  ruby-progressbar (~> 1.7)
74
- unicode-display_width (>= 1.4.0, < 2.0)
75
- rubocop-ast (1.1.1)
78
+ unicode-display_width (>= 1.4.0, < 3.0)
79
+ rubocop-ast (1.4.0)
76
80
  parser (>= 2.7.1.5)
77
- rubocop-performance (1.8.1)
78
- rubocop (>= 0.87.0)
81
+ rubocop-performance (1.9.2)
82
+ rubocop (>= 0.90.0, < 2.0)
79
83
  rubocop-ast (>= 0.4.0)
80
- rubocop-rspec (2.0.0)
84
+ rubocop-rspec (2.1.0)
81
85
  rubocop (~> 1.0)
82
86
  rubocop-ast (>= 1.1.0)
83
- ruby-progressbar (1.10.1)
84
- ruby_parser (3.15.0)
87
+ ruby-progressbar (1.11.0)
88
+ ruby_parser (3.15.1)
85
89
  sexp_processor (~> 4.9)
86
- sexp_processor (4.15.1)
90
+ sexp_processor (4.15.2)
87
91
  simplecov (0.17.1)
88
92
  docile (~> 1.1)
89
93
  json (>= 1.8, < 3)
@@ -92,13 +96,14 @@ GEM
92
96
  simpleidn (0.1.1)
93
97
  unf (~> 0.1.4)
94
98
  thor (1.0.1)
95
- truemail-rspec (0.2.1)
96
- rspec (~> 3.9)
97
- truemail (~> 1.4, >= 1.4.1)
99
+ truemail-rspec (0.3.3)
100
+ faker (~> 2.15, >= 2.15.1)
101
+ rspec (~> 3.10)
102
+ truemail (~> 2.2)
98
103
  unf (0.1.4)
99
104
  unf_ext
100
105
  unf_ext (0.0.7.7)
101
- unicode-display_width (1.7.0)
106
+ unicode-display_width (2.0.0)
102
107
 
103
108
  PLATFORMS
104
109
  ruby
@@ -106,20 +111,20 @@ PLATFORMS
106
111
  DEPENDENCIES
107
112
  bundler (~> 1.16)
108
113
  bundler-audit (~> 0.7.0.1)
114
+ faker (~> 2.15, >= 2.15.1)
109
115
  fasterer (~> 0.8.3)
110
- ffaker (~> 2.17)
111
116
  json_matchers (~> 0.11.1)
112
117
  overcommit (~> 0.57.0)
113
118
  pry-byebug (~> 3.9)
114
- rake (~> 13.0, >= 13.0.1)
115
- reek (~> 6.0, >= 6.0.2)
119
+ rake (~> 13.0, >= 13.0.3)
120
+ reek (~> 6.0, >= 6.0.3)
116
121
  rspec (~> 3.10)
117
- rubocop (~> 1.3)
118
- rubocop-performance (~> 1.8, >= 1.8.1)
119
- rubocop-rspec (~> 2.0)
122
+ rubocop (~> 1.8, >= 1.8.1)
123
+ rubocop-performance (~> 1.9, >= 1.9.2)
124
+ rubocop-rspec (~> 2.1)
120
125
  simplecov (~> 0.17.1)
121
126
  truemail!
122
- truemail-rspec (~> 0.2.1)
127
+ truemail-rspec (~> 0.3.3)
123
128
 
124
129
  BUNDLED WITH
125
130
  1.16.6
data/README.md CHANGED
@@ -40,6 +40,7 @@ Configurable framework agnostic plain Ruby email validator. Verify email via Reg
40
40
  - [RFC MX lookup flow](#rfc-mx-lookup-flow)
41
41
  - [Not RFC MX lookup flow](#not-rfc-mx-lookup-flow)
42
42
  - [SMTP validation](#smtp-validation)
43
+ - [SMTP fail fast enabled](#smtp-fail-fast-enabled)
43
44
  - [SMTP safe check disabled](#smtp-safe-check-disabled)
44
45
  - [SMTP safe check enabled](#smtp-safe-check-enabled)
45
46
  - [Host audit features](#host-audit-features)
@@ -82,10 +83,12 @@ Also Truemail gem allows performing an audit of the host in which runs.
82
83
  - Minimal runtime dependencies
83
84
  - Supporting of internationalized emails ([EAI](https://en.wikipedia.org/wiki/Email_address#Internationalization))
84
85
  - Whitelist/blacklist validation layers
86
+ - Ability to configure different MX/SMTP validation flows
85
87
  - Simple SMTP debugger
86
88
  - Event logger
87
89
  - Host auditor tools (helps to detect common host problems interfering to proper email verification)
88
90
  - JSON serializers
91
+ - Ability to use the library as independent stateless microservice ([Truemail Server](https://truemail-rb.org/truemail-rack))
89
92
 
90
93
  ## Requirements
91
94
 
@@ -129,6 +132,8 @@ You can use global gem configuration or custom independent configuration. Availa
129
132
  - whitelisted domains
130
133
  - whitelist validation
131
134
  - blacklisted domains
135
+ - RFC MX lookup flow
136
+ - SMTP fail fast
132
137
  - SMTP safe check
133
138
  - event logger
134
139
  - JSON serializer
@@ -201,6 +206,13 @@ Truemail.configure do |config|
201
206
  # By default this option is disabled.
202
207
  config.not_rfc_mx_lookup_flow = true
203
208
 
209
+ # Optional parameter. This option will provide to use smtp fail fast behaviour. When
210
+ # smtp_fail_fast = true it means that truemail ends smtp validation session after first
211
+ # attempt on the first mx server in any fail cases (network connection/timeout error,
212
+ # smtp validation error). This feature helps to reduce total time of SMTP validation
213
+ # session up to 1 second. By default this option is disabled.
214
+ config.smtp_fail_fast = true
215
+
204
216
  # Optional parameter. This option will be parse bodies of SMTP errors. It will be helpful
205
217
  # if SMTP server does not return an exact answer that the email does not exist
206
218
  # By default this option is disabled, available for SMTP validation only.
@@ -233,6 +245,7 @@ Truemail.configuration
233
245
  @verifier_domain="somedomain.com",
234
246
  @verifier_email="verifier@example.com",
235
247
  @not_rfc_mx_lookup_flow=true,
248
+ @smtp_fail_fast=true,
236
249
  @smtp_safe_check=true,
237
250
  @logger=#<Truemail::Logger:0x0000557f837450b0
238
251
  @event=:all, @file="/home/app/log/truemail.log", @stdout=true>>
@@ -262,6 +275,7 @@ Truemail.configuration
262
275
  @verifier_domain="somedomain.com",
263
276
  @verifier_email="verifier@example.com",
264
277
  @not_rfc_mx_lookup_flow=true,
278
+ @smtp_fail_fast=true,
265
279
  @smtp_safe_check=true,
266
280
  @logger=#<Truemail::Logger:0x0000557f837450b0
267
281
  @event=:all, @file="/home/app/log/truemail.log", @stdout=true>>
@@ -294,7 +308,6 @@ Truemail.host_audit('email@example.com', custom_configuration: custom_configurat
294
308
 
295
309
  Please note, you should have global or custom configuration for use Truemail gem.
296
310
 
297
-
298
311
  ### Validation features
299
312
 
300
313
  #### Whitelist/Blacklist check
@@ -346,6 +359,7 @@ Truemail.validate('email@white-domain.com')
346
359
  @response_timeout=2,
347
360
  @smtp_error_body_pattern=/(?=.*550)(?=.*(user|account|customer|mailbox)).*/i,
348
361
  @not_rfc_mx_lookup_flow=false,
362
+ @smtp_fail_fast=false,
349
363
  @smtp_safe_check=false,
350
364
  @validation_type_by_domain={"somedomain.com"=>:mx},
351
365
  @verifier_domain="example.com",
@@ -392,6 +406,7 @@ Truemail.validate('email@white-domain.com', with: :regex)
392
406
  @response_timeout=2,
393
407
  @smtp_error_body_pattern=/(?=.*550)(?=.*(user|account|customer|mailbox)).*/i,
394
408
  @not_rfc_mx_lookup_flow=false,
409
+ @smtp_fail_fast=false,
395
410
  @smtp_safe_check=false,
396
411
  @validation_type_by_domain={},
397
412
  @verifier_domain="example.com",
@@ -424,6 +439,7 @@ Truemail.validate('email@domain.com', with: :regex)
424
439
  @response_timeout=2,
425
440
  @smtp_error_body_pattern=/(?=.*550)(?=.*(user|account|customer|mailbox)).*/i,
426
441
  @not_rfc_mx_lookup_flow=false,
442
+ @smtp_fail_fast=false,
427
443
  @smtp_safe_check=false,
428
444
  @validation_type_by_domain={},
429
445
  @verifier_domain="example.com",
@@ -458,6 +474,7 @@ Truemail.validate('email@black-domain.com')
458
474
  @response_timeout=2,
459
475
  @smtp_error_body_pattern=/(?=.*550)(?=.*(user|account|customer|mailbox)).*/i,
460
476
  @not_rfc_mx_lookup_flow=false,
477
+ @smtp_fail_fast=false,
461
478
  @smtp_safe_check=false,
462
479
  @validation_type_by_domain={},
463
480
  @verifier_domain="example.com",
@@ -492,6 +509,7 @@ Truemail.validate('email@somedomain.com')
492
509
  @response_timeout=2,
493
510
  @smtp_error_body_pattern=/(?=.*550)(?=.*(user|account|customer|mailbox)).*/i,
494
511
  @not_rfc_mx_lookup_flow=false,
512
+ @smtp_fail_fast=false,
495
513
  @smtp_safe_check=false,
496
514
  @validation_type_by_domain={},
497
515
  @verifier_domain="example.com",
@@ -542,6 +560,7 @@ Truemail.validate('email@example.com', with: :regex)
542
560
  @response_timeout=2,
543
561
  @smtp_error_body_pattern=/(?=.*550)(?=.*(user|account|customer|mailbox)).*/i,
544
562
  @not_rfc_mx_lookup_flow=false,
563
+ @smtp_fail_fast=false,
545
564
  @smtp_safe_check=false,
546
565
  @validation_type_by_domain={},
547
566
  @verifier_domain="example.com",
@@ -584,6 +603,7 @@ Truemail.validate('email@example.com', with: :regex)
584
603
  @response_timeout=2,
585
604
  @smtp_error_body_pattern=/(?=.*550)(?=.*(user|account|customer|mailbox)).*/i,
586
605
  @not_rfc_mx_lookup_flow=false,
606
+ @smtp_fail_fast=false,
587
607
  @smtp_safe_check=false,
588
608
  @validation_type_by_domain={},
589
609
  @verifier_domain="example.com",
@@ -637,6 +657,7 @@ Truemail.validate('email@example.com', with: :mx)
637
657
  @response_timeout=2,
638
658
  @smtp_error_body_pattern=/(?=.*550)(?=.*(user|account|customer|mailbox)).*/i,
639
659
  @not_rfc_mx_lookup_flow=false,
660
+ @smtp_fail_fast=false,
640
661
  @smtp_safe_check=false,
641
662
  @validation_type_by_domain={},
642
663
  @verifier_domain="example.com",
@@ -681,6 +702,7 @@ Truemail.validate('email@example.com', with: :mx)
681
702
  @response_timeout=2,
682
703
  @smtp_error_body_pattern=/(?=.*550)(?=.*(user|account|customer|mailbox)).*/i,
683
704
  @not_rfc_mx_lookup_flow=true,
705
+ @smtp_fail_fast=false,
684
706
  @smtp_safe_check=false,
685
707
  @validation_type_by_domain={},
686
708
  @verifier_domain="example.com",
@@ -702,6 +724,68 @@ If total count of MX servers is equal to one, `Truemail::Smtp` validator will us
702
724
 
703
725
  By default, you don't need pass with-parameter to use it. Example of usage is specified below:
704
726
 
727
+ ##### SMTP fail fast enabled
728
+
729
+ Truemail can use fail fast behaviour for SMTP validation layer. When `smtp_fail_fast = true` it means that `truemail` ends smtp validation session after first attempt on the first mx server in any fail cases (network connection/timeout error, smtp validation error). This feature helps to reduce total time of SMTP validation session up to 1 second.
730
+
731
+ ```ruby
732
+ require 'truemail'
733
+
734
+ Truemail.configure do |config|
735
+ config.verifier_email = 'verifier@example.com'
736
+ config.smtp_fail_fast = true
737
+ end
738
+
739
+ Truemail.validate('email@example.com')
740
+
741
+ # SMTP validation failed, smtp fail fast validation scenario
742
+ => #<Truemail::Validator:0x00007fdc4504f460
743
+ @result=
744
+ #<struct Truemail::Validator::Result
745
+ success=false,
746
+ email="email@example.com",
747
+ domain="example.com",
748
+ mail_servers=["127.0.1.1", "127.0.1.2", "127.0.1.3"], # there are 3 mail servers in a row
749
+ errors={:smtp=>"smtp error"},
750
+ smtp_debug=
751
+ [#<Truemail::Validate::Smtp::Request:0x00007fdc43150b90 # but iteration has been stopped after the first failure
752
+ @attempts=nil,
753
+ @configuration=
754
+ #<Truemail::Validate::Smtp::Request::Configuration:0x00007fdc43150b18
755
+ @connection_timeout=2,
756
+ @response_timeout=2,
757
+ @verifier_domain="example.com",
758
+ @verifier_email="verifier@example.com">,
759
+ @email="email@example.com",
760
+ @host="127.0.1.1",
761
+ @response=
762
+ #<struct Truemail::Validate::Smtp::Response
763
+ port_opened=false,
764
+ connection=nil,
765
+ helo=nil,
766
+ mailfrom=nil,
767
+ rcptto=nil,
768
+ errors={}>>],
769
+ configuration=
770
+ #<Truemail::Configuration:0x00007fdc4504f5c8
771
+ @blacklisted_domains=[],
772
+ @connection_attempts=2,
773
+ @connection_timeout=2,
774
+ @default_validation_type=:smtp,
775
+ @email_pattern=/(?=\A.{6,255}\z)(\A([\p{L}0-9]+[\w|\-.+]*)@((?i-mx:[\p{L}0-9]+([\-.]{1}[\p{L}0-9]+)*\.\p{L}{2,63}))\z)/,
776
+ @not_rfc_mx_lookup_flow=false,
777
+ @response_timeout=2,
778
+ @smtp_error_body_pattern=/(?=.*550)(?=.*(user|account|customer|mailbox)).*/i,
779
+ @smtp_fail_fast=true,
780
+ @smtp_safe_check=false,
781
+ @validation_type_by_domain={},
782
+ @verifier_domain="example.com",
783
+ @verifier_email="verifier@example.com",
784
+ @whitelist_validation=false,
785
+ @whitelisted_domains=[]>>,
786
+ @validation_type=:smtp>
787
+ ```
788
+
705
789
  ##### SMTP safe check disabled
706
790
 
707
791
  With `smtp_safe_check = false`
@@ -735,6 +819,7 @@ Truemail.validate('email@example.com')
735
819
  @response_timeout=2,
736
820
  @smtp_error_body_pattern=/(?=.*550)(?=.*(user|account|customer|mailbox)).*/i,
737
821
  @not_rfc_mx_lookup_flow=false,
822
+ @smtp_fail_fast=false,
738
823
  @smtp_safe_check=false,
739
824
  @validation_type_by_domain={},
740
825
  @verifier_domain="example.com",
@@ -784,6 +869,7 @@ Truemail.validate('email@example.com')
784
869
  @response_timeout=2,
785
870
  @smtp_error_body_pattern=/(?=.*550)(?=.*(user|account|customer|mailbox)).*/i,
786
871
  @not_rfc_mx_lookup_flow=false,
872
+ @smtp_fail_fast=false,
787
873
  @smtp_safe_check=false,
788
874
  @validation_type_by_domain={},
789
875
  @verifier_domain="example.com",
@@ -845,6 +931,7 @@ Truemail.validate('email@example.com')
845
931
  @response_timeout=2,
846
932
  @smtp_error_body_pattern=/(?=.*550)(?=.*(user|account|customer|mailbox)).*/i,
847
933
  @not_rfc_mx_lookup_flow=false,
934
+ @smtp_fail_fast=false,
848
935
  @smtp_safe_check=false,
849
936
  @validation_type_by_domain={},
850
937
  @verifier_domain="example.com",
@@ -891,6 +978,7 @@ Truemail.validate('email@example.com')
891
978
  @response_timeout=2,
892
979
  @smtp_error_body_pattern=/(?=.*550)(?=.*(user|account|customer|mailbox)).*/i,
893
980
  @not_rfc_mx_lookup_flow=false,
981
+ @smtp_fail_fast=false,
894
982
  @smtp_safe_check=false,
895
983
  @validation_type_by_domain={},
896
984
  @verifier_domain="example.com",
@@ -938,6 +1026,7 @@ Truemail.host_audit
938
1026
  @response_timeout=2,
939
1027
  @smtp_error_body_pattern=/(?=.*550)(?=.*(user|account|customer|mailbox)).*/i,
940
1028
  @not_rfc_mx_lookup_flow=false,
1029
+ @smtp_fail_fast=false,
941
1030
  @smtp_safe_check=false,
942
1031
  @validation_type_by_domain={},
943
1032
  @verifier_domain="example.com",
@@ -964,6 +1053,7 @@ Truemail.host_audit
964
1053
  @response_timeout=2,
965
1054
  @smtp_error_body_pattern=/(?=.*550)(?=.*(user|account|customer|mailbox)).*/i,
966
1055
  @not_rfc_mx_lookup_flow=false,
1056
+ @smtp_fail_fast=false,
967
1057
  @smtp_safe_check=false,
968
1058
  @validation_type_by_domain={},
969
1059
  @verifier_domain="example.com",
@@ -1012,6 +1102,7 @@ Truemail::Log::Serializer::AuditorJson.call(Truemail.host_audit)
1012
1102
  "whitelisted_domains": null,
1013
1103
  "blacklisted_domains": null,
1014
1104
  "not_rfc_mx_lookup_flow": false,
1105
+ "smtp_fail_fast": false,
1015
1106
  "smtp_safe_check": false,
1016
1107
  "email_pattern": "default gem value",
1017
1108
  "smtp_error_body_pattern": "default gem value"
@@ -1050,6 +1141,7 @@ Truemail::Log::Serializer::ValidatorJson.call(Truemail.validate('nonexistent_ema
1050
1141
  "whitelisted_domains": null,
1051
1142
  "blacklisted_domains": null,
1052
1143
  "not_rfc_mx_lookup_flow": false,
1144
+ "smtp_fail_fast": false,
1053
1145
  "smtp_safe_check": false,
1054
1146
  "email_pattern": "default gem value",
1055
1147
  "smtp_error_body_pattern": "default gem value"
@@ -1090,6 +1182,7 @@ Truemail.host_audit.as_json
1090
1182
  "whitelisted_domains": null,
1091
1183
  "blacklisted_domains": null,
1092
1184
  "not_rfc_mx_lookup_flow": false,
1185
+ "smtp_fail_fast": false,
1093
1186
  "smtp_safe_check": false,
1094
1187
  "email_pattern": "default gem value",
1095
1188
  "smtp_error_body_pattern": "default gem value"
@@ -1125,6 +1218,7 @@ Truemail.validate('nonexistent_email@bestweb.com.ua').as_json
1125
1218
  "whitelisted_domains": null,
1126
1219
  "blacklisted_domains": null,
1127
1220
  "not_rfc_mx_lookup_flow": false,
1221
+ "smtp_fail_fast": false,
1128
1222
  "smtp_safe_check": false,
1129
1223
  "email_pattern": "default gem value",
1130
1224
  "smtp_error_body_pattern": "default gem value"
@@ -10,7 +10,7 @@ module Truemail
10
10
  class << self
11
11
  def configuration(&block)
12
12
  @configuration ||= begin
13
- return unless block_given?
13
+ return unless block
14
14
  configuration = Truemail::Configuration.new(&block)
15
15
  raise_unless(configuration.complete?, Truemail::INCOMPLETE_CONFIG)
16
16
  configuration
@@ -21,13 +21,13 @@ module Truemail
21
21
  :blacklisted_domains,
22
22
  :logger
23
23
 
24
- attr_accessor :whitelist_validation, :not_rfc_mx_lookup_flow, :smtp_safe_check
24
+ attr_accessor :whitelist_validation, :not_rfc_mx_lookup_flow, :smtp_fail_fast, :smtp_safe_check
25
25
 
26
26
  def initialize(&block)
27
27
  instance_initializer.each do |instace_variable, value|
28
28
  instance_variable_set(:"@#{instace_variable}", value)
29
29
  end
30
- tap(&block) if block_given?
30
+ tap(&block) if block
31
31
  end
32
32
 
33
33
  %i[email_pattern smtp_error_body_pattern].each do |method|
@@ -102,6 +102,7 @@ module Truemail
102
102
  whitelist_validation: false,
103
103
  blacklisted_domains: [],
104
104
  not_rfc_mx_lookup_flow: false,
105
+ smtp_fail_fast: false,
105
106
  smtp_safe_check: false
106
107
  }
107
108
  end
@@ -56,6 +56,7 @@ module Truemail
56
56
  whitelisted_domains: whitelisted_domains,
57
57
  blacklisted_domains: blacklisted_domains,
58
58
  not_rfc_mx_lookup_flow: executor_configuration.not_rfc_mx_lookup_flow,
59
+ smtp_fail_fast: executor_configuration.smtp_fail_fast,
59
60
  smtp_safe_check: executor_configuration.smtp_safe_check,
60
61
  email_pattern: email_pattern,
61
62
  smtp_error_body_pattern: smtp_error_body_pattern
@@ -13,6 +13,10 @@ module Truemail
13
13
 
14
14
  attr_reader :validation_type
15
15
 
16
+ def replace_invalid_chars
17
+ ->(value) { value.encode('UTF-8', invalid: :replace) }
18
+ end
19
+
16
20
  def smtp_debug
17
21
  validation_smtp_debug = executor_result.smtp_debug
18
22
  return unless validation_smtp_debug
@@ -22,7 +26,7 @@ module Truemail
22
26
  mail_host: smtp_request.host,
23
27
  port_opened: smtp_response.port_opened,
24
28
  connection: smtp_response.connection,
25
- errors: smtp_response.errors
29
+ errors: smtp_response.errors.transform_values(&replace_invalid_chars)
26
30
  }
27
31
  end
28
32
  end
@@ -30,7 +30,7 @@ module Truemail
30
30
  end
31
31
 
32
32
  def fetch_target_hosts(hosts)
33
- mail_servers.push(*hosts)
33
+ mail_servers.push(*(hosts.uniq - mail_servers))
34
34
  end
35
35
 
36
36
  def null_mx?(domain_mx_records)
@@ -24,13 +24,23 @@ module Truemail
24
24
 
25
25
  private
26
26
 
27
- def request
28
- smtp_results.last
27
+ def fail_fast?
28
+ configuration.smtp_fail_fast
29
+ end
30
+
31
+ def filtered_mail_servers_by_fail_fast_scenario
32
+ fail_fast? ? mail_servers.first(1) : mail_servers
29
33
  end
30
34
 
31
35
  def attempts
32
- @attempts ||=
33
- mail_servers.one? ? { attempts: configuration.connection_attempts } : {}
36
+ @attempts ||= begin
37
+ return {} if fail_fast? || !mail_servers.one?
38
+ { attempts: configuration.connection_attempts }
39
+ end
40
+ end
41
+
42
+ def request
43
+ smtp_results.last
34
44
  end
35
45
 
36
46
  def rcptto_error
@@ -38,7 +48,7 @@ module Truemail
38
48
  end
39
49
 
40
50
  def establish_smtp_connection
41
- mail_servers.each do |mail_server|
51
+ filtered_mail_servers_by_fail_fast_scenario.each do |mail_server|
42
52
  smtp_results << Truemail::Validate::Smtp::Request.new(
43
53
  configuration: configuration, host: mail_server, email: result.punycode_email, **attempts
44
54
  )
@@ -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
- Timeout.timeout(configuration.connection_timeout) do
26
- return response.port_opened = !TCPSocket.new(host, Truemail::Validate::Smtp::Request::SMTP_PORT).close
27
- end
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?(Timeout::Error)
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Truemail
4
- VERSION = '2.0.2'
4
+ VERSION = '2.2.3'
5
5
  end
@@ -35,17 +35,17 @@ Gem::Specification.new do |spec|
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 'faker', '~> 2.15', '>= 2.15.1'
38
39
  spec.add_development_dependency 'fasterer', '~> 0.8.3'
39
- spec.add_development_dependency 'ffaker', '~> 2.17'
40
40
  spec.add_development_dependency 'json_matchers', '~> 0.11.1'
41
41
  spec.add_development_dependency 'overcommit', '~> 0.57.0'
42
42
  spec.add_development_dependency 'pry-byebug', '~> 3.9'
43
- spec.add_development_dependency 'rake', '~> 13.0', '>= 13.0.1'
44
- spec.add_development_dependency 'reek', '~> 6.0', '>= 6.0.2'
43
+ spec.add_development_dependency 'rake', '~> 13.0', '>= 13.0.3'
44
+ spec.add_development_dependency 'reek', '~> 6.0', '>= 6.0.3'
45
45
  spec.add_development_dependency 'rspec', '~> 3.10'
46
- spec.add_development_dependency 'rubocop', '~> 1.3'
47
- spec.add_development_dependency 'rubocop-performance', '~> 1.8', '>= 1.8.1'
48
- spec.add_development_dependency 'rubocop-rspec', '~> 2.0'
46
+ spec.add_development_dependency 'rubocop', '~> 1.8', '>= 1.8.1'
47
+ spec.add_development_dependency 'rubocop-performance', '~> 1.9', '>= 1.9.2'
48
+ spec.add_development_dependency 'rubocop-rspec', '~> 2.1'
49
49
  spec.add_development_dependency 'simplecov', '~> 0.17.1'
50
- spec.add_development_dependency 'truemail-rspec', '~> 0.2.1'
50
+ spec.add_development_dependency 'truemail-rspec', '~> 0.3.3'
51
51
  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.0.2
4
+ version: 2.2.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: 2020-11-14 00:00:00.000000000 Z
11
+ date: 2021-01-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: simpleidn
@@ -53,33 +53,39 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: 0.7.0.1
55
55
  - !ruby/object:Gem::Dependency
56
- name: fasterer
56
+ name: faker
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: 0.8.3
61
+ version: '2.15'
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: 2.15.1
62
65
  type: :development
63
66
  prerelease: false
64
67
  version_requirements: !ruby/object:Gem::Requirement
65
68
  requirements:
66
69
  - - "~>"
67
70
  - !ruby/object:Gem::Version
68
- version: 0.8.3
71
+ version: '2.15'
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: 2.15.1
69
75
  - !ruby/object:Gem::Dependency
70
- name: ffaker
76
+ name: fasterer
71
77
  requirement: !ruby/object:Gem::Requirement
72
78
  requirements:
73
79
  - - "~>"
74
80
  - !ruby/object:Gem::Version
75
- version: '2.17'
81
+ version: 0.8.3
76
82
  type: :development
77
83
  prerelease: false
78
84
  version_requirements: !ruby/object:Gem::Requirement
79
85
  requirements:
80
86
  - - "~>"
81
87
  - !ruby/object:Gem::Version
82
- version: '2.17'
88
+ version: 0.8.3
83
89
  - !ruby/object:Gem::Dependency
84
90
  name: json_matchers
85
91
  requirement: !ruby/object:Gem::Requirement
@@ -131,7 +137,7 @@ dependencies:
131
137
  version: '13.0'
132
138
  - - ">="
133
139
  - !ruby/object:Gem::Version
134
- version: 13.0.1
140
+ version: 13.0.3
135
141
  type: :development
136
142
  prerelease: false
137
143
  version_requirements: !ruby/object:Gem::Requirement
@@ -141,7 +147,7 @@ dependencies:
141
147
  version: '13.0'
142
148
  - - ">="
143
149
  - !ruby/object:Gem::Version
144
- version: 13.0.1
150
+ version: 13.0.3
145
151
  - !ruby/object:Gem::Dependency
146
152
  name: reek
147
153
  requirement: !ruby/object:Gem::Requirement
@@ -151,7 +157,7 @@ dependencies:
151
157
  version: '6.0'
152
158
  - - ">="
153
159
  - !ruby/object:Gem::Version
154
- version: 6.0.2
160
+ version: 6.0.3
155
161
  type: :development
156
162
  prerelease: false
157
163
  version_requirements: !ruby/object:Gem::Requirement
@@ -161,7 +167,7 @@ dependencies:
161
167
  version: '6.0'
162
168
  - - ">="
163
169
  - !ruby/object:Gem::Version
164
- version: 6.0.2
170
+ version: 6.0.3
165
171
  - !ruby/object:Gem::Dependency
166
172
  name: rspec
167
173
  requirement: !ruby/object:Gem::Requirement
@@ -182,48 +188,54 @@ dependencies:
182
188
  requirements:
183
189
  - - "~>"
184
190
  - !ruby/object:Gem::Version
185
- version: '1.3'
191
+ version: '1.8'
192
+ - - ">="
193
+ - !ruby/object:Gem::Version
194
+ version: 1.8.1
186
195
  type: :development
187
196
  prerelease: false
188
197
  version_requirements: !ruby/object:Gem::Requirement
189
198
  requirements:
190
199
  - - "~>"
191
200
  - !ruby/object:Gem::Version
192
- version: '1.3'
201
+ version: '1.8'
202
+ - - ">="
203
+ - !ruby/object:Gem::Version
204
+ version: 1.8.1
193
205
  - !ruby/object:Gem::Dependency
194
206
  name: rubocop-performance
195
207
  requirement: !ruby/object:Gem::Requirement
196
208
  requirements:
197
209
  - - "~>"
198
210
  - !ruby/object:Gem::Version
199
- version: '1.8'
211
+ version: '1.9'
200
212
  - - ">="
201
213
  - !ruby/object:Gem::Version
202
- version: 1.8.1
214
+ version: 1.9.2
203
215
  type: :development
204
216
  prerelease: false
205
217
  version_requirements: !ruby/object:Gem::Requirement
206
218
  requirements:
207
219
  - - "~>"
208
220
  - !ruby/object:Gem::Version
209
- version: '1.8'
221
+ version: '1.9'
210
222
  - - ">="
211
223
  - !ruby/object:Gem::Version
212
- version: 1.8.1
224
+ version: 1.9.2
213
225
  - !ruby/object:Gem::Dependency
214
226
  name: rubocop-rspec
215
227
  requirement: !ruby/object:Gem::Requirement
216
228
  requirements:
217
229
  - - "~>"
218
230
  - !ruby/object:Gem::Version
219
- version: '2.0'
231
+ version: '2.1'
220
232
  type: :development
221
233
  prerelease: false
222
234
  version_requirements: !ruby/object:Gem::Requirement
223
235
  requirements:
224
236
  - - "~>"
225
237
  - !ruby/object:Gem::Version
226
- version: '2.0'
238
+ version: '2.1'
227
239
  - !ruby/object:Gem::Dependency
228
240
  name: simplecov
229
241
  requirement: !ruby/object:Gem::Requirement
@@ -244,14 +256,14 @@ dependencies:
244
256
  requirements:
245
257
  - - "~>"
246
258
  - !ruby/object:Gem::Version
247
- version: 0.2.1
259
+ version: 0.3.3
248
260
  type: :development
249
261
  prerelease: false
250
262
  version_requirements: !ruby/object:Gem::Requirement
251
263
  requirements:
252
264
  - - "~>"
253
265
  - !ruby/object:Gem::Version
254
- version: 0.2.1
266
+ version: 0.3.3
255
267
  description: Configurable framework agnostic plain Ruby email validator. Verify email
256
268
  via Regex, DNS and SMTP.
257
269
  email: