email_validator 2.2.2 → 2.2.3
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 +10 -0
- data/README.md +7 -3
- data/lib/email_validator.rb +35 -16
- data/spec/email_validator_spec.rb +53 -17
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 46bd723714c6aa3a844e584e986e5989920b6d3f212a44d800183d118c561cb7
|
4
|
+
data.tar.gz: bb58e5bf862c4be796e3ce59727dcf3fd2e28267e7c6077014f01d25dc841580
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2ece91a44bd82bd79c5484a17729996731787148b6813af0c4e41804715242a9cbfb4c0d661b08e0c904753dd59f23560d11aed7bf9044986802445e36f69438
|
7
|
+
data.tar.gz: 1b91bf21ce112f86f9b97138573d20fe14b67f075935136c3b19a620f155d50c5d5cf5ff9566e4c101429b8d7ce80ccb80709a2a15eeb07f4caeaac34f2b86b0
|
data/CHANGELOG.md
CHANGED
@@ -5,6 +5,16 @@ This file is used to list changes made in `email_validator`.
|
|
5
5
|
All notable changes to this project will be documented in this file.
|
6
6
|
This project adheres to [Semantic Versioning](http://semver.org/).
|
7
7
|
|
8
|
+
## 2.2.3 (2021-04-05)
|
9
|
+
|
10
|
+
* [karlwilbur] - Fix regexp for numeric domains (fixes [#72](https://github.com/K-and-R/email_validator/issues/72))
|
11
|
+
- [delphaber] - Add checks for numeric-only domains in tests (should be considered valid)
|
12
|
+
- [karlwilbur] - Fix specs for numeric-only domains labels (should be considered valid)
|
13
|
+
- [karlwilbur] - Add checks for numeric-only TLDs in tests (should be considered invalid)
|
14
|
+
- [karlwilbur] - Add tests to ensure that `regexp` returns expected value
|
15
|
+
- [karlwilbur] - Add checks for double dash in domain (should be considered invalid)
|
16
|
+
- [karlwilbur] - Add `EmailValidator::Error` class, raise `EmailValidator::Error` when invalid `mode`
|
17
|
+
|
8
18
|
## 2.2.2 (2020-12-10)
|
9
19
|
|
10
20
|
* [karlwilbur] - Fix includes for `:rfc` and `:strict` modes from `Gemfile`
|
data/README.md
CHANGED
@@ -54,9 +54,9 @@ by setting `require_fqdn: true` or by enabling `:strict` checking:
|
|
54
54
|
validates :my_email_attribute, email: {mode: :strict, require_fqdn: true}
|
55
55
|
```
|
56
56
|
|
57
|
-
You can also limit to a single domain (e.g:
|
58
|
-
|
59
|
-
|
57
|
+
You can also limit to a single domain (e.g: you have separate `User` and
|
58
|
+
`AdminUser` models and want to ensure that `AdminUser` emails are on a specific
|
59
|
+
domain):
|
60
60
|
|
61
61
|
```ruby
|
62
62
|
validates :my_email_attribute, email: {domain: 'example.com'}
|
@@ -166,6 +166,10 @@ EmailValidator.valid?('narf@somehost') # boolean false
|
|
166
166
|
EmailValidator.invalid?('narf@somehost', require_fqdn: false) # boolean true
|
167
167
|
```
|
168
168
|
|
169
|
+
_NB: Enabling strict mode (`mode: :strict`) enables `require_fqdn`
|
170
|
+
(`require_fqdn: true`), overridding any `require_fqdn: false` while
|
171
|
+
`mode: :strict` is set._
|
172
|
+
|
169
173
|
### Requiring a specific domain
|
170
174
|
|
171
175
|
```ruby
|
data/lib/email_validator.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
# Based on work from http://thelucid.com/2010/01/08/sexy-validation-in-edge-rails-rails-3/
|
2
|
+
|
3
|
+
# EmailValidator class
|
2
4
|
class EmailValidator < ActiveModel::EachValidator
|
3
5
|
# rubocop:disable Style/ClassVars
|
4
6
|
@@default_options = {
|
@@ -9,6 +11,13 @@ class EmailValidator < ActiveModel::EachValidator
|
|
9
11
|
}
|
10
12
|
# rubocop:enable Style/ClassVars
|
11
13
|
|
14
|
+
# EmailValidator::Error class
|
15
|
+
class Error < StandardError
|
16
|
+
def initialize(msg = 'EmailValidator error')
|
17
|
+
super
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
12
21
|
class << self
|
13
22
|
def default_options
|
14
23
|
@@default_options
|
@@ -35,8 +44,11 @@ class EmailValidator < ActiveModel::EachValidator
|
|
35
44
|
loose_regexp(options)
|
36
45
|
when :rfc
|
37
46
|
rfc_regexp(options)
|
38
|
-
|
47
|
+
when :strict
|
48
|
+
options[:require_fqdn] = true
|
39
49
|
strict_regexp(options)
|
50
|
+
else
|
51
|
+
fail EmailValidator::Error, "Validation mode '#{options[:mode]}' is not supported by EmailValidator"
|
40
52
|
end
|
41
53
|
end
|
42
54
|
|
@@ -81,31 +93,38 @@ class EmailValidator < ActiveModel::EachValidator
|
|
81
93
|
end
|
82
94
|
|
83
95
|
def host_label_pattern
|
96
|
+
"#{label_is_correct_length}" \
|
97
|
+
"#{label_contains_no_more_than_one_consecutive_hyphen}" \
|
84
98
|
"#{alnum}(?:#{alnumhy}{,61}#{alnum})?"
|
85
99
|
end
|
86
100
|
|
87
101
|
# splitting this up into separate regex pattern for performance; let's not
|
88
102
|
# try the "contains" pattern unless we have to
|
89
103
|
def domain_label_pattern
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
104
|
+
"#{host_label_pattern}\\.#{tld_label_pattern}"
|
105
|
+
end
|
106
|
+
|
107
|
+
# While, techincally, TLDs can be numeric-only, this is not allowed by ICANN
|
108
|
+
# Ref: ICANN Application Guidebook for new TLDs (June 2012)
|
109
|
+
# says the following starting at page 64:
|
110
|
+
#
|
111
|
+
# > The ASCII label must consist entirely of letters (alphabetic characters a-z)
|
112
|
+
#
|
113
|
+
# -- https://newgtlds.icann.org/en/applicants/agb/guidebook-full-04jun12-en.pdf
|
114
|
+
def tld_label_pattern
|
115
|
+
"#{alpha}{1,64}"
|
97
116
|
end
|
98
117
|
|
99
|
-
def
|
100
|
-
|
118
|
+
def label_is_correct_length
|
119
|
+
'(?=[^.]{1,63}(?:\.|$))'
|
101
120
|
end
|
102
121
|
|
103
|
-
def
|
104
|
-
|
122
|
+
def domain_part_is_correct_length
|
123
|
+
'(?=.{1,255}$)'
|
105
124
|
end
|
106
125
|
|
107
|
-
def
|
108
|
-
|
126
|
+
def label_contains_no_more_than_one_consecutive_hyphen
|
127
|
+
'(?!.*?--.*$)'
|
109
128
|
end
|
110
129
|
|
111
130
|
def atom_char
|
@@ -122,11 +141,11 @@ class EmailValidator < ActiveModel::EachValidator
|
|
122
141
|
def domain_part_pattern(options)
|
123
142
|
return options[:domain].sub(/\./, '\.') if options[:domain].present?
|
124
143
|
return fqdn_pattern if options[:require_fqdn]
|
125
|
-
"
|
144
|
+
"#{domain_part_is_correct_length}(?:#{address_literal}|(?:#{host_label_pattern}\\.)*#{tld_label_pattern})"
|
126
145
|
end
|
127
146
|
|
128
147
|
def fqdn_pattern
|
129
|
-
"(?=.{1,255}$)(?:#{host_label_pattern}\\.)*#{domain_label_pattern}
|
148
|
+
"(?=.{1,255}$)(?:#{host_label_pattern}\\.)*#{domain_label_pattern}"
|
130
149
|
end
|
131
150
|
|
132
151
|
private
|
@@ -146,7 +146,8 @@ RSpec.describe EmailValidator do
|
|
146
146
|
'john.doe@a2.com',
|
147
147
|
'john.doe@2020.a-z.com',
|
148
148
|
'john.doe@2020.a2z.com',
|
149
|
-
'john.doe@2020.12345a6789.com'
|
149
|
+
'john.doe@2020.12345a6789.com',
|
150
|
+
'jonh.doe@163.com'
|
150
151
|
]).flatten.each do |email|
|
151
152
|
context 'when using defaults' do
|
152
153
|
it "'#{email}' should be valid" do
|
@@ -289,20 +290,20 @@ RSpec.describe EmailValidator do
|
|
289
290
|
end
|
290
291
|
|
291
292
|
context 'when in `:strict` mode' do
|
292
|
-
it "'#{email}' should
|
293
|
-
expect(StrictUser.new(:email => email)).
|
293
|
+
it "'#{email}' should be valid" do
|
294
|
+
expect(StrictUser.new(:email => email)).to be_valid
|
294
295
|
end
|
295
296
|
|
296
|
-
it "'#{email}' should
|
297
|
-
expect(described_class).
|
297
|
+
it "'#{email}' should be valid using EmailValidator.valid?" do
|
298
|
+
expect(described_class).to be_valid(email, :mode => :strict)
|
298
299
|
end
|
299
300
|
|
300
|
-
it "'#{email}' should be invalid using EmailValidator.invalid?" do
|
301
|
-
expect(described_class).
|
301
|
+
it "'#{email}' should be not invalid using EmailValidator.invalid?" do
|
302
|
+
expect(described_class).not_to be_invalid(email, :mode => :strict)
|
302
303
|
end
|
303
304
|
|
304
|
-
it "'#{email}' should
|
305
|
-
expect(!!(email.strip =~ described_class.regexp(:mode => :strict))).to be(
|
305
|
+
it "'#{email}' should match the regexp" do
|
306
|
+
expect(!!(email.strip =~ described_class.regexp(:mode => :strict))).to be(true)
|
306
307
|
end
|
307
308
|
end
|
308
309
|
|
@@ -476,6 +477,7 @@ RSpec.describe EmailValidator do
|
|
476
477
|
'host-beginning-with-dot@.example.com',
|
477
478
|
'domain-beginning-with-dash@-example.com',
|
478
479
|
'domain-ending-with-dash@example-.com',
|
480
|
+
'domain-contains-double-dash@foo--example.com',
|
479
481
|
'the-local-part-is-invalid-if-it-is-longer-than-sixty-four-characters@sld.dev',
|
480
482
|
"domain-too-long@t#{".#{'o' * 63}" * 5}.long",
|
481
483
|
"user@example.com<script>alert('hello')</script>"
|
@@ -703,7 +705,8 @@ RSpec.describe EmailValidator do
|
|
703
705
|
]}).concat([
|
704
706
|
'user..-with-double-dots@example.com',
|
705
707
|
'.user-beginning-with-dot@example.com',
|
706
|
-
'user-ending-with-dot.@example.com'
|
708
|
+
'user-ending-with-dot.@example.com',
|
709
|
+
'fully-numeric-tld@example.123'
|
707
710
|
]).flatten.each do |email|
|
708
711
|
context 'when using defaults' do
|
709
712
|
it "#{email.strip} in a model should be valid" do
|
@@ -781,23 +784,24 @@ RSpec.describe EmailValidator do
|
|
781
784
|
end
|
782
785
|
end
|
783
786
|
|
787
|
+
# Strict mode enables `require_fqdn` anyway
|
784
788
|
context 'when in `:strict` mode' do
|
785
789
|
let(:opts) { { :require_fqdn => false, :mode => :strict } }
|
786
790
|
|
787
|
-
it 'is valid' do
|
788
|
-
expect(NonFqdnStrictUser.new(:email => email)).
|
791
|
+
it 'is not valid' do
|
792
|
+
expect(NonFqdnStrictUser.new(:email => email)).not_to be_valid
|
789
793
|
end
|
790
794
|
|
791
|
-
it 'is valid using EmailValidator.valid?' do
|
792
|
-
expect(described_class).
|
795
|
+
it 'is not valid using EmailValidator.valid?' do
|
796
|
+
expect(described_class).not_to be_valid(email, opts)
|
793
797
|
end
|
794
798
|
|
795
|
-
it 'is
|
796
|
-
expect(described_class).
|
799
|
+
it 'is invalid using EmailValidator.invalid?' do
|
800
|
+
expect(described_class).to be_invalid(email, opts)
|
797
801
|
end
|
798
802
|
|
799
803
|
it 'matches the regexp' do
|
800
|
-
expect(!!(email =~ described_class.regexp(opts))).to be(
|
804
|
+
expect(!!(email =~ described_class.regexp(opts))).to be(false)
|
801
805
|
end
|
802
806
|
end
|
803
807
|
|
@@ -1012,4 +1016,36 @@ RSpec.describe EmailValidator do
|
|
1012
1016
|
end
|
1013
1017
|
end
|
1014
1018
|
end
|
1019
|
+
|
1020
|
+
context 'with regexp' do
|
1021
|
+
it 'returns a regexp when asked' do
|
1022
|
+
expect(described_class.regexp).to be_a(Regexp)
|
1023
|
+
end
|
1024
|
+
|
1025
|
+
it 'returns a strict regexp when asked' do
|
1026
|
+
expect(described_class.regexp(:mode => :strict)).to be_a(Regexp)
|
1027
|
+
end
|
1028
|
+
|
1029
|
+
it 'returns a RFC regexp when asked' do
|
1030
|
+
expect(described_class.regexp(:mode => :rfc)).to be_a(Regexp)
|
1031
|
+
end
|
1032
|
+
|
1033
|
+
it 'has different regexp for strict and loose' do
|
1034
|
+
expect(described_class.regexp(:mode => :strict)).not_to eq(described_class.regexp(:mode => :loose))
|
1035
|
+
end
|
1036
|
+
|
1037
|
+
it 'has different regexp for RFC and loose' do
|
1038
|
+
expect(described_class.regexp(:mode => :rfc)).not_to eq(described_class.regexp(:mode => :loose))
|
1039
|
+
end
|
1040
|
+
|
1041
|
+
it 'has different regexp for RFC and strict' do
|
1042
|
+
expect(described_class.regexp(:mode => :rfc)).not_to eq(described_class.regexp(:mode => :strict))
|
1043
|
+
end
|
1044
|
+
end
|
1045
|
+
|
1046
|
+
context 'with invalid `:mode`' do
|
1047
|
+
it 'raises an error' do
|
1048
|
+
expect { described_class.regexp(:mode => :invalid) }.to raise_error(EmailValidator::Error)
|
1049
|
+
end
|
1050
|
+
end
|
1015
1051
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: email_validator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.2.
|
4
|
+
version: 2.2.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brian Alexander
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2021-04-05 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activemodel
|