valid_email2 3.2.4 → 3.4.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 +4 -4
- data/CHANGELOG.md +15 -0
- data/README.md +5 -0
- data/config/disposable_email_domains.txt +7 -2
- data/lib/valid_email2.rb +28 -16
- data/lib/valid_email2/address.rb +20 -16
- data/lib/valid_email2/email_validator.rb +11 -10
- data/lib/valid_email2/version.rb +1 -1
- data/spec/benchmark_spec.rb +18 -0
- data/spec/spec_helper.rb +9 -0
- data/spec/valid_email2_spec.rb +23 -5
- data/valid_email2.gemspec +1 -0
- metadata +19 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 71c14200d42afbdf47d3222f443c72f81dd23af157f32baebbcc607d2ef09959
|
4
|
+
data.tar.gz: 67e841c534a03d363b118bc50026dcc54ee1550478a98d92e885d53c40905ffe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 27e0b370d3fc4fa2fb1530e931c9f06156c88045f9b55a4b9e038d521460b34ac4dc8b81f6194ea649477cb4169774cfe3b7a9ad15e06447f472b0742700433e
|
7
|
+
data.tar.gz: d160ab3de4196dc830e26aedab650c9839520b9aadccb9e6153305eb42ad796929cab5a209aef3ce869e1a801171b7de45fdc23d3e5ac6004436ad7e31a2a6ef
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,18 @@
|
|
1
|
+
## Version 3.4.0
|
2
|
+
* Disallow consecutive dots https://github.com/micke/valid_email2/pull/163
|
3
|
+
* Add andyes.net https://github.com/micke/valid_email2/pull/162
|
4
|
+
|
5
|
+
## Version 3.3.1
|
6
|
+
* Fix some performance regressions (https://github.com/micke/valid_email2/pull/150)
|
7
|
+
|
8
|
+
## Version 3.3.0
|
9
|
+
* Allow multiple addresses separated by comma (https://github.com/micke/valid_email2/pull/156)
|
10
|
+
* Make prohibited_domain_characters_regex changeable (https://github.com/micke/valid_email2/pull/157)
|
11
|
+
|
12
|
+
## Version 3.2.5
|
13
|
+
* Remove false positives
|
14
|
+
* Pull new domains
|
15
|
+
|
1
16
|
## Version 3.2.4
|
2
17
|
* Remove false positives
|
3
18
|
|
data/README.md
CHANGED
@@ -83,6 +83,11 @@ To validate create your own custom message:
|
|
83
83
|
validates :email, 'valid_email_2/email': { message: "is not a valid email" }
|
84
84
|
```
|
85
85
|
|
86
|
+
To allow multiple addresses separated by comma:
|
87
|
+
```ruby
|
88
|
+
validates :email, 'valid_email_2/email': { multiple: true }
|
89
|
+
```
|
90
|
+
|
86
91
|
All together:
|
87
92
|
```ruby
|
88
93
|
validates :email, 'valid_email_2/email': { mx: true, disposable: true, disallow_subaddressing: true}
|
@@ -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
|
@@ -7866,6 +7867,7 @@ cungmuachungnhom.com
|
|
7866
7867
|
cungsuyngam.com
|
7867
7868
|
cungtam.com
|
7868
7869
|
cuoiz.com
|
7870
|
+
cuoly.com
|
7869
7871
|
cuongvumarketingseo.com
|
7870
7872
|
cupf6mdhtujxytdcoxh.cf
|
7871
7873
|
cupf6mdhtujxytdcoxh.ga
|
@@ -9772,7 +9774,6 @@ edu.auction
|
|
9772
9774
|
edu.dmtc.dev
|
9773
9775
|
edu.hstu.eu.org
|
9774
9776
|
edu.my
|
9775
|
-
edu.sg
|
9776
9777
|
eduanswer.ru
|
9777
9778
|
education.eu
|
9778
9779
|
educationleaders-ksa.com
|
@@ -10352,6 +10353,7 @@ eo-z.com
|
|
10352
10353
|
eoffice.top
|
10353
10354
|
eomail.com
|
10354
10355
|
eonmech.com
|
10356
|
+
eoopy.com
|
10355
10357
|
eorbs.com
|
10356
10358
|
eos2mail.com
|
10357
10359
|
eotoplenie.ru
|
@@ -11401,6 +11403,8 @@ fitnessjockey.org
|
|
11401
11403
|
fitnessmojo.org
|
11402
11404
|
fitnessreviewsonline.com
|
11403
11405
|
fitnesszbyszko.pl
|
11406
|
+
fitschool.be
|
11407
|
+
fitschool.space
|
11404
11408
|
fittinggeeks.pl
|
11405
11409
|
fitzgeraldforjudge.com
|
11406
11410
|
five-club.com
|
@@ -28483,6 +28487,7 @@ tempemailaddress.com
|
|
28483
28487
|
tempemails.io
|
28484
28488
|
tempinbox.co.uk
|
28485
28489
|
tempinbox.com
|
28490
|
+
tempinbox.xyz
|
28486
28491
|
tempm.cf
|
28487
28492
|
tempm.com
|
28488
28493
|
tempm.ga
|
@@ -33695,4 +33700,4 @@ zzv2bfja5.pl
|
|
33695
33700
|
zzz.co
|
33696
33701
|
zzz.com
|
33697
33702
|
zzzmail.pl
|
33698
|
-
zzzzzzzzzzzzz.com
|
33703
|
+
zzzzzzzzzzzzz.com
|
data/lib/valid_email2.rb
CHANGED
@@ -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
|
-
|
11
|
-
|
12
|
-
|
10
|
+
class << self
|
11
|
+
def disposable_emails
|
12
|
+
@disposable_emails ||= load_file(DISPOSABLE_FILE)
|
13
|
+
end
|
13
14
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
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
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
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
|
data/lib/valid_email2/address.rb
CHANGED
@@ -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,21 @@ module ValidEmail2
|
|
24
32
|
end
|
25
33
|
|
26
34
|
def valid?
|
27
|
-
@valid
|
28
|
-
|
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 !~
|
34
|
-
|
35
|
-
domain
|
36
|
-
|
37
|
-
domain
|
38
|
-
|
39
|
-
|
40
|
-
|
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?('.')
|
46
50
|
else
|
47
51
|
false
|
48
52
|
end
|
@@ -62,7 +66,7 @@ module ValidEmail2
|
|
62
66
|
end
|
63
67
|
|
64
68
|
def disposable_domain?
|
65
|
-
|
69
|
+
domain_is_in?(ValidEmail2.disposable_emails)
|
66
70
|
end
|
67
71
|
|
68
72
|
def disposable_mx_server?
|
@@ -5,43 +5,44 @@ 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, 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
|
-
|
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
|
18
|
+
error(record, attribute) && return unless addresses.all?(&:valid?)
|
18
19
|
|
19
20
|
if options[:disallow_dotted]
|
20
|
-
error(record, attribute) && return if
|
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
|
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
|
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
|
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? }
|
37
38
|
end
|
38
39
|
|
39
40
|
if options[:blacklist]
|
40
|
-
error(record, attribute) && return if
|
41
|
+
error(record, attribute) && return if addresses.any?(&:blacklisted?)
|
41
42
|
end
|
42
43
|
|
43
44
|
if options[:mx]
|
44
|
-
error(record, attribute) && return unless
|
45
|
+
error(record, attribute) && return unless addresses.all?(&:valid_mx?)
|
45
46
|
end
|
46
47
|
end
|
47
48
|
|
data/lib/valid_email2/version.rb
CHANGED
@@ -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
|
data/spec/spec_helper.rb
CHANGED
@@ -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
|
|
data/spec/valid_email2_spec.rb
CHANGED
@@ -39,6 +39,10 @@ class TestUserMessage < TestModel
|
|
39
39
|
validates :email, 'valid_email_2/email': { message: "custom message" }
|
40
40
|
end
|
41
41
|
|
42
|
+
class TestUserMultiple < TestModel
|
43
|
+
validates :email, 'valid_email_2/email': { multiple: true }
|
44
|
+
end
|
45
|
+
|
42
46
|
describe ValidEmail2 do
|
43
47
|
|
44
48
|
let(:disposable_domain) { ValidEmail2.disposable_emails.first }
|
@@ -83,13 +87,13 @@ describe ValidEmail2 do
|
|
83
87
|
expect(user.valid?).to be_falsey
|
84
88
|
end
|
85
89
|
|
86
|
-
it "is invalid if the
|
87
|
-
user = TestUser.new(email: "foo
|
88
|
-
expect(user.valid?).to
|
90
|
+
it "is invalid if the address contains consecutive dots" do
|
91
|
+
user = TestUser.new(email: "foo..bar@gmail.com")
|
92
|
+
expect(user.valid?).to be_falsey
|
89
93
|
end
|
90
94
|
|
91
|
-
it "is invalid if the
|
92
|
-
user = TestUser.new(email: "foo
|
95
|
+
it "is invalid if the email contains emoticons" do
|
96
|
+
user = TestUser.new(email: "foo🙈@gmail.com")
|
93
97
|
expect(user.valid?).to be_falsy
|
94
98
|
end
|
95
99
|
|
@@ -244,6 +248,20 @@ describe ValidEmail2 do
|
|
244
248
|
end
|
245
249
|
end
|
246
250
|
|
251
|
+
describe "with multiple addresses" do
|
252
|
+
it "tests each address for it's own" do
|
253
|
+
user = TestUserMultiple.new(email: "foo@gmail.com, bar@gmail.com")
|
254
|
+
expect(user.valid?).to be_truthy
|
255
|
+
end
|
256
|
+
|
257
|
+
context 'when one address is invalid' do
|
258
|
+
it "fails for all" do
|
259
|
+
user = TestUserMultiple.new(email: "foo@gmail.com, bar@123")
|
260
|
+
expect(user.valid?).to be_falsey
|
261
|
+
end
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
247
265
|
describe "#dotted?" do
|
248
266
|
it "is true when address local part contains a dot delimiter ('.')" do
|
249
267
|
email = ValidEmail2::Address.new("john.doe@gmail.com")
|
data/valid_email2.gemspec
CHANGED
@@ -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.
|
4
|
+
version: 3.4.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-
|
11
|
+
date: 2020-09-11 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.
|
160
|
+
rubygems_version: 3.1.2
|
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
|