truemail 2.3.4 → 2.4.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: 9a738f1fd2c236927014ba6a2303921ae8a90f33866bc4bc58e95fd8c8061e71
4
- data.tar.gz: 43c708aa1253358616601ffce03a9ba743eb44ba428d47c67b02ea13712dea26
3
+ metadata.gz: 93c31449fbc6da2f25c4ded78c2a976e67f71e2b7112aac70db27bf6e1b75f20
4
+ data.tar.gz: 53599be276e8b72ff3f338c2991c7a10bbdd0c5876e506c40f0965e06941f8c8
5
5
  SHA512:
6
- metadata.gz: f9546a0c5c6db1e8653536f084e746bd98d48454c9b8ff7c05a23c2551315b500ed2d6be55d050f4f5ba4d1794107330453dd6b5a346e3a20feb432aeb47d5e3
7
- data.tar.gz: 5b955a25e540ef7330360e8b8b8ce65b02eea78af89d6f1f288c9db2e83122ea7894f33df1772e126107a63911e7cca20dd671ba22c2c1db9f519da50b2855c1
6
+ metadata.gz: fc0e3012563e61ee123486a4aa2b27e2b81da60668eccef8ed5d998ca82884f6365cc25c9cabe1cf6ef444eecc4663435b661b7de6b4100dcc5e83dbe65868cb
7
+ data.tar.gz: 4a27edc3f01d46eb948f172eeb95bcabe5f47a10eb770f8e0f2769454bb94fe8b30f55ec9a19f388592cf70cfd36f224343a879f02ab7b67c13db97b2a3329a2
data/.codeclimate.yml CHANGED
@@ -7,7 +7,7 @@ checks:
7
7
  plugins:
8
8
  rubocop:
9
9
  enabled: true
10
- channel: rubocop-1-12
10
+ channel: rubocop-1-13
11
11
 
12
12
  reek:
13
13
  enabled: true
data/.reek.yml CHANGED
@@ -34,18 +34,19 @@ detectors:
34
34
 
35
35
  UtilityFunction:
36
36
  exclude:
37
- - Truemail::Validate::Smtp::Request#compose_from
38
- - Truemail::Validator#select_validation_type
39
- - Truemail::Validate::Base#configuration
40
- - Truemail::Validate::Mx#null_mx?
41
- - Truemail::Validate::Mx#a_record
42
37
  - Truemail::Audit::Base#verifier_domain
43
- - Truemail::Configuration#domain_matcher
44
38
  - Truemail::Configuration#logger_options
39
+ - Truemail::Configuration#match_regex?
40
+ - Truemail::Configuration#regex_by_method
41
+ - Truemail::Dns::Worker#nameserver_port
45
42
  - Truemail::Log::Serializer::Base#errors
46
43
  - Truemail::Log::Serializer::ValidatorBase#replace_invalid_chars
47
- - Truemail::Dns::Worker#nameserver_port
48
- - Truemail::Configuration#check_dns_settings
44
+ - Truemail::Validator#select_validation_type
45
+ - Truemail::Validator#constantize
46
+ - Truemail::Validate::Base#configuration
47
+ - Truemail::Validate::Mx#null_mx?
48
+ - Truemail::Validate::Mx#a_record
49
+ - Truemail::Validate::Smtp::Request#compose_from
49
50
 
50
51
  ControlParameter:
51
52
  exclude:
data/.rubocop.yml CHANGED
@@ -356,6 +356,9 @@ Performance/RedundantEqualityComparisonBlock:
356
356
  Performance/RedundantSplitRegexpArgument:
357
357
  Enabled: true
358
358
 
359
+ Performance/MapCompact:
360
+ Enabled: true
361
+
359
362
  RSpec/ExampleLength:
360
363
  Enabled: false
361
364
 
data/CHANGELOG.md CHANGED
@@ -2,6 +2,35 @@
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.4.0] - 2021.04.28
6
+
7
+ ### Added
8
+
9
+ - Implemented `MxBlacklist` validation. This layer provides checking mail servers with predefined blacklisted IP addresses list and can be used as a part of DEA ([disposable email address](https://en.wikipedia.org/wiki/Disposable_email_address)) validations.
10
+
11
+ ```ruby
12
+ Truemail.configure do |config|
13
+ # Optional parameter. With this option Truemail will filter out unwanted mx servers via
14
+ # predefined list of ip addresses. It can be used as a part of DEA (disposable email
15
+ # address) validations. It is equal to empty array by default.
16
+ config.blacklisted_mx_ip_addresses = ['1.1.1.1', '2.2.2.2']
17
+ end
18
+
19
+ ```
20
+
21
+ - Added `Truemail::Validate::MxBlacklist`, tests
22
+
23
+ ### Changed
24
+
25
+ - Updated `Truemail::Core`, tests
26
+ - Updated `Truemail::Configuration`, tests
27
+ - Updated `Truemail::Validator`
28
+ - Updated `Truemail::Validate::Smtp`, tests
29
+ - Updated `Truemail::Log::Serializer::Base`, dependent tests
30
+ - Updated `Truemail::Log::Serializer::ValidatorText`, tests
31
+ - Updated gem development dependencies
32
+ - Updated gem documentation, changelog, version
33
+
5
34
  ## [2.3.4] - 2021.04.16
6
35
 
7
36
  ### Fixed
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- truemail (2.3.4)
4
+ truemail (2.4.0)
5
5
  simpleidn (~> 0.2.1)
6
6
 
7
7
  GEM
@@ -54,7 +54,7 @@ GEM
54
54
  public_suffix (4.0.6)
55
55
  rainbow (3.0.0)
56
56
  rake (13.0.3)
57
- reek (6.0.3)
57
+ reek (6.0.4)
58
58
  kwalify (~> 0.7.0)
59
59
  parser (~> 3.0.0)
60
60
  psych (~> 3.1)
@@ -74,7 +74,7 @@ GEM
74
74
  diff-lcs (>= 1.2.0, < 2.0)
75
75
  rspec-support (~> 3.10.0)
76
76
  rspec-support (3.10.2)
77
- rubocop (1.12.1)
77
+ rubocop (1.13.0)
78
78
  parallel (~> 1.10)
79
79
  parser (>= 3.0.0.0)
80
80
  rainbow (>= 2.2.2, < 4.0)
@@ -85,10 +85,10 @@ GEM
85
85
  unicode-display_width (>= 1.4.0, < 3.0)
86
86
  rubocop-ast (1.4.1)
87
87
  parser (>= 2.7.1.5)
88
- rubocop-performance (1.10.2)
89
- rubocop (>= 0.90.0, < 2.0)
88
+ rubocop-performance (1.11.0)
89
+ rubocop (>= 1.7.0, < 2.0)
90
90
  rubocop-ast (>= 0.4.0)
91
- rubocop-rspec (2.2.0)
91
+ rubocop-rspec (2.3.0)
92
92
  rubocop (~> 1.0)
93
93
  rubocop-ast (>= 1.1.0)
94
94
  ruby-progressbar (1.11.0)
@@ -129,11 +129,11 @@ DEPENDENCIES
129
129
  overcommit (~> 0.57.0)
130
130
  pry-byebug (~> 3.9)
131
131
  rake (~> 13.0, >= 13.0.3)
132
- reek (~> 6.0, >= 6.0.3)
132
+ reek (~> 6.0, >= 6.0.4)
133
133
  rspec (~> 3.10)
134
- rubocop (~> 1.12, >= 1.12.1)
135
- rubocop-performance (~> 1.10, >= 1.10.2)
136
- rubocop-rspec (~> 2.2)
134
+ rubocop (~> 1.13)
135
+ rubocop-performance (~> 1.11)
136
+ rubocop-rspec (~> 2.3)
137
137
  simplecov (~> 0.17.1)
138
138
  truemail!
139
139
  truemail-rspec (~> 0.4)
data/README.md CHANGED
@@ -39,6 +39,7 @@ Configurable framework agnostic plain Ruby email validator. Verify email via Reg
39
39
  - [DNS (MX) validation](#mx-validation)
40
40
  - [RFC MX lookup flow](#rfc-mx-lookup-flow)
41
41
  - [Not RFC MX lookup flow](#not-rfc-mx-lookup-flow)
42
+ - [MX blacklist validation](#mx-blacklist-validation)
42
43
  - [SMTP validation](#smtp-validation)
43
44
  - [SMTP fail fast enabled](#smtp-fail-fast-enabled)
44
45
  - [SMTP safe check disabled](#smtp-safe-check-disabled)
@@ -132,6 +133,7 @@ You can use global gem configuration or custom independent configuration. Availa
132
133
  - whitelisted domains
133
134
  - whitelist validation
134
135
  - blacklisted domains
136
+ - blacklisted mx ip-addresses
135
137
  - custom DNS gateway(s)
136
138
  - RFC MX lookup flow
137
139
  - SMTP fail fast
@@ -200,7 +202,12 @@ Truemail.configure do |config|
200
202
  # Optional parameter. Validation of email which contains blacklisted domain always will
201
203
  # return false. Other validations will not processed even if it was defined in validation_type_for
202
204
  # It is equal to empty array by default.
203
- config.blacklisted_domains = ['somedomain1.com', 'somedomain2.com']
205
+ config.blacklisted_domains = ['somedomain3.com', 'somedomain4.com']
206
+
207
+ # Optional parameter. With this option Truemail will filter out unwanted mx servers via
208
+ # predefined list of ip addresses. It can be used as a part of DEA (disposable email
209
+ # address) validations. It is equal to empty array by default.
210
+ config.blacklisted_mx_ip_addresses = ['1.1.1.1', '2.2.2.2']
204
211
 
205
212
  # Optional parameter. This option will provide to use custom DNS gateway when Truemail
206
213
  # interacts with DNS. Valid port numbers are in the range 1-65535. If you won't specify
@@ -245,11 +252,13 @@ Truemail.configuration
245
252
  @smtp_error_body_pattern=/regex_pattern/,
246
253
  @response_timeout=1,
247
254
  @connection_attempts=3,
248
- @validation_type_by_domain={},
249
- @whitelisted_domains=[],
255
+ @default_validation_type=:mx,
256
+ @validation_type_by_domain={"somedomain.com" => :regex, "otherdomain.com" => :mx},
257
+ @whitelisted_domains=["somedomain1.com", "somedomain2.com"],
250
258
  @whitelist_validation=true,
251
- @blacklisted_domains=[],
252
- @dns=[],
259
+ @blacklisted_domains=["somedomain3.com", "somedomain4.com"],
260
+ @blacklisted_mx_ip_addresses=["1.1.1.1", "2.2.2.2"],
261
+ @dns=["10.0.0.1", "10.0.0.2:54"],
253
262
  @verifier_domain="somedomain.com",
254
263
  @verifier_email="verifier@example.com",
255
264
  @not_rfc_mx_lookup_flow=true,
@@ -276,11 +285,13 @@ Truemail.configuration
276
285
  @smtp_error_body_pattern=/regex_pattern/,
277
286
  @response_timeout=4,
278
287
  @connection_attempts=1,
279
- @validation_type_by_domain={},
280
- @whitelisted_domains=[],
288
+ @default_validation_type=:mx,
289
+ @validation_type_by_domain={"somedomain.com" => :regex, "otherdomain.com" => :mx},
290
+ @whitelisted_domains=["somedomain1.com", "somedomain2.com"],
281
291
  @whitelist_validation=true,
282
- @blacklisted_domains=[],
283
- @dns=[],
292
+ @blacklisted_domains=["somedomain3.com", "somedomain4.com"],
293
+ @blacklisted_mx_ip_addresses=["1.1.1.1", "2.2.2.2"],
294
+ @dns=["10.0.0.1", "10.0.0.2:54"],
284
295
  @verifier_domain="somedomain.com",
285
296
  @verifier_email="verifier@example.com",
286
297
  @not_rfc_mx_lookup_flow=true,
@@ -361,6 +372,7 @@ Truemail.validate('email@white-domain.com')
361
372
  smtp_debug=nil>,
362
373
  configuration=#<Truemail::Configuration:0x00005629f801bd28
363
374
  @blacklisted_domains=["black-domain.com", "somedomain.com"],
375
+ @blacklisted_mx_ip_addresses=[],
364
376
  @dns=[],
365
377
  @connection_attempts=2,
366
378
  @connection_timeout=2,
@@ -409,6 +421,7 @@ Truemail.validate('email@white-domain.com', with: :regex)
409
421
  configuration=
410
422
  #<Truemail::Configuration:0x0000563f0d2605c8
411
423
  @blacklisted_domains=[],
424
+ @blacklisted_mx_ip_addresses=[],
412
425
  @dns=[],
413
426
  @connection_attempts=2,
414
427
  @connection_timeout=2,
@@ -443,6 +456,7 @@ Truemail.validate('email@domain.com', with: :regex)
443
456
  configuration=
444
457
  #<Truemail::Configuration:0x0000563f0cd82ab0
445
458
  @blacklisted_domains=[],
459
+ @blacklisted_mx_ip_addresses=[],
446
460
  @dns=[],
447
461
  @connection_attempts=2,
448
462
  @connection_timeout=2,
@@ -463,7 +477,7 @@ Truemail.validate('email@domain.com', with: :regex)
463
477
 
464
478
  ##### Blacklist case
465
479
 
466
- When email in blacklist, validation type will be redefined too. Validation result returns ```false```
480
+ When email in blacklist, validation type will be redefined too. Validation result returns `false`
467
481
 
468
482
  ```ruby
469
483
  Truemail.validate('email@black-domain.com')
@@ -479,6 +493,7 @@ Truemail.validate('email@black-domain.com')
479
493
  configuration=
480
494
  #<Truemail::Configuration:0x0000563f0d36f4f0
481
495
  @blacklisted_domains=[],
496
+ @blacklisted_mx_ip_addresses=[],
482
497
  @dns=[],
483
498
  @connection_attempts=2,
484
499
  @connection_timeout=2,
@@ -515,6 +530,7 @@ Truemail.validate('email@somedomain.com')
515
530
  configuration=
516
531
  #<Truemail::Configuration:0x0000563f0d3f8fc0
517
532
  @blacklisted_domains=[],
533
+ @blacklisted_mx_ip_addresses=[],
518
534
  @dns=[],
519
535
  @connection_attempts=2,
520
536
  @connection_timeout=2,
@@ -567,6 +583,7 @@ Truemail.validate('email@example.com', with: :regex)
567
583
  configuration=
568
584
  #<Truemail::Configuration:0x000055aa56a54d48
569
585
  @blacklisted_domains=[],
586
+ @blacklisted_mx_ip_addresses=[],
570
587
  @dns=[],
571
588
  @connection_attempts=2,
572
589
  @connection_timeout=2,
@@ -611,6 +628,7 @@ Truemail.validate('email@example.com', with: :regex)
611
628
  configuration=
612
629
  #<Truemail::Configuration:0x0000560e58d80830
613
630
  @blacklisted_domains=[],
631
+ @blacklisted_mx_ip_addresses=[],
614
632
  @dns=[],
615
633
  @connection_attempts=2,
616
634
  @connection_timeout=2,
@@ -666,6 +684,7 @@ Truemail.validate('email@example.com', with: :mx)
666
684
  configuration=
667
685
  #<Truemail::Configuration:0x0000559b6e44af70
668
686
  @blacklisted_domains=[],
687
+ @blacklisted_mx_ip_addresses=[],
669
688
  @dns=[],
670
689
  @connection_attempts=2,
671
690
  @connection_timeout=2,
@@ -712,6 +731,7 @@ Truemail.validate('email@example.com', with: :mx)
712
731
  configuration=
713
732
  #<Truemail::Configuration:0x0000559b6e44af70
714
733
  @blacklisted_domains=[],
734
+ @blacklisted_mx_ip_addresses=[],
715
735
  @dns=[],
716
736
  @connection_attempts=2,
717
737
  @connection_timeout=2,
@@ -730,12 +750,63 @@ Truemail.validate('email@example.com', with: :mx)
730
750
  @validation_type=:mx>
731
751
  ```
732
752
 
753
+ #### MX blacklist validation
754
+
755
+ MX blacklist validation is the third validation level. This layer provides checking extracted mail server(s) IP address from MX validation with predefined blacklisted IP addresses list. It can be used as a part of DEA ([disposable email address](https://en.wikipedia.org/wiki/Disposable_email_address)) validations.
756
+
757
+ ```code
758
+ [Whitelist/Blacklist] -> [Regex validation] -> [MX validation] -> [MX blacklist validation]
759
+ ```
760
+
761
+ Example of usage:
762
+
763
+ ```ruby
764
+ require 'truemail'
765
+
766
+ Truemail.configure do |config|
767
+ config.verifier_email = 'verifier@example.com'
768
+ config.blacklisted_mx_ip_addresses = ['127.0.1.2']
769
+ end
770
+
771
+ Truemail.validate('email@example.com', with: :mx_blacklist)
772
+
773
+ => #<Truemail::Validator:0x00007fca0c8aea70
774
+ @result=
775
+ #<struct Truemail::Validator::Result
776
+ success=false,
777
+ email="email@example.com",
778
+ domain="example.com",
779
+ mail_servers=["127.0.1.1", "127.0.1.2"],
780
+ errors={:mx_blacklist=>"blacklisted mx server ip address"},
781
+ smtp_debug=nil,
782
+ configuration=
783
+ #<Truemail::Configuration:0x00007fca0c8aeb38
784
+ @blacklisted_domains=[],
785
+ @blacklisted_mx_ip_addresses=["127.0.1.2"],
786
+ @connection_attempts=2,
787
+ @connection_timeout=2,
788
+ @default_validation_type=:smtp,
789
+ @dns=[],
790
+ @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)/,
791
+ @not_rfc_mx_lookup_flow=false,
792
+ @response_timeout=2,
793
+ @smtp_error_body_pattern=/(?=.*550)(?=.*(user|account|customer|mailbox)).*/i,
794
+ @smtp_fail_fast=false,
795
+ @smtp_safe_check=false,
796
+ @validation_type_by_domain={},
797
+ @verifier_domain="example.com",
798
+ @verifier_email="verifier@example.com",
799
+ @whitelist_validation=false,
800
+ @whitelisted_domains=[]>>,
801
+ @validation_type=:mx_blacklist>
802
+ ```
803
+
733
804
  #### SMTP validation
734
805
 
735
- SMTP validation is a final, third validation level. This type of validation tries to check real existence of email account on a current email server. This validation runs a chain of previous validations and if they're complete successfully then runs itself.
806
+ SMTP validation is a final, fourth validation level. This type of validation tries to check real existence of email account on a current email server. This validation runs a chain of previous validations and if they're complete successfully then runs itself.
736
807
 
737
808
  ```code
738
- [Whitelist/Blacklist] -> [Regex validation] -> [MX validation] -> [SMTP validation]
809
+ [Whitelist/Blacklist] -> [Regex validation] -> [MX validation] -> [MX blacklist validation] -> [SMTP validation]
739
810
  ```
740
811
 
741
812
  If total count of MX servers is equal to one, `Truemail::Smtp` validator will use value from `Truemail.configuration.connection_attempts` as connection attempts. By default it's equal `2`.
@@ -787,6 +858,7 @@ Truemail.validate('email@example.com')
787
858
  configuration=
788
859
  #<Truemail::Configuration:0x00007fdc4504f5c8
789
860
  @blacklisted_domains=[],
861
+ @blacklisted_mx_ip_addresses=[],
790
862
  @dns=[],
791
863
  @connection_attempts=2,
792
864
  @connection_timeout=2,
@@ -831,6 +903,7 @@ Truemail.validate('email@example.com')
831
903
  configuration=
832
904
  #<Truemail::Configuration:0x00005615e87b9298
833
905
  @blacklisted_domains=[],
906
+ @blacklisted_mx_ip_addresses=[],
834
907
  @dns=[],
835
908
  @connection_attempts=2,
836
909
  @connection_timeout=2,
@@ -882,6 +955,7 @@ Truemail.validate('email@example.com')
882
955
  configuration=
883
956
  #<Truemail::Configuration:0x00005615e87b9298
884
957
  @blacklisted_domains=[],
958
+ @blacklisted_mx_ip_addresses=[],
885
959
  @dns=[],
886
960
  @connection_attempts=2,
887
961
  @connection_timeout=2,
@@ -945,6 +1019,7 @@ Truemail.validate('email@example.com')
945
1019
  configuration=
946
1020
  #<Truemail::Configuration:0x00005615e87b9298
947
1021
  @blacklisted_domains=[],
1022
+ @blacklisted_mx_ip_addresses=[],
948
1023
  @dns=[],
949
1024
  @connection_attempts=2,
950
1025
  @connection_timeout=2,
@@ -993,6 +1068,7 @@ Truemail.validate('email@example.com')
993
1068
  configuration=
994
1069
  #<Truemail::Configuration:0x00005615e87b9298
995
1070
  @blacklisted_domains=[],
1071
+ @blacklisted_mx_ip_addresses=[],
996
1072
  @dns=[],
997
1073
  @connection_attempts=2,
998
1074
  @connection_timeout=2,
@@ -1042,6 +1118,7 @@ Truemail.host_audit
1042
1118
  configuration=
1043
1119
  #<Truemail::Configuration:0x00005615e86327a8
1044
1120
  @blacklisted_domains=[],
1121
+ @blacklisted_mx_ip_addresses=[],
1045
1122
  @dns=[],
1046
1123
  @connection_attempts=2,
1047
1124
  @connection_timeout=2,
@@ -1070,6 +1147,7 @@ Truemail.host_audit
1070
1147
  configuration=
1071
1148
  #<Truemail::Configuration:0x00005615e86327a8
1072
1149
  @blacklisted_domains=[],
1150
+ @blacklisted_mx_ip_addresses=[],
1073
1151
  @dns=[],
1074
1152
  @connection_attempts=2,
1075
1153
  @connection_timeout=2,
@@ -1123,6 +1201,7 @@ Truemail::Log::Serializer::AuditorJson.call(Truemail.host_audit)
1123
1201
  },
1124
1202
  "configuration": {
1125
1203
  "blacklisted_domains": null,
1204
+ "blacklisted_mx_ip_addresses": null,
1126
1205
  "dns": null,
1127
1206
  "email_pattern": "default gem value",
1128
1207
  "not_rfc_mx_lookup_flow": false,
@@ -1163,6 +1242,7 @@ Truemail::Log::Serializer::ValidatorJson.call(Truemail.validate('nonexistent_ema
1163
1242
  ],
1164
1243
  "configuration": {
1165
1244
  "blacklisted_domains": null,
1245
+ "blacklisted_mx_ip_addresses": null,
1166
1246
  "dns": null,
1167
1247
  "email_pattern": "default gem value",
1168
1248
  "not_rfc_mx_lookup_flow": false,
@@ -1205,6 +1285,7 @@ Truemail.host_audit.as_json
1205
1285
  },
1206
1286
  "configuration": {
1207
1287
  "blacklisted_domains": null,
1288
+ "blacklisted_mx_ip_addresses": null,
1208
1289
  "dns": null,
1209
1290
  "email_pattern": "default gem value",
1210
1291
  "not_rfc_mx_lookup_flow": false,
@@ -1242,6 +1323,7 @@ Truemail.validate('nonexistent_email@bestweb.com.ua').as_json
1242
1323
  ],
1243
1324
  "configuration": {
1244
1325
  "blacklisted_domains": null,
1326
+ "blacklisted_mx_ip_addresses": null,
1245
1327
  "dns": null,
1246
1328
  "email_pattern": "default gem value",
1247
1329
  "not_rfc_mx_lookup_flow": false,
@@ -15,13 +15,14 @@ module Truemail
15
15
  connection_attempts
16
16
  whitelisted_domains
17
17
  blacklisted_domains
18
+ blacklisted_mx_ip_addresses
19
+ dns
18
20
  ].freeze
19
21
 
20
22
  attr_reader :verifier_email,
21
23
  :verifier_domain,
22
24
  :default_validation_type,
23
25
  :validation_type_by_domain,
24
- :dns,
25
26
  :logger,
26
27
  *Truemail::Configuration::SETTERS
27
28
 
@@ -55,9 +56,9 @@ module Truemail
55
56
  validation_type_by_domain.merge!(settings)
56
57
  end
57
58
 
58
- def argument_consistent?(argument)
59
+ def argument_consistent?(method, argument)
59
60
  case argument
60
- when ::Array then check_domain_list(argument)
61
+ when ::Array then items_match_regex?(argument, regex_by_method(method))
61
62
  when ::Integer then argument.positive?
62
63
  when ::Regexp then true
63
64
  end
@@ -65,16 +66,11 @@ module Truemail
65
66
 
66
67
  Truemail::Configuration::SETTERS.each do |method|
67
68
  define_method("#{method}=") do |argument|
68
- raise_unless(argument, __method__, argument_consistent?(argument))
69
+ raise_unless(argument, __method__, argument_consistent?(method, argument))
69
70
  instance_variable_set(:"@#{method}", argument)
70
71
  end
71
72
  end
72
73
 
73
- def dns=(argument)
74
- raise_unless(argument, __method__, argument.is_a?(::Array) && check_dns_settings(argument))
75
- @dns = argument
76
- end
77
-
78
74
  def logger=(options)
79
75
  tracking_event, stdout, log_absolute_path = logger_options(options)
80
76
  valid_event = Truemail::Log::Event::TRACKING_EVENTS.key?(tracking_event)
@@ -104,6 +100,7 @@ module Truemail
104
100
  whitelisted_domains: [],
105
101
  whitelist_validation: false,
106
102
  blacklisted_domains: [],
103
+ blacklisted_mx_ip_addresses: [],
107
104
  dns: [],
108
105
  not_rfc_mx_lookup_flow: false,
109
106
  smtp_fail_fast: false,
@@ -115,25 +112,27 @@ module Truemail
115
112
  raise Truemail::ArgumentError.new(argument_context, argument_name) unless condition
116
113
  end
117
114
 
115
+ def match_regex?(regex_pattern, object)
116
+ regex_pattern.match?(object.to_s)
117
+ end
118
+
118
119
  def validate_arguments(argument, method)
119
- constant = Truemail::RegexConstant.const_get("regex_#{method[/\A.+_(.+)=\z/, 1]}_pattern".upcase)
120
- raise_unless(argument, method, constant.match?(argument.to_s))
120
+ regex_pattern = Truemail::RegexConstant.const_get("regex_#{method[/\A.+_(.+)=\z/, 1]}_pattern".upcase)
121
+ raise_unless(argument, method, match_regex?(regex_pattern, argument))
121
122
  end
122
123
 
123
124
  def default_verifier_domain
124
125
  self.verifier_domain ||= verifier_email[Truemail::RegexConstant::REGEX_EMAIL_PATTERN, 3]
125
126
  end
126
127
 
127
- def domain_matcher
128
- ->(domain) { Truemail::RegexConstant::REGEX_DOMAIN_PATTERN.match?(domain.to_s) }
128
+ def regex_by_method(method)
129
+ return Truemail::RegexConstant::REGEX_IP_ADDRESS_PATTERN if method.eql?(:blacklisted_mx_ip_addresses)
130
+ return Truemail::RegexConstant::REGEX_DNS_SERVER_ADDRESS_PATTERN if method.eql?(:dns)
131
+ Truemail::RegexConstant::REGEX_DOMAIN_PATTERN
129
132
  end
130
133
 
131
- def check_domain(domain)
132
- raise_unless(domain, 'domain', domain_matcher.call(domain))
133
- end
134
-
135
- def check_domain_list(domains)
136
- domains.all?(&domain_matcher)
134
+ def items_match_regex?(items, regex_pattern)
135
+ items.all? { |item| match_regex?(regex_pattern, item) }
137
136
  end
138
137
 
139
138
  def check_validation_type(validation_type)
@@ -143,15 +142,11 @@ module Truemail
143
142
  def validate_validation_type(settings)
144
143
  raise_unless(settings, 'hash with settings', settings.is_a?(::Hash))
145
144
  settings.each do |domain, validation_type|
146
- check_domain(domain)
145
+ raise_unless(domain, 'domain', match_regex?(Truemail::RegexConstant::REGEX_DOMAIN_PATTERN, domain))
147
146
  check_validation_type(validation_type)
148
147
  end
149
148
  end
150
149
 
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
-
155
150
  def logger_options(current_options)
156
151
  Truemail::Configuration::DEFAULT_LOGGER_OPTIONS.merge(current_options).values
157
152
  end
data/lib/truemail/core.rb CHANGED
@@ -24,8 +24,10 @@ module Truemail
24
24
  REGEX_DOMAIN_PATTERN = /(?=\A.{4,255}\z)(\A#{REGEX_DOMAIN}\z)/.freeze
25
25
  REGEX_DOMAIN_FROM_EMAIL = /\A.+@(.+)\z/.freeze
26
26
  REGEX_SMTP_ERROR_BODY_PATTERN = /(?=.*550)(?=.*(user|account|customer|mailbox)).*/i.freeze
27
+ REGEX_IP_ADDRESS = /((1\d|[1-9]|2[0-4])?\d|25[0-5])(\.\g<1>){3}/.freeze
28
+ REGEX_IP_ADDRESS_PATTERN = /\A#{REGEX_IP_ADDRESS}\z/.freeze
27
29
  REGEX_PORT_NUMBER = /6553[0-5]|655[0-2]\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
30
+ REGEX_DNS_SERVER_ADDRESS_PATTERN = /\A#{REGEX_IP_ADDRESS}(:#{REGEX_PORT_NUMBER})?\z/.freeze
29
31
  end
30
32
 
31
33
  module Dns
@@ -46,6 +48,7 @@ module Truemail
46
48
  require_relative '../truemail/validate/domain_list_match'
47
49
  require_relative '../truemail/validate/regex'
48
50
  require_relative '../truemail/validate/mx'
51
+ require_relative '../truemail/validate/mx_blacklist'
49
52
  require_relative '../truemail/validate/smtp'
50
53
  require_relative '../truemail/validate/smtp/response'
51
54
  require_relative '../truemail/validate/smtp/request'
@@ -6,6 +6,14 @@ module Truemail
6
6
  class Base
7
7
  require 'json'
8
8
 
9
+ CONFIGURATION_ARRAY_ATTRS = %i[
10
+ validation_type_by_domain
11
+ whitelisted_domains
12
+ blacklisted_domains
13
+ blacklisted_mx_ip_addresses
14
+ dns
15
+ ].freeze
16
+ CONFIGURATION_REGEX_ATTRS = %i[email_pattern smtp_error_body_pattern].freeze
9
17
  DEFAULT_GEM_VALUE = 'default gem value'
10
18
 
11
19
  def self.call(executor_instance)
@@ -30,7 +38,7 @@ module Truemail
30
38
 
31
39
  alias warnings errors
32
40
 
33
- %i[validation_type_by_domain whitelisted_domains blacklisted_domains dns].each do |method|
41
+ Truemail::Log::Serializer::Base::CONFIGURATION_ARRAY_ATTRS.each do |method|
34
42
  define_method(method) do
35
43
  value = executor_configuration.public_send(method)
36
44
  return if value.empty?
@@ -38,7 +46,7 @@ module Truemail
38
46
  end
39
47
  end
40
48
 
41
- %i[email_pattern smtp_error_body_pattern].each do |method|
49
+ Truemail::Log::Serializer::Base::CONFIGURATION_REGEX_ATTRS.each do |method|
42
50
  define_method(method) do
43
51
  value = executor_configuration.public_send(method)
44
52
  default_pattern = Truemail::RegexConstant.const_get(
@@ -55,6 +63,7 @@ module Truemail
55
63
  whitelist_validation: executor_configuration.whitelist_validation,
56
64
  whitelisted_domains: whitelisted_domains,
57
65
  blacklisted_domains: blacklisted_domains,
66
+ blacklisted_mx_ip_addresses: blacklisted_mx_ip_addresses,
58
67
  dns: dns,
59
68
  not_rfc_mx_lookup_flow: executor_configuration.not_rfc_mx_lookup_flow,
60
69
  smtp_fail_fast: executor_configuration.smtp_fail_fast,
@@ -19,9 +19,9 @@ module Truemail
19
19
  def data_composer(enumerable_object)
20
20
  enumerable_object.inject([]) do |formatted_data, (key, value)|
21
21
  data =
22
- case
23
- when value.is_a?(::Hash) then "\n#{printer(value)}"
24
- when value.is_a?(::Array) then value.join(', ')
22
+ case value
23
+ when ::Hash then "\n#{printer(value)}"
24
+ when ::Array then value.join(', ')
25
25
  else value
26
26
  end
27
27
  formatted_data << "#{key.to_s.tr('_', ' ')}: #{data}".chomp << "\n"
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Truemail
4
+ module Validate
5
+ class MxBlacklist < Truemail::Validate::Base
6
+ ERROR = 'blacklisted mx server ip address'
7
+
8
+ def run
9
+ return false unless Truemail::Validate::Mx.check(result)
10
+ return true if success(mail_servers.none?(&blacklisted_ip?))
11
+ add_error(Truemail::Validate::MxBlacklist::ERROR)
12
+ false
13
+ end
14
+
15
+ private
16
+
17
+ def blacklisted_ip?
18
+ ->(mail_server) { configuration.blacklisted_mx_ip_addresses.include?(mail_server) }
19
+ end
20
+ end
21
+ end
22
+ end
@@ -13,7 +13,7 @@ module Truemail
13
13
  end
14
14
 
15
15
  def run
16
- return false unless Truemail::Validate::Mx.check(result)
16
+ return false unless Truemail::Validate::MxBlacklist.check(result)
17
17
  establish_smtp_connection
18
18
  return true if success(success_response?)
19
19
  result.smtp_debug = smtp_results
@@ -3,7 +3,7 @@
3
3
  module Truemail
4
4
  class Validator < Truemail::Executor
5
5
  RESULT_ATTRS = %i[success email domain mail_servers errors smtp_debug configuration].freeze
6
- VALIDATION_TYPES = %i[regex mx smtp].freeze
6
+ VALIDATION_TYPES = %i[regex mx mx_blacklist smtp].freeze
7
7
 
8
8
  Result = ::Struct.new(*RESULT_ATTRS, keyword_init: true) do
9
9
  def initialize(mail_servers: [], errors: {}, **args)
@@ -27,7 +27,7 @@ module Truemail
27
27
 
28
28
  def run
29
29
  Truemail::Validate::DomainListMatch.check(result)
30
- result_not_changed? ? Truemail::Validate.const_get(validation_type.capitalize).check(result) : update_validation_type
30
+ result_not_changed? ? Truemail::Validate.const_get(constantize(validation_type)).check(result) : update_validation_type
31
31
  logger&.push(self)
32
32
  self
33
33
  end
@@ -43,6 +43,10 @@ module Truemail
43
43
  result.configuration.validation_type_by_domain[domain] || current_validation_type
44
44
  end
45
45
 
46
+ def constantize(symbol)
47
+ symbol.capitalize.to_s.gsub(/_[a-z]/, &:upcase).tr('_', '').to_sym
48
+ end
49
+
46
50
  def update_validation_type
47
51
  @validation_type = result.success ? :whitelist : :blacklist
48
52
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Truemail
4
- VERSION = '2.3.4'
4
+ VERSION = '2.4.0'
5
5
  end
data/truemail.gemspec CHANGED
@@ -11,7 +11,7 @@ Gem::Specification.new do |spec|
11
11
  spec.email = ['admin@bestweb.com.ua']
12
12
 
13
13
  spec.summary = %(truemail)
14
- spec.description = %(Configurable framework agnostic plain Ruby email validator. Verify email via Regex, DNS and SMTP.)
14
+ spec.description = %(Configurable framework agnostic plain Ruby email validator. Verify email via Regex, DNS, SMTP and even more.)
15
15
 
16
16
  spec.homepage = 'https://github.com/truemail-rb/truemail'
17
17
  spec.license = 'MIT'
@@ -42,11 +42,11 @@ Gem::Specification.new do |spec|
42
42
  spec.add_development_dependency 'overcommit', '~> 0.57.0'
43
43
  spec.add_development_dependency 'pry-byebug', '~> 3.9'
44
44
  spec.add_development_dependency 'rake', '~> 13.0', '>= 13.0.3'
45
- spec.add_development_dependency 'reek', '~> 6.0', '>= 6.0.3'
45
+ spec.add_development_dependency 'reek', '~> 6.0', '>= 6.0.4'
46
46
  spec.add_development_dependency 'rspec', '~> 3.10'
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'
47
+ spec.add_development_dependency 'rubocop', '~> 1.13'
48
+ spec.add_development_dependency 'rubocop-performance', '~> 1.11'
49
+ spec.add_development_dependency 'rubocop-rspec', '~> 2.3'
50
50
  spec.add_development_dependency 'simplecov', '~> 0.17.1'
51
51
  spec.add_development_dependency 'truemail-rspec', '~> 0.4'
52
52
  spec.add_development_dependency 'webmock', '~> 3.12', '>= 3.12.2'
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.3.4
4
+ version: 2.4.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-04-16 00:00:00.000000000 Z
11
+ date: 2021-04-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: simpleidn
@@ -171,7 +171,7 @@ dependencies:
171
171
  version: '6.0'
172
172
  - - ">="
173
173
  - !ruby/object:Gem::Version
174
- version: 6.0.3
174
+ version: 6.0.4
175
175
  type: :development
176
176
  prerelease: false
177
177
  version_requirements: !ruby/object:Gem::Requirement
@@ -181,7 +181,7 @@ dependencies:
181
181
  version: '6.0'
182
182
  - - ">="
183
183
  - !ruby/object:Gem::Version
184
- version: 6.0.3
184
+ version: 6.0.4
185
185
  - !ruby/object:Gem::Dependency
186
186
  name: rspec
187
187
  requirement: !ruby/object:Gem::Requirement
@@ -202,54 +202,42 @@ dependencies:
202
202
  requirements:
203
203
  - - "~>"
204
204
  - !ruby/object:Gem::Version
205
- version: '1.12'
206
- - - ">="
207
- - !ruby/object:Gem::Version
208
- version: 1.12.1
205
+ version: '1.13'
209
206
  type: :development
210
207
  prerelease: false
211
208
  version_requirements: !ruby/object:Gem::Requirement
212
209
  requirements:
213
210
  - - "~>"
214
211
  - !ruby/object:Gem::Version
215
- version: '1.12'
216
- - - ">="
217
- - !ruby/object:Gem::Version
218
- version: 1.12.1
212
+ version: '1.13'
219
213
  - !ruby/object:Gem::Dependency
220
214
  name: rubocop-performance
221
215
  requirement: !ruby/object:Gem::Requirement
222
216
  requirements:
223
217
  - - "~>"
224
218
  - !ruby/object:Gem::Version
225
- version: '1.10'
226
- - - ">="
227
- - !ruby/object:Gem::Version
228
- version: 1.10.2
219
+ version: '1.11'
229
220
  type: :development
230
221
  prerelease: false
231
222
  version_requirements: !ruby/object:Gem::Requirement
232
223
  requirements:
233
224
  - - "~>"
234
225
  - !ruby/object:Gem::Version
235
- version: '1.10'
236
- - - ">="
237
- - !ruby/object:Gem::Version
238
- version: 1.10.2
226
+ version: '1.11'
239
227
  - !ruby/object:Gem::Dependency
240
228
  name: rubocop-rspec
241
229
  requirement: !ruby/object:Gem::Requirement
242
230
  requirements:
243
231
  - - "~>"
244
232
  - !ruby/object:Gem::Version
245
- version: '2.2'
233
+ version: '2.3'
246
234
  type: :development
247
235
  prerelease: false
248
236
  version_requirements: !ruby/object:Gem::Requirement
249
237
  requirements:
250
238
  - - "~>"
251
239
  - !ruby/object:Gem::Version
252
- version: '2.2'
240
+ version: '2.3'
253
241
  - !ruby/object:Gem::Dependency
254
242
  name: simplecov
255
243
  requirement: !ruby/object:Gem::Requirement
@@ -299,7 +287,7 @@ dependencies:
299
287
  - !ruby/object:Gem::Version
300
288
  version: 3.12.2
301
289
  description: Configurable framework agnostic plain Ruby email validator. Verify email
302
- via Regex, DNS and SMTP.
290
+ via Regex, DNS, SMTP and even more.
303
291
  email:
304
292
  - admin@bestweb.com.ua
305
293
  executables: []
@@ -353,6 +341,7 @@ files:
353
341
  - lib/truemail/validate/base.rb
354
342
  - lib/truemail/validate/domain_list_match.rb
355
343
  - lib/truemail/validate/mx.rb
344
+ - lib/truemail/validate/mx_blacklist.rb
356
345
  - lib/truemail/validate/regex.rb
357
346
  - lib/truemail/validate/smtp.rb
358
347
  - lib/truemail/validate/smtp/request.rb