valid_email2 3.2.5 → 3.6.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 826d65203316bb843deb2167608e1fcd087741ad0d2cbb96d123eb87997d633c
4
- data.tar.gz: 8e67f13e8b38393f0b8cf3d6562135bd1bdab809ce54c267c6fed615bbbd7304
3
+ metadata.gz: f6543e0ca764df6ed5698a864b232260e456a0fc3b8e3f82918122e21cdca0c3
4
+ data.tar.gz: 989805e58182e1b4ab18b9a16a80a9507465f840bea19840abebe841d628dfa9
5
5
  SHA512:
6
- metadata.gz: 8c2bef1c61e6cabfba92a339b4157809a090aafc709d18652f3c1e149bb438f8fcc79fddb467efba8fd859ac299926f9695c1d6f89b5b680bb1264e66029ffea
7
- data.tar.gz: 5626451520015990d7f1f64d6f34cabf75b38f9f3a82ca2c6af9616b0c03a50e43ef78ba733b59ec1818cd07b68eca10478a01a1085efa47295d6f31b1f41d30
6
+ metadata.gz: 59813d38f00f9c75cbaae7d944f47d50f9e0239f740c468e8718c51345af324f46411e13b2796c5881769a62127345529be92ae374d07082d07e06610e50b62a
7
+ data.tar.gz: 131d25e900327ff67b0cd80e17ecc0de83462394d8094cafbed93780ec9b4d472b8e1b95591dc8c894fc8c4f47a8a5a60d31d7fa3c6733210f1b429ca79ff72c
@@ -1,3 +1,22 @@
1
+ ## Version 3.6.0
2
+ * Add strict_mx validation https://github.com/micke/valid_email2/pull/173
3
+
4
+ ## Version 3.5.0
5
+ * Disallow emails starting with a dot https://github.com/micke/valid_email2/pull/170
6
+ * Add option to whitelist domains from MX check https://github.com/micke/valid_email2/pull/167
7
+ * Remove false positives
8
+
9
+ ## Version 3.4.0
10
+ * Disallow consecutive dots https://github.com/micke/valid_email2/pull/163
11
+ * Add andyes.net https://github.com/micke/valid_email2/pull/162
12
+
13
+ ## Version 3.3.1
14
+ * Fix some performance regressions (https://github.com/micke/valid_email2/pull/150)
15
+
16
+ ## Version 3.3.0
17
+ * Allow multiple addresses separated by comma (https://github.com/micke/valid_email2/pull/156)
18
+ * Make prohibited_domain_characters_regex changeable (https://github.com/micke/valid_email2/pull/157)
19
+
1
20
  ## Version 3.2.5
2
21
  * Remove false positives
3
22
  * Pull new domains
data/README.md CHANGED
@@ -43,10 +43,14 @@ class User < ActiveRecord::Base
43
43
  end
44
44
  ```
45
45
 
46
- To validate that the domain has a MX record:
46
+ To validate that the domain has an MX record or A record:
47
47
  ```ruby
48
48
  validates :email, 'valid_email_2/email': { mx: true }
49
49
  ```
50
+ To validate strictly that the domain has an MX record:
51
+ ```ruby
52
+ validates :email, 'valid_email_2/email': { strict_mx: true }
53
+ ```
50
54
 
51
55
  To validate that the domain is not a disposable email (checks domain and MX server):
52
56
  ```ruby
@@ -58,11 +62,17 @@ To validate that the domain is not a disposable email (checks domain only, does
58
62
  validates :email, 'valid_email_2/email': { disposable_domain: true }
59
63
  ```
60
64
 
61
- To validate that the domain is not a disposable email or a disposable email but whitelisted (under config/whitelisted_email_domains.yml):
65
+ To validate that the domain is not a disposable email or a disposable email (checks domain and MX server) but whitelisted (under config/whitelisted_email_domains.yml):
62
66
  ```ruby
63
67
  validates :email, 'valid_email_2/email': { disposable_with_whitelist: true }
64
68
  ```
65
69
 
70
+ To validate that the domain is not a disposable email or a disposable email (checks domain only, does not check MX server) but whitelisted (under config/whitelisted_email_domains.yml):
71
+
72
+ ```ruby
73
+ validates :email, 'valid_email_2/email': { disposable_domain_with_whitelist: true }
74
+ ```
75
+
66
76
  To validate that the domain is not blacklisted (under config/blacklisted_email_domains.yml):
67
77
  ```ruby
68
78
  validates :email, 'valid_email_2/email': { blacklist: true }
@@ -83,6 +93,11 @@ To validate create your own custom message:
83
93
  validates :email, 'valid_email_2/email': { message: "is not a valid email" }
84
94
  ```
85
95
 
96
+ To allow multiple addresses separated by comma:
97
+ ```ruby
98
+ validates :email, 'valid_email_2/email': { multiple: true }
99
+ ```
100
+
86
101
  All together:
87
102
  ```ruby
88
103
  validates :email, 'valid_email_2/email': { mx: true, disposable: true, disallow_subaddressing: true}
@@ -98,6 +113,7 @@ address = ValidEmail2::Address.new("lisinge@gmail.com")
98
113
  address.valid? => true
99
114
  address.disposable? => false
100
115
  address.valid_mx? => true
116
+ address.valid_strict_mx? => true
101
117
  address.subaddressed? => false
102
118
  ```
103
119
 
@@ -109,6 +125,7 @@ Do so by adding this in your `spec_helper`:
109
125
  ```ruby
110
126
  config.before(:each) do
111
127
  allow_any_instance_of(ValidEmail2::Address).to receive(:valid_mx?).and_return(true)
128
+ allow_any_instance_of(ValidEmail2::Address).to receive(:valid_strict_mx?).and_return(true)
112
129
  end
113
130
  ```
114
131
 
@@ -3398,6 +3398,7 @@ androidsapps.co
3398
3398
  androidworld.tw
3399
3399
  andthen.us
3400
3400
  andy1mail.host
3401
+ andyes.net
3401
3402
  andynugraha.net
3402
3403
  andyyxc45.biz
3403
3404
  aneaproducciones.com
@@ -4173,6 +4174,7 @@ avuimkgtbgccejft901.ml
4173
4174
  avuimkgtbgccejft901.tk
4174
4175
  avumail.com
4175
4176
  avvmail.com
4177
+ avxrja.com
4176
4178
  aw.kikwet.com
4177
4179
  awahal0vk1o7gbyzf0.cf
4178
4180
  awahal0vk1o7gbyzf0.ga
@@ -12788,6 +12790,7 @@ gmailllll.ga
12788
12790
  gmaills.eu
12789
12791
  gmailmail.ga
12790
12792
  gmailmarina.com
12793
+ gmailnator.com
12791
12794
  gmailner.com
12792
12795
  gmailnew.com
12793
12796
  gmailom.co
@@ -12938,6 +12941,7 @@ golivejasmin.com
12938
12941
  gomail.in
12939
12942
  gomail.pgojual.com
12940
12943
  gomailbox.info
12944
+ gomaild.com
12941
12945
  gomaile.com
12942
12946
  gomailstar.xyz
12943
12947
  gomessage.ml
@@ -18053,6 +18057,7 @@ louboutinshoessalejp.com
18053
18057
  louboutinshoesstoresjp.com
18054
18058
  louboutinshoesus.com
18055
18059
  louder1.bid
18060
+ loufad.com
18056
18061
  louis-vuitton-onlinestore.com
18057
18062
  louis-vuitton-outlet.com
18058
18063
  louis-vuitton-outletenter.com
@@ -31026,7 +31031,6 @@ voyagebirmanie.net
31026
31031
  voyancegratuite10min.com
31027
31032
  voyeurseite.info
31028
31033
  vozmivtop.ru
31029
- vp.com
31030
31034
  vp.ycare.de
31031
31035
  vpanel.ru
31032
31036
  vpc608a0.pl
@@ -31423,7 +31427,6 @@ webcontact-france.eu
31423
31427
  webcool.club
31424
31428
  webdesign-guide.info
31425
31429
  webdesign-romania.net
31426
- webdesignspecialist.com.au
31427
31430
  webdesigrsbio.gr
31428
31431
  webdespro.ru
31429
31432
  webdev-pro.ru
@@ -32328,6 +32331,7 @@ xdvsagsdg4we.ga
32328
32331
  xe2g.com
32329
32332
  xeames.net
32330
32333
  xeb9xwp7.tk
32334
+ xedmi.com
32331
32335
  xemaps.com
32332
32336
  xemne.com
32333
32337
  xenacareholdings.com
@@ -32378,6 +32382,7 @@ xhkss.net
32378
32382
  xijjfjoo.turystyka.pl
32379
32383
  xilopro.com
32380
32384
  xilor.com
32385
+ ximtyl.com
32381
32386
  xinbo.info
32382
32387
  xinbox.info
32383
32388
  xinfi.com.pl
@@ -7,23 +7,35 @@ module ValidEmail2
7
7
  WHITELIST_FILE = "config/whitelisted_email_domains.yml"
8
8
  DISPOSABLE_FILE = File.expand_path('../config/disposable_email_domains.txt', __dir__)
9
9
 
10
- def self.disposable_emails
11
- @disposable_emails ||= File.open(DISPOSABLE_FILE){ |f| f.read }.split("\n")
12
- end
10
+ class << self
11
+ def disposable_emails
12
+ @disposable_emails ||= load_file(DISPOSABLE_FILE)
13
+ end
13
14
 
14
- def self.blacklist
15
- @blacklist ||= if File.exist?(BLACKLIST_FILE)
16
- YAML.load_file(File.expand_path(BLACKLIST_FILE))
17
- else
18
- []
19
- end
20
- end
15
+ def blacklist
16
+ @blacklist ||= load_if_exists(BLACKLIST_FILE)
17
+ end
18
+
19
+ def whitelist
20
+ @whitelist ||= load_if_exists(WHITELIST_FILE)
21
+ end
22
+
23
+ private
24
+
25
+ def load_if_exists(path)
26
+ File.exist?(path) ? load_file(path) : Set.new
27
+ end
21
28
 
22
- def self.whitelist
23
- @whitelist ||= if File.exist?(WHITELIST_FILE)
24
- YAML.load_file(File.expand_path(WHITELIST_FILE))
25
- else
26
- []
27
- end
29
+ def load_file(path)
30
+ # This method MUST return a Set, otherwise the
31
+ # performance will suffer!
32
+ if path.end_with?(".yml")
33
+ Set.new(YAML.load_file(path))
34
+ else
35
+ File.open(path, "r").each_line.each_with_object(Set.new) do |domain, set|
36
+ set << domain.tap(&:chomp!)
37
+ end
38
+ end
39
+ end
28
40
  end
29
41
  end
@@ -10,6 +10,14 @@ module ValidEmail2
10
10
  DEFAULT_RECIPIENT_DELIMITER = '+'.freeze
11
11
  DOT_DELIMITER = '.'.freeze
12
12
 
13
+ def self.prohibited_domain_characters_regex
14
+ @prohibited_domain_characters_regex ||= PROHIBITED_DOMAIN_CHARACTERS_REGEX
15
+ end
16
+
17
+ def self.prohibited_domain_characters_regex=(val)
18
+ @prohibited_domain_characters_regex = val
19
+ end
20
+
13
21
  def initialize(address)
14
22
  @parse_error = false
15
23
  @raw_address = address
@@ -24,25 +32,22 @@ module ValidEmail2
24
32
  end
25
33
 
26
34
  def valid?
27
- @valid ||= begin
28
- return false if @parse_error
35
+ return @valid unless @valid.nil?
36
+ return false if @parse_error
29
37
 
38
+ @valid = begin
30
39
  if address.domain && address.address == @raw_address
31
40
  domain = address.domain
32
41
 
33
- domain !~ PROHIBITED_DOMAIN_CHARACTERS_REGEX &&
34
- # Domain needs to have at least one dot
35
- domain =~ /\./ &&
36
- # Domain may not have two consecutive dots
37
- domain !~ /\.{2,}/ &&
38
- # Domain may not start with a dot
39
- domain !~ /^\./ &&
40
- # Domain may not start with a dash
41
- domain !~ /^-/ &&
42
- # Domain name may not end with a dash
43
- domain !~ /-\./ &&
44
- # Address may not contain a dot directly before @
45
- address.address !~ /\.@/
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?('.')
46
51
  else
47
52
  false
48
53
  end
@@ -62,7 +67,7 @@ module ValidEmail2
62
67
  end
63
68
 
64
69
  def disposable_domain?
65
- valid? && domain_is_in?(ValidEmail2.disposable_emails)
70
+ domain_is_in?(ValidEmail2.disposable_emails)
66
71
  end
67
72
 
68
73
  def disposable_mx_server?
@@ -80,6 +85,12 @@ module ValidEmail2
80
85
  def valid_mx?
81
86
  return false unless valid?
82
87
 
88
+ mx_or_a_servers.any?
89
+ end
90
+
91
+ def valid_strict_mx?
92
+ return false unless valid?
93
+
83
94
  mx_servers.any?
84
95
  end
85
96
 
@@ -114,7 +125,12 @@ module ValidEmail2
114
125
 
115
126
  def mx_servers
116
127
  @mx_servers ||= Resolv::DNS.open do |dns|
117
- mx_servers = dns.getresources(address.domain, Resolv::DNS::Resource::IN::MX)
128
+ dns.getresources(address.domain, Resolv::DNS::Resource::IN::MX)
129
+ end
130
+ end
131
+
132
+ def mx_or_a_servers
133
+ @mx_or_a_servers ||= Resolv::DNS.open do |dns|
118
134
  (mx_servers.any? && mx_servers) ||
119
135
  dns.getresources(address.domain, Resolv::DNS::Resource::IN::A)
120
136
  end
@@ -5,43 +5,52 @@ 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, disallow_subaddressing: false }
8
+ { regex: true, disposable: false, mx: false, strict_mx: false, disallow_subaddressing: false, multiple: false }
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
- address = ValidEmail2::Address.new(value)
15
+ value_spitted = options[:multiple] ? value.split(',').map(&:strip) : [value]
16
+ addresses = value_spitted.map { |v| ValidEmail2::Address.new(v) }
16
17
 
17
- error(record, attribute) && return unless address.valid?
18
+ error(record, attribute) && return unless addresses.all?(&:valid?)
18
19
 
19
20
  if options[:disallow_dotted]
20
- error(record, attribute) && return if address.dotted?
21
+ error(record, attribute) && return if addresses.any?(&:dotted?)
21
22
  end
22
23
 
23
24
  if options[:disallow_subaddressing]
24
- error(record, attribute) && return if address.subaddressed?
25
+ error(record, attribute) && return if addresses.any?(&:subaddressed?)
25
26
  end
26
27
 
27
28
  if options[:disposable]
28
- error(record, attribute) && return if address.disposable?
29
+ error(record, attribute) && return if addresses.any?(&:disposable?)
29
30
  end
30
31
 
31
32
  if options[:disposable_domain]
32
- error(record, attribute) && return if address.disposable_domain?
33
+ error(record, attribute) && return if addresses.any?(&:disposable_domain?)
33
34
  end
34
35
 
35
36
  if options[:disposable_with_whitelist]
36
- error(record, attribute) && return if address.disposable? && !address.whitelisted?
37
+ error(record, attribute) && return if addresses.any? { |address| address.disposable? && !address.whitelisted? }
38
+ end
39
+
40
+ if options[:disposable_domain_with_whitelist]
41
+ error(record, attribute) && return if addresses.any? { |address| address.disposable_domain? && !address.whitelisted? }
37
42
  end
38
43
 
39
44
  if options[:blacklist]
40
- error(record, attribute) && return if address.blacklisted?
45
+ error(record, attribute) && return if addresses.any?(&:blacklisted?)
41
46
  end
42
47
 
43
48
  if options[:mx]
44
- error(record, attribute) && return unless address.valid_mx?
49
+ error(record, attribute) && return unless addresses.all?(&:valid_mx?)
50
+ end
51
+
52
+ if options[:strict_mx]
53
+ error(record, attribute) && return unless addresses.all?(&:valid_strict_mx?)
45
54
  end
46
55
  end
47
56
 
@@ -1,3 +1,3 @@
1
1
  module ValidEmail2
2
- VERSION = "3.2.5"
2
+ VERSION = "3.6.0"
3
3
  end
@@ -8,7 +8,7 @@ require "net/http"
8
8
  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
- yandex.net gmx.com gmx.es
11
+ yandex.net gmx.com gmx.es webdesignspecialist.com.au vp.com
12
12
  )
13
13
 
14
14
  existing_emails = File.open("config/disposable_email_domains.txt") { |f| f.read.split("\n") }
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ describe "Performance testing" do
6
+ let(:disposable_domain) { ValidEmail2.disposable_emails.first }
7
+
8
+ it "has acceptable lookup performance" do
9
+ address = ValidEmail2::Address.new("test@example.com")
10
+
11
+ # preload list and check size
12
+ expect(ValidEmail2.disposable_emails).to be_a(Set)
13
+ expect(ValidEmail2.disposable_emails.count).to be > 30000
14
+
15
+ # check lookup timing
16
+ expect { address.disposable_domain? }.to perform_under(0.0001).sample(10).times
17
+ end
18
+ end
@@ -1,6 +1,15 @@
1
1
  $:.unshift File.expand_path("../lib",__FILE__)
2
2
  require "valid_email2"
3
3
 
4
+ # Include and configure benchmark
5
+ require 'rspec-benchmark'
6
+ RSpec.configure do |config|
7
+ config.include RSpec::Benchmark::Matchers
8
+ end
9
+ RSpec::Benchmark.configure do |config|
10
+ config.disable_gc = true
11
+ end
12
+
4
13
  class TestModel
5
14
  include ActiveModel::Validations
6
15
 
@@ -19,6 +19,10 @@ class TestUserMX < TestModel
19
19
  validates :email, 'valid_email_2/email': { mx: true }
20
20
  end
21
21
 
22
+ class TestUserStrictMX < TestModel
23
+ validates :email, 'valid_email_2/email': { strict_mx: true }
24
+ end
25
+
22
26
  class TestUserDisallowDisposable < TestModel
23
27
  validates :email, 'valid_email_2/email': { disposable: true }
24
28
  end
@@ -31,6 +35,10 @@ class TestUserDisallowDisposableWithWhitelist < TestModel
31
35
  validates :email, 'valid_email_2/email': { disposable_with_whitelist: true }
32
36
  end
33
37
 
38
+ class TestUserDisallowDisposableDomainWithWhitelist < TestModel
39
+ validates :email, 'valid_email_2/email': { disposable_domain_with_whitelist: true }
40
+ end
41
+
34
42
  class TestUserDisallowBlacklisted < TestModel
35
43
  validates :email, 'valid_email_2/email': { blacklist: true }
36
44
  end
@@ -39,6 +47,10 @@ class TestUserMessage < TestModel
39
47
  validates :email, 'valid_email_2/email': { message: "custom message" }
40
48
  end
41
49
 
50
+ class TestUserMultiple < TestModel
51
+ validates :email, 'valid_email_2/email': { multiple: true }
52
+ end
53
+
42
54
  describe ValidEmail2 do
43
55
 
44
56
  let(:disposable_domain) { ValidEmail2.disposable_emails.first }
@@ -83,13 +95,23 @@ describe ValidEmail2 do
83
95
  expect(user.valid?).to be_falsey
84
96
  end
85
97
 
86
- it "is invalid if the domain contains emoticons" do
87
- user = TestUser.new(email: "foo🙈@gmail.com")
88
- expect(user.valid?).to be_falsy
98
+ it "is invalid if the address contains consecutive dots" do
99
+ user = TestUser.new(email: "foo..bar@gmail.com")
100
+ expect(user.valid?).to be_falsey
101
+ end
102
+
103
+ it "is invalid if the address starts with a dot" do
104
+ user = TestUser.new(email: ".foo@bar.com")
105
+ expect(user.valid?).to be_falsey
89
106
  end
90
107
 
91
- it "is invalid if the domain contains .@ consecutively" do
92
- user = TestUser.new(email: "foo.@gmail.com")
108
+ it "is invalid if the local part of the address ends with a dot" do
109
+ user = TestUser.new(email: "foo.@bar.com")
110
+ expect(user.valid?).to be_falsey
111
+ end
112
+
113
+ it "is invalid if the email contains emoticons" do
114
+ user = TestUser.new(email: "foo🙈@gmail.com")
93
115
  expect(user.valid?).to be_falsy
94
116
  end
95
117
 
@@ -166,8 +188,18 @@ describe ValidEmail2 do
166
188
  let(:whitelist_domain) { disposable_domain }
167
189
  let(:whitelist_file_path) { "config/whitelisted_email_domains.yml" }
168
190
 
191
+ # Some of the specs below need to explictly set the whitelist var or it
192
+ # may be cached to an empty set
193
+ def set_whitelist
194
+ ValidEmail2.instance_variable_set(
195
+ :@whitelist,
196
+ ValidEmail2.send(:load_if_exists, ValidEmail2::WHITELIST_FILE)
197
+ )
198
+ end
199
+
169
200
  after do
170
201
  FileUtils.rm(whitelist_file_path, force: true)
202
+ set_whitelist
171
203
  end
172
204
 
173
205
  it "is invalid if the domain is disposable and not in the whitelist" do
@@ -177,9 +209,22 @@ describe ValidEmail2 do
177
209
 
178
210
  it "is valid if the domain is disposable but in the whitelist" do
179
211
  File.open(whitelist_file_path, "w") { |f| f.write [whitelist_domain].to_yaml }
212
+ set_whitelist
180
213
  user = TestUserDisallowDisposableWithWhitelist.new(email: "foo@#{whitelist_domain}")
214
+ expect(user.valid?).to be_truthy
215
+ end
216
+
217
+ it "is invalid if the domain is a disposable_domain and not in the whitelist" do
218
+ user = TestUserDisallowDisposableDomainWithWhitelist.new(email: "foo@#{whitelist_domain}")
181
219
  expect(user.valid?).to be_falsey
182
220
  end
221
+
222
+ it "is valid if the domain is a disposable_domain but in the whitelist" do
223
+ File.open(whitelist_file_path, "w") { |f| f.write [whitelist_domain].to_yaml }
224
+ set_whitelist
225
+ user = TestUserDisallowDisposableDomainWithWhitelist.new(email: "foo@#{whitelist_domain}")
226
+ expect(user.valid?).to be_truthy
227
+ end
183
228
  end
184
229
  end
185
230
 
@@ -212,6 +257,23 @@ describe ValidEmail2 do
212
257
  end
213
258
  end
214
259
 
260
+ describe "with strict mx validation" do
261
+ it "is valid if mx records are found" do
262
+ user = TestUserStrictMX.new(email: "foo@gmail.com")
263
+ expect(user.valid?).to be_truthy
264
+ end
265
+
266
+ it "is invalid if A records are found but no mx records are found" do
267
+ user = TestUserStrictMX.new(email: "foo@ghs.google.com")
268
+ expect(user.valid?).to be_falsey
269
+ end
270
+
271
+ it "is invalid if no mx records are found" do
272
+ user = TestUserStrictMX.new(email: "foo@subdomain.gmail.com")
273
+ expect(user.valid?).to be_falsey
274
+ end
275
+ end
276
+
215
277
  describe "with dotted validation" do
216
278
  it "is valid when address does not contain dots" do
217
279
  user = TestUserDotted.new(email: "johndoe@gmail.com")
@@ -244,6 +306,20 @@ describe ValidEmail2 do
244
306
  end
245
307
  end
246
308
 
309
+ describe "with multiple addresses" do
310
+ it "tests each address for it's own" do
311
+ user = TestUserMultiple.new(email: "foo@gmail.com, bar@gmail.com")
312
+ expect(user.valid?).to be_truthy
313
+ end
314
+
315
+ context 'when one address is invalid' do
316
+ it "fails for all" do
317
+ user = TestUserMultiple.new(email: "foo@gmail.com, bar@123")
318
+ expect(user.valid?).to be_falsey
319
+ end
320
+ end
321
+ end
322
+
247
323
  describe "#dotted?" do
248
324
  it "is true when address local part contains a dot delimiter ('.')" do
249
325
  email = ValidEmail2::Address.new("john.doe@gmail.com")
@@ -23,6 +23,7 @@ Gem::Specification.new do |spec|
23
23
  spec.add_development_dependency "bundler", "~> 2.0"
24
24
  spec.add_development_dependency "rake", "~> 12.3.3"
25
25
  spec.add_development_dependency "rspec", "~> 3.5.0"
26
+ spec.add_development_dependency "rspec-benchmark", "~> 0.6"
26
27
  spec.add_development_dependency "pry"
27
28
  spec.add_runtime_dependency "mail", "~> 2.5"
28
29
  spec.add_runtime_dependency "activemodel", ">= 3.2"
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.2.5
4
+ version: 3.6.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: 2020-08-06 00:00:00.000000000 Z
11
+ date: 2021-01-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: 3.5.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec-benchmark
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.6'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.6'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: pry
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -120,6 +134,7 @@ files:
120
134
  - lib/valid_email2/email_validator.rb
121
135
  - lib/valid_email2/version.rb
122
136
  - pull_mailchecker_emails.rb
137
+ - spec/benchmark_spec.rb
123
138
  - spec/spec_helper.rb
124
139
  - spec/valid_email2_spec.rb
125
140
  - valid_email2.gemspec
@@ -142,11 +157,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
142
157
  - !ruby/object:Gem::Version
143
158
  version: '0'
144
159
  requirements: []
145
- rubygems_version: 3.1.2
160
+ rubygems_version: 3.1.4
146
161
  signing_key:
147
162
  specification_version: 4
148
163
  summary: ActiveModel validation for email. Including MX lookup and disposable email
149
164
  blacklist
150
165
  test_files:
166
+ - spec/benchmark_spec.rb
151
167
  - spec/spec_helper.rb
152
168
  - spec/valid_email2_spec.rb