valid_email2 3.6.0 → 4.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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