valid_email2 5.1.1 → 5.2.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: 925627af7072ddf7e2f82482253520d9bef1111e605317106afbf84b951c5a57
4
- data.tar.gz: 7eb5251aa7f5cf9e2bcd24c63f23fb45ea6770581d8e1ceebf00933f64f24498
3
+ metadata.gz: c2972753ce57ed3f1c8b9f4b3a5738956bcd3bd67deed34ae248180c9b01155f
4
+ data.tar.gz: 7b0ca1ec81052af623267b0703e90e63f4200133f556bc6dbe52663593588399
5
5
  SHA512:
6
- metadata.gz: 3f02e361ed0c985a4f770a09222fef9179de6a9f01995ac84c57ae6b9a843172afaf80116d01dc1ad9a9b5959dfcc6a089ce5b2ea2d6340701308b8e3b8a9817
7
- data.tar.gz: f05c620994e0aaf353dfc4227cc317d20d2bd9be59e1b85ba4ab70db5d0cf0522ed939dab7fff625ad5701c710da33f037ba37e44123d9f1989b14b3faa64980
6
+ metadata.gz: 1ff8f1b5eee02958bbd8337e340f9fc90fc41f0d7ede63a3019a403bcc65c1dc6d6f4f031a386e15f601316d4965a3068d6d023a34dfdcca0410f209e46e51b1
7
+ data.tar.gz: 7a27bc60a0b7e4522ce28a5bc055b37750a285811b3d2aba8ff0d93addeb70668dcb770c4cf62b28b03486d8bd135bb46f040657028893e8e6aeba083a5ca04f
data/CHANGELOG.md CHANGED
@@ -1,3 +1,6 @@
1
+ ## Version 5.2.0
2
+ * Allow configuration of DNS nameserver [#230](https://github.com/micke/valid_email2/pull/230)
3
+
1
4
  ## Version 5.1.1
2
5
  * Remove false positives [#223](https://github.com/micke/valid_email2/issues/223)
3
6
 
data/README.md CHANGED
@@ -51,12 +51,18 @@ To validate strictly that the domain has an MX record:
51
51
  ```ruby
52
52
  validates :email, 'valid_email_2/email': { strict_mx: true }
53
53
  ```
54
- `strict_mx` and `mx` both default to a 5 second timeout for DNS lookups. To
55
- override this timeout, specify a `dns_timeout` option:
54
+ `strict_mx` and `mx` both default to a 5 second timeout for DNS lookups.
55
+ To override this timeout, specify a `dns_timeout` option:
56
56
  ```ruby
57
57
  validates :email, 'valid_email_2/email': { strict_mx: true, dns_timeout: 10 }
58
58
  ```
59
59
 
60
+ Any checks that require DNS resolution will use the default `Resolv::DNS` nameservers for DNS lookups.
61
+ To override these, specify a `dns_nameserver` option:
62
+ ```ruby
63
+ validates :email, 'valid_email_2/email': { mx: true, dns_nameserver: ['8.8.8.8', '8.8.4.4'] }
64
+ ```
65
+
60
66
  To validate that the domain is not a disposable email (checks domain and MX server):
61
67
  ```ruby
62
68
  validates :email, 'valid_email_2/email': { disposable: true }
@@ -20,11 +20,14 @@ module ValidEmail2
20
20
  @prohibited_domain_characters_regex = val
21
21
  end
22
22
 
23
- def initialize(address, dns_timeout = 5)
23
+ def initialize(address, dns_timeout = 5, dns_nameserver = nil)
24
24
  @parse_error = false
25
25
  @raw_address = address
26
26
  @dns_timeout = dns_timeout
27
27
 
28
+ @resolv_config = Resolv::DNS::Config.default_config_hash
29
+ @resolv_config[:nameserver] = dns_nameserver if dns_nameserver
30
+
28
31
  begin
29
32
  @address = Mail::Address.new(address)
30
33
  rescue Mail::Field::ParseError
@@ -134,7 +137,7 @@ module ValidEmail2
134
137
  end
135
138
 
136
139
  def mx_servers
137
- @mx_servers ||= Resolv::DNS.open do |dns|
140
+ @mx_servers ||= Resolv::DNS.open(@resolv_config) do |dns|
138
141
  dns.timeouts = @dns_timeout
139
142
  dns.getresources(address.domain, Resolv::DNS::Resource::IN::MX)
140
143
  end
@@ -145,7 +148,7 @@ module ValidEmail2
145
148
  end
146
149
 
147
150
  def mx_or_a_servers
148
- @mx_or_a_servers ||= Resolv::DNS.open do |dns|
151
+ @mx_or_a_servers ||= Resolv::DNS.open(@resolv_config) do |dns|
149
152
  dns.timeouts = @dns_timeout
150
153
  (mx_servers.any? && mx_servers) ||
151
154
  dns.getresources(address.domain, Resolv::DNS::Resource::IN::A)
@@ -5,14 +5,14 @@ require "active_model/validations"
5
5
  module ValidEmail2
6
6
  class EmailValidator < ActiveModel::EachValidator
7
7
  def default_options
8
- { disposable: false, mx: false, strict_mx: false, disallow_subaddressing: false, multiple: false, dns_timeout: 5 }
8
+ { disposable: false, mx: false, strict_mx: false, disallow_subaddressing: false, multiple: false, dns_timeout: 5, dns_nameserver: nil }
9
9
  end
10
10
 
11
11
  def validate_each(record, attribute, value)
12
12
  return unless value.present?
13
13
  options = default_options.merge(self.options)
14
14
 
15
- addresses = sanitized_values(value).map { |v| ValidEmail2::Address.new(v, options[:dns_timeout]) }
15
+ addresses = sanitized_values(value).map { |v| ValidEmail2::Address.new(v, options[:dns_timeout], options[:dns_nameserver]) }
16
16
 
17
17
  error(record, attribute) && return unless addresses.all?(&:valid?)
18
18
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal:true
2
2
 
3
3
  module ValidEmail2
4
- VERSION = "5.1.1"
4
+ VERSION = "5.2.0"
5
5
  end
@@ -23,6 +23,22 @@ class TestUserStrictMX < TestModel
23
23
  validates :email, 'valid_email_2/email': { strict_mx: true }
24
24
  end
25
25
 
26
+ class TestUserMXDnsTimeout < TestModel
27
+ validates :email, 'valid_email_2/email': { mx: true, dns_timeout: 10 }
28
+ end
29
+
30
+ class TestUserMXDnsFailingTimeout < TestModel
31
+ validates :email, 'valid_email_2/email': { mx: true, dns_timeout: Float::MIN }
32
+ end
33
+
34
+ class TestUserMXDnsNameserver < TestModel
35
+ validates :email, 'valid_email_2/email': { mx: true, dns_nameserver: ['8.8.8.8', '8.8.4.4'] }
36
+ end
37
+
38
+ class TestUserMXDnsFailingNameserver < TestModel
39
+ validates :email, 'valid_email_2/email': { mx: true, dns_timeout: 0.1, dns_nameserver: '1.0.0.0' }
40
+ end
41
+
26
42
  class TestUserDisallowDisposable < TestModel
27
43
  validates :email, 'valid_email_2/email': { disposable: true }
28
44
  end
@@ -292,6 +308,94 @@ describe ValidEmail2 do
292
308
  end
293
309
  end
294
310
 
311
+ describe "with mx validation and dns not hitting timeout" do
312
+ it "is valid if mx records are found" do
313
+ user = TestUserMXDnsTimeout.new(email: "foo@gmail.com")
314
+ expect(user.valid?).to be_truthy
315
+ end
316
+
317
+ it "is valid if A records are found" do
318
+ user = TestUserMXDnsTimeout.new(email: "foo@ghs.google.com")
319
+ expect(user.valid?).to be_truthy
320
+ end
321
+
322
+ it "is invalid if no mx records are found" do
323
+ user = TestUserMXDnsTimeout.new(email: "foo@subdomain.gmail.com")
324
+ expect(user.valid?).to be_falsey
325
+ end
326
+
327
+ it "is invalid if a null mx is found" do
328
+ user = TestUserMXDnsTimeout.new(email: "foo@gmail.de")
329
+ expect(user.valid?).to be_falsey
330
+ end
331
+ end
332
+
333
+ describe "with mx validation and dns hitting timeout" do
334
+ it "is never valid even if mx records exist" do
335
+ user = TestUserMXDnsFailingTimeout.new(email: "foo@gmail.com")
336
+ expect(user.valid?).to be_falsey
337
+ end
338
+
339
+ it "is never valid even A records exist" do
340
+ user = TestUserMXDnsFailingTimeout.new(email: "foo@ghs.google.com")
341
+ expect(user.valid?).to be_falsey
342
+ end
343
+
344
+ it "is invalid if no mx records exist" do
345
+ user = TestUserMXDnsFailingTimeout.new(email: "foo@subdomain.gmail.com")
346
+ expect(user.valid?).to be_falsey
347
+ end
348
+
349
+ it "is invalid if a null mx exists" do
350
+ user = TestUserMXDnsFailingTimeout.new(email: "foo@gmail.de")
351
+ expect(user.valid?).to be_falsey
352
+ end
353
+ end
354
+
355
+ describe "with mx validation and dns nameserver" do
356
+ it "is valid if mx records are found" do
357
+ user = TestUserMXDnsNameserver.new(email: "foo@gmail.com")
358
+ expect(user.valid?).to be_truthy
359
+ end
360
+
361
+ it "is valid if A records are found" do
362
+ user = TestUserMXDnsNameserver.new(email: "foo@ghs.google.com")
363
+ expect(user.valid?).to be_truthy
364
+ end
365
+
366
+ it "is invalid if no mx records are found" do
367
+ user = TestUserMXDnsNameserver.new(email: "foo@subdomain.gmail.com")
368
+ expect(user.valid?).to be_falsey
369
+ end
370
+
371
+ it "is invalid if a null mx is found" do
372
+ user = TestUserMXDnsNameserver.new(email: "foo@gmail.de")
373
+ expect(user.valid?).to be_falsey
374
+ end
375
+ end
376
+
377
+ describe "with mx validation and failing dns nameserver" do
378
+ it "is never valid even if mx records exist" do
379
+ user = TestUserMXDnsFailingNameserver.new(email: "foo@gmail.com")
380
+ expect(user.valid?).to be_falsey
381
+ end
382
+
383
+ it "is never valid even A records exist" do
384
+ user = TestUserMXDnsFailingNameserver.new(email: "foo@ghs.google.com")
385
+ expect(user.valid?).to be_falsey
386
+ end
387
+
388
+ it "is invalid if no mx records exist" do
389
+ user = TestUserMXDnsFailingNameserver.new(email: "foo@subdomain.gmail.com")
390
+ expect(user.valid?).to be_falsey
391
+ end
392
+
393
+ it "is invalid if a null mx exists" do
394
+ user = TestUserMXDnsFailingNameserver.new(email: "foo@gmail.de")
395
+ expect(user.valid?).to be_falsey
396
+ end
397
+ end
398
+
295
399
  describe "with dotted validation" do
296
400
  it "is valid when address does not contain dots" do
297
401
  user = TestUserDotted.new(email: "johndoe@gmail.com")
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: valid_email2
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.1.1
4
+ version: 5.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Micke Lisinge
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-10-26 00:00:00.000000000 Z
11
+ date: 2024-02-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler