valid_email2 3.2.5 → 3.6.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: 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