valid_email2 3.6.0 → 4.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal:true
2
+
1
3
  require "valid_email2"
2
4
  require "resolv"
3
5
  require "mail"
@@ -7,8 +9,8 @@ module ValidEmail2
7
9
  attr_accessor :address
8
10
 
9
11
  PROHIBITED_DOMAIN_CHARACTERS_REGEX = /[+!_\/\s'`]/
10
- DEFAULT_RECIPIENT_DELIMITER = '+'.freeze
11
- DOT_DELIMITER = '.'.freeze
12
+ DEFAULT_RECIPIENT_DELIMITER = '+'
13
+ DOT_DELIMITER = '.'
12
14
 
13
15
  def self.prohibited_domain_characters_regex
14
16
  @prohibited_domain_characters_regex ||= PROHIBITED_DOMAIN_CHARACTERS_REGEX
@@ -18,9 +20,10 @@ module ValidEmail2
18
20
  @prohibited_domain_characters_regex = val
19
21
  end
20
22
 
21
- def initialize(address)
23
+ def initialize(address, dns_timeout = 5)
22
24
  @parse_error = false
23
25
  @raw_address = address
26
+ @dns_timeout = dns_timeout
24
27
 
25
28
  begin
26
29
  @address = Mail::Address.new(address)
@@ -35,23 +38,27 @@ module ValidEmail2
35
38
  return @valid unless @valid.nil?
36
39
  return false if @parse_error
37
40
 
38
- @valid = begin
39
- if address.domain && address.address == @raw_address
40
- domain = address.domain
41
-
42
- domain !~ self.class.prohibited_domain_characters_regex &&
43
- domain.include?('.') &&
44
- !domain.include?('..') &&
45
- !domain.start_with?('.') &&
46
- !domain.start_with?('-') &&
47
- !domain.include?('-.') &&
48
- !address.local.include?('..') &&
49
- !address.local.end_with?('.') &&
50
- !address.local.start_with?('.')
51
- else
52
- false
53
- end
54
- end
41
+ @valid = address.domain &&
42
+ address.address == @raw_address &&
43
+ valid_domain? &&
44
+ valid_address?
45
+ end
46
+
47
+ def valid_domain?
48
+ domain = address.domain
49
+
50
+ domain !~ self.class.prohibited_domain_characters_regex &&
51
+ domain.include?('.') &&
52
+ !domain.include?('..') &&
53
+ !domain.start_with?('.') &&
54
+ !domain.start_with?('-') &&
55
+ !domain.include?('-.')
56
+ end
57
+
58
+ def valid_address?
59
+ !address.local.include?('..') &&
60
+ !address.local.end_with?('.') &&
61
+ !address.local.start_with?('.')
55
62
  end
56
63
 
57
64
  def dotted?
@@ -103,12 +110,13 @@ module ValidEmail2
103
110
  i = address_domain.index('.')
104
111
  return false unless i
105
112
 
106
- return domain_list.include?(address_domain[(i+1)..-1])
113
+ domain_list.include?(address_domain[(i + 1)..-1])
107
114
  end
108
115
 
109
116
  def mx_server_is_in?(domain_list)
110
117
  mx_servers.any? { |mx_server|
111
118
  return false unless mx_server.respond_to?(:exchange)
119
+
112
120
  mx_server = mx_server.exchange.to_s
113
121
 
114
122
  domain_list.any? { |domain|
@@ -125,12 +133,14 @@ module ValidEmail2
125
133
 
126
134
  def mx_servers
127
135
  @mx_servers ||= Resolv::DNS.open do |dns|
136
+ dns.timeouts = @dns_timeout
128
137
  dns.getresources(address.domain, Resolv::DNS::Resource::IN::MX)
129
138
  end
130
139
  end
131
140
 
132
141
  def mx_or_a_servers
133
142
  @mx_or_a_servers ||= Resolv::DNS.open do |dns|
143
+ dns.timeouts = @dns_timeout
134
144
  (mx_servers.any? && mx_servers) ||
135
145
  dns.getresources(address.domain, Resolv::DNS::Resource::IN::A)
136
146
  end
@@ -5,15 +5,14 @@ require "active_model/validations"
5
5
  module ValidEmail2
6
6
  class EmailValidator < ActiveModel::EachValidator
7
7
  def default_options
8
- { regex: true, disposable: false, mx: false, strict_mx: false, disallow_subaddressing: false, multiple: false }
8
+ { regex: true, disposable: false, mx: false, strict_mx: false, disallow_subaddressing: false, multiple: false, dns_timeout: 5 }
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
- value_spitted = options[:multiple] ? value.split(',').map(&:strip) : [value]
16
- addresses = value_spitted.map { |v| ValidEmail2::Address.new(v) }
15
+ addresses = sanitized_values(value).map { |v| ValidEmail2::Address.new(v, options[:dns_timeout]) }
17
16
 
18
17
  error(record, attribute) && return unless addresses.all?(&:valid?)
19
18
 
@@ -54,6 +53,18 @@ module ValidEmail2
54
53
  end
55
54
  end
56
55
 
56
+ def sanitized_values(input)
57
+ options = default_options.merge(self.options)
58
+
59
+ if options[:multiple]
60
+ email_list = input.is_a?(Array) ? input : input.split(',')
61
+ else
62
+ email_list = [input]
63
+ end
64
+
65
+ email_list.reject(&:empty?).map(&:strip)
66
+ end
67
+
57
68
  def error(record, attribute)
58
69
  record.errors.add(attribute, options[:message] || :invalid)
59
70
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal:true
2
+
1
3
  module ValidEmail2
2
- VERSION = "3.6.0"
4
+ VERSION = "4.0.1"
3
5
  end
@@ -9,6 +9,7 @@ whitelisted_emails = %w(
9
9
  onet.pl poczta.onet.pl fastmail.fm hushmail.com
10
10
  hush.ai hush.com hushmail.me naver.com qq.com example.com
11
11
  yandex.net gmx.com gmx.es webdesignspecialist.com.au vp.com
12
+ onit.com asics.com
12
13
  )
13
14
 
14
15
  existing_emails = File.open("config/disposable_email_domains.txt") { |f| f.read.split("\n") }
@@ -312,6 +312,11 @@ describe ValidEmail2 do
312
312
  expect(user.valid?).to be_truthy
313
313
  end
314
314
 
315
+ it "tests each address from an array" do
316
+ user = TestUserMultiple.new(email: %w[foo@gmail.com bar@gmail.com])
317
+ expect(user.valid?).to be_truthy
318
+ end
319
+
315
320
  context 'when one address is invalid' do
316
321
  it "fails for all" do
317
322
  user = TestUserMultiple.new(email: "foo@gmail.com, bar@123")
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: 3.6.0
4
+ version: 4.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Micke Lisinge
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-01-30 00:00:00.000000000 Z
11
+ date: 2021-12-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -157,7 +157,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
157
157
  - !ruby/object:Gem::Version
158
158
  version: '0'
159
159
  requirements: []
160
- rubygems_version: 3.1.4
160
+ rubygems_version: 3.2.3
161
161
  signing_key:
162
162
  specification_version: 4
163
163
  summary: ActiveModel validation for email. Including MX lookup and disposable email