email_validator 1.6.0 → 2.2.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +131 -0
- data/README.md +172 -18
- data/lib/email_validator/rfc.rb +4 -0
- data/lib/email_validator/strict.rb +2 -3
- data/lib/email_validator.rb +152 -16
- data/spec/email_validator_spec.rb +1041 -116
- data/spec/spec_helper.rb +12 -2
- metadata +17 -45
- data/.document +0 -5
- data/.gitignore +0 -22
- data/.travis.yml +0 -7
- data/Changes.md +0 -11
- data/Gemfile +0 -3
- data/Rakefile +0 -10
- data/email_validator.gemspec +0 -23
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: c6952edf85fc0eafbe159b4a3b812731c81361ee0a15f22927e270a3eb885c9d
|
4
|
+
data.tar.gz: 8b5a56e059f652f1822c93cbcec0be9da23842433e9c7e5f97478496ba888ff9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 158307d4196989b8d73872fa91c302ee9eab174b25f0686f3d61fe395796fa0b8e6c1c08185a4accf6c9581e23ba66bbebb8e3e8dc46b7ded935ed80a2484b53
|
7
|
+
data.tar.gz: 7f9ccf405a9bcf08d809fa58819d9e6d8489871a52020115802f3c755eddc3962b3533928f8f7c40e8122b055ad185c6f72cf1878ad6c920ba1b86872c0362a8
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
# CHANGELOG
|
2
|
+
|
3
|
+
This file is used to list changes made in `email_validator`.
|
4
|
+
|
5
|
+
All notable changes to this project will be documented in this file.
|
6
|
+
This project adheres to [Semantic Versioning](http://semver.org/).
|
7
|
+
|
8
|
+
## 2.2.4 (2022-11-09)
|
9
|
+
|
10
|
+
* [karlwilbur] - Remove Ruby 2.4 from tested versions; add Ruby 3.0 and 3.1 to tested versions
|
11
|
+
* [karlwilbur] - Fix issue where `domain: ''` wasn't requiring empty domain
|
12
|
+
* [karlwilbur] - Remove checks for double hyphens (fixes [#87](https://github.com/K-and-R/email_validator/issues/87))
|
13
|
+
* [dependabot] - Security updates
|
14
|
+
- [#89](https://github.com/K-and-R/email_validator/pull/89)
|
15
|
+
+ Bump `minimist` from `1.2.5` to `1.2.7`
|
16
|
+
- [#86](https://github.com/K-and-R/email_validator/pull/86)
|
17
|
+
+ Bump `node-fetch` from `2.6.1` to `2.6.7`
|
18
|
+
+ Add `whatwg-url` at `5.0.0`
|
19
|
+
+ Add `tr46` at `0.0.3`
|
20
|
+
+ Add `webidl-conversions` at `3.0.0`
|
21
|
+
- [#80](https://github.com/K-and-R/email_validator/pull/80)
|
22
|
+
+ Bump `tar` from `6.0.5` to `6.1.11`
|
23
|
+
+ Bump `minipass` from `3.1.3` to `3.1.5`
|
24
|
+
- [#79](https://github.com/K-and-R/email_validator/pull/79)
|
25
|
+
+ Bump `path-parse` from `1.0.6` to `1.0.7`
|
26
|
+
- [#76](https://github.com/K-and-R/email_validator/pull/76)
|
27
|
+
+ Bump `lodash` from `4.17.20` to `4.17.21`
|
28
|
+
- [#75](https://github.com/K-and-R/email_validator/pull/75)
|
29
|
+
+ Bump `hosted-git-info` from `2.8.8` to `2.8.9`
|
30
|
+
* [msands] - Fix URL in `README.md` [#81](https://github.com/K-and-R/email_validator/pull/81)
|
31
|
+
* [kerolloz] - Fix typo in `README.md` [#73](https://github.com/K-and-R/email_validator/pull/73)
|
32
|
+
|
33
|
+
## 2.2.3 (2021-04-05)
|
34
|
+
|
35
|
+
* [karlwilbur] - Fix regexp for numeric domains (fixes [#72](https://github.com/K-and-R/email_validator/issues/72))
|
36
|
+
- [delphaber] - Add checks for numeric-only domains in tests (should be considered valid)
|
37
|
+
- [karlwilbur] - Fix specs for numeric-only domains labels (should be considered valid)
|
38
|
+
- [karlwilbur] - Add checks for numeric-only TLDs in tests (should be considered invalid)
|
39
|
+
- [karlwilbur] - Add tests to ensure that `regexp` returns expected value
|
40
|
+
* [karlwilbur] - Add checks for double dash in domain (should be considered invalid)
|
41
|
+
* [karlwilbur] - Add `EmailValidator::Error` class, raise `EmailValidator::Error` when invalid `mode`
|
42
|
+
|
43
|
+
## 2.2.2 (2020-12-10)
|
44
|
+
|
45
|
+
* [karlwilbur] - Fix includes for `:rfc` and `:strict` modes from `Gemfile`
|
46
|
+
|
47
|
+
## 2.2.1 (2020-12-10)
|
48
|
+
|
49
|
+
* [karlwilbur] - Modify regexp to:
|
50
|
+
- allow numeric-only hosts [#68]
|
51
|
+
- allow mailbox-only addresses in `:rfc` mode
|
52
|
+
- enforce the 255-char domain limit (not in `:loose` mode unless using `:domain`)
|
53
|
+
|
54
|
+
## 2.2.0 (2020-12-09)
|
55
|
+
|
56
|
+
* [karlwilbur] - Rename `:strict` -> `:rfc`; `:moderate` -> `:strict`
|
57
|
+
|
58
|
+
## 2.1.0 (2020-12-09)
|
59
|
+
|
60
|
+
* [karlwilbur] - Add linters and commit hooks to validate code prior to commits
|
61
|
+
* [karlwilbur] - Add `:mode` config option; values `:loose`, `:moderate`, `:strict`; default to `:loose`
|
62
|
+
* [karlwilbur] - Merge in changes from <https://github.com/karlwilbur/email_validator> fork
|
63
|
+
|
64
|
+
## 1.9.0.pre (2020-10-14)
|
65
|
+
|
66
|
+
* [karlwilbur] - Add `require_fqdn` option, require FQDN by default
|
67
|
+
* [karlwilbur] - Add support for IPv4 and IPv6 address hosts
|
68
|
+
* [karlwilbur] - Add Rubocop, `.editorconfig`; code cleanup/linting
|
69
|
+
|
70
|
+
## 1.8.0 (2019-06-14)
|
71
|
+
|
72
|
+
* [karlwilbur] - Refactor class methods for readability
|
73
|
+
* [karlwilbur] - `gemspec` meta updates
|
74
|
+
* [karlwilbur] - Use POSIX classes for better performance
|
75
|
+
* [karlwilbur] - Refactored tests to check specical characters one at a time
|
76
|
+
* [karlwilbur] - Refactored validation regex to be more techincally correct
|
77
|
+
* [karlwilbur] - Add this `CHANGELOG`
|
78
|
+
|
79
|
+
## 1.7.0 (2019-04-20)
|
80
|
+
|
81
|
+
* [karlwilbur] - Added test coverage badge to README
|
82
|
+
* [karlwilbur] - Added I18n directive to remove warning message in testing
|
83
|
+
* [karlwilbur] - Added RFC-2822 reference
|
84
|
+
* [karlwilbur] - Ignore local rspec config file
|
85
|
+
* [karlwilbur] - Check for invalid double dots in strict mode
|
86
|
+
* [karlwilbur] - Updated spec_helper to remove Code Climate Test Reporter; it is to be run separately now
|
87
|
+
* [karlwilbur] - Allow leading/trailing whitespace in normal, not strict
|
88
|
+
* [karlwilbur] - Added `invalid?` as inverse of `valid?`
|
89
|
+
* [karlwilbur] - Add the ability to limit to a domain
|
90
|
+
* [karlwilbur] - Removed CodeShip badge
|
91
|
+
* [karlwilbur] - Make the dot in the domain part non-conditional
|
92
|
+
* [karlwilbur] - Fix domain label pattern to allow numbers per rfc5321
|
93
|
+
|
94
|
+
## 1.6.0 (2015-06-14)
|
95
|
+
|
96
|
+
* [karlwilbur] - Fixed validation to be closer to RFC-5321
|
97
|
+
* [karlwilbur] - Updated specs to use Rspec 3 syntax
|
98
|
+
* [karlwilbur] - Added unicode suport to validation regexp
|
99
|
+
* [karlwilbur] - Added class access to regexp, and `valid?` calss method
|
100
|
+
* [karlwilbur] - Simplified code using new methods
|
101
|
+
* [karlwilbur] - Added CodeClimate and SimpleCov
|
102
|
+
* [karlwilbur] - Updated version and contact info
|
103
|
+
|
104
|
+
*** Forked from <https://github.com/balexand/email_validator>
|
105
|
+
|
106
|
+
## 2.0.1 (2019-03-09)
|
107
|
+
|
108
|
+
* Add email value to error details [f1sherman #50]
|
109
|
+
* CI doesn't test Ruby versions that no longer receive updates [f1sherman #51]
|
110
|
+
|
111
|
+
## 2.0.0 (2019-03-02)
|
112
|
+
|
113
|
+
* Looser validation [#49]
|
114
|
+
|
115
|
+
## 1.6.0 (2015-05-12)
|
116
|
+
|
117
|
+
* Unicode characters support [i7an #24]
|
118
|
+
|
119
|
+
## 1.5.0 (2014-12-08)
|
120
|
+
|
121
|
+
* Add a class method for simpler validation [TiteiKo and cluesque #19]
|
122
|
+
* RSpec 3.0 syntax [strivedi183 #17]
|
123
|
+
* Create Changes.md
|
124
|
+
|
125
|
+
---
|
126
|
+
|
127
|
+
Check the [Markdown Syntax Guide](http://daringfireball.net/projects/markdown/syntax)
|
128
|
+
for help with Markdown.
|
129
|
+
|
130
|
+
The [Github Flavored Markdown page](http://github.github.com/github-flavored-markdown/)
|
131
|
+
describes the differences between markdown on github and standard markdown.
|
data/README.md
CHANGED
@@ -1,6 +1,29 @@
|
|
1
|
-
|
1
|
+
# EmailValidator
|
2
2
|
|
3
|
-
|
3
|
+
[![Build Status](https://travis-ci.com/K-and-R/email_validator.svg?branch=master)](http://travis-ci.com/K-and-R/email_validator)
|
4
|
+
[![Code Climate](https://codeclimate.com/github/K-and-R/email_validator/badges/gpa.svg)](https://codeclimate.com/github/K-and-R/email_validator)
|
5
|
+
[![Test Coverage](https://codeclimate.com/github/K-and-R/email_validator/badges/coverage.svg)](https://codeclimate.com/github/K-and-R/email_validator/coverage)
|
6
|
+
|
7
|
+
An email validator for Rails 3+.
|
8
|
+
|
9
|
+
Supports RFC-2822-compliant and RFC-5321-compliant email validation using RFC-3696 validation.
|
10
|
+
|
11
|
+
Formerly found at: <https://github.com/balexand/email_validator>
|
12
|
+
|
13
|
+
## Validation philosophy
|
14
|
+
|
15
|
+
The default validation provided by this gem (the `:loose` configuration option)
|
16
|
+
is extremely loose. It just checks that there's an `@` with something before and
|
17
|
+
after it without any whitespace. See [this article by David Gilbertson](https://medium.com/hackernoon/the-100-correct-way-to-validate-email-addresses-7c4818f24643)
|
18
|
+
for an explanation of why.
|
19
|
+
|
20
|
+
We understand that many use cases require an increased level of validation. This
|
21
|
+
is supported by using the `:strict` validation mode. Additionally, the `:rfc`
|
22
|
+
RFC-compliant mode will consider technically valid emails address as valid which
|
23
|
+
may not be wanted, such as the valid `user` or `user@somehost` addresses. These
|
24
|
+
would be valid in `:rfc` mode but not valid in `:loose` or `:strict`.
|
25
|
+
|
26
|
+
## Installation
|
4
27
|
|
5
28
|
Add to your Gemfile:
|
6
29
|
|
@@ -10,54 +33,185 @@ gem 'email_validator'
|
|
10
33
|
|
11
34
|
Run:
|
12
35
|
|
13
|
-
```
|
36
|
+
```bash
|
14
37
|
bundle install
|
15
38
|
```
|
16
39
|
|
17
|
-
|
40
|
+
## Usage
|
41
|
+
|
42
|
+
Add the following to your model:
|
18
43
|
|
19
44
|
```ruby
|
20
|
-
validates :my_email_attribute, :
|
45
|
+
validates :my_email_attribute, email: true
|
21
46
|
```
|
22
47
|
|
23
|
-
|
48
|
+
You may wish to allow domains without a FQDN, like `user@somehost`. While this
|
49
|
+
is technically a valid address, it is uncommon to consider such address valid.
|
50
|
+
We will consider them valid by default with the `:loose` checking. Disallowed
|
51
|
+
by setting `require_fqdn: true` or by enabling `:strict` checking:
|
52
|
+
|
53
|
+
```ruby
|
54
|
+
validates :my_email_attribute, email: {mode: :strict, require_fqdn: true}
|
55
|
+
```
|
24
56
|
|
25
|
-
|
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):
|
26
60
|
|
27
61
|
```ruby
|
28
|
-
|
62
|
+
validates :my_email_attribute, email: {domain: 'example.com'}
|
29
63
|
```
|
30
64
|
|
31
|
-
|
65
|
+
## Configuration
|
66
|
+
|
67
|
+
Default configuration can be overridden by setting options in `config/initializers/email_validator.rb`:
|
32
68
|
|
33
69
|
```ruby
|
34
|
-
|
70
|
+
if defined?(EmailValidator)
|
71
|
+
# To completely override the defaults
|
72
|
+
EmailValidator.default_options = {
|
73
|
+
allow_nil: false,
|
74
|
+
domain: nil,
|
75
|
+
require_fqdn: nil,
|
76
|
+
mode: :loose
|
77
|
+
}
|
78
|
+
|
79
|
+
# or just a few options
|
80
|
+
EmailValidator.default_options.merge!({ domain: 'mydomain.com' })
|
81
|
+
end
|
35
82
|
```
|
36
83
|
|
84
|
+
### Loose mode
|
85
|
+
|
86
|
+
This it the default validation mode of this gem. It is intentionally extremely
|
87
|
+
loose (see the [Validation Philosophy section](#validation_philosophy) above. It
|
88
|
+
just checks that there's an `@` with something before and after it without any
|
89
|
+
whitespace.
|
90
|
+
|
91
|
+
### Strict mode
|
92
|
+
|
93
|
+
Enabling `:strict` checking will check for a "normal" email format that would
|
94
|
+
be expected in most common everyday usage. Strict mode basically checks for a
|
95
|
+
properly sized and formatted mailbox label, a single "@" symbol, and a properly
|
96
|
+
sized and formatted FQDN. Enabling `:strict` mode will also enable `:require_fqdn`
|
97
|
+
configuration option.
|
98
|
+
|
99
|
+
Strict mode can be enabled globally by requiring `email_validator/strict` in
|
100
|
+
your `Gemfile`, by setting the option in `config/initializers/email_validator.rb`,
|
101
|
+
or by specifying the option in a specific `validates` call.
|
102
|
+
|
103
|
+
* `Gemfile`:
|
104
|
+
|
105
|
+
```ruby
|
106
|
+
gem 'email_validator', require: 'email_validator/strict'
|
107
|
+
```
|
108
|
+
|
109
|
+
* `config/initializers/email_validator.rb`:
|
110
|
+
|
111
|
+
```ruby
|
112
|
+
if defined?(EmailValidator)
|
113
|
+
EmailValidator.default_options[:mode] = :strict
|
114
|
+
end
|
115
|
+
```
|
116
|
+
|
117
|
+
* `validates` call:
|
118
|
+
|
119
|
+
```ruby
|
120
|
+
validates :my_email_attribute, email: {mode: :strict}
|
121
|
+
```
|
122
|
+
|
123
|
+
### RFC mode
|
124
|
+
|
125
|
+
In order to have RFC-compliant validation (according to [http://www.remote.org/jochen/mail/info/chars.html](https://web.archive.org/web/20150508102948/http://www.remote.org/jochen/mail/info/chars.html)),
|
126
|
+
enable `:rfc` mode.
|
127
|
+
|
128
|
+
You can do this globally by requiring `email_validator/rfc` in your `Gemfile`,
|
129
|
+
by setting the options in `config/initializers/email_validator.rb`, or you can do
|
130
|
+
this in a specific `validates` call.
|
131
|
+
|
132
|
+
* `Gemfile`:
|
133
|
+
|
134
|
+
```ruby
|
135
|
+
gem 'email_validator', require: 'email_validator/rfc'
|
136
|
+
```
|
137
|
+
|
138
|
+
* `config/initializers/email_validator.rb`:
|
139
|
+
|
140
|
+
```ruby
|
141
|
+
if defined?(EmailValidator)
|
142
|
+
EmailValidator.default_options[:mode] = :rfc
|
143
|
+
end
|
144
|
+
```
|
145
|
+
|
146
|
+
* `validates` call:
|
147
|
+
|
148
|
+
```ruby
|
149
|
+
validates :my_email_attribute, email: {mode: :rfc}
|
150
|
+
```
|
151
|
+
|
37
152
|
## Validation outside a model
|
38
153
|
|
39
|
-
If you need to validate an email outside a model, you can get the regexp
|
154
|
+
If you need to validate an email outside a model, you can get the regexp:
|
40
155
|
|
41
|
-
###
|
156
|
+
### Loose/default mode
|
42
157
|
|
43
158
|
```ruby
|
44
|
-
EmailValidator.regexp # returns the regex
|
45
159
|
EmailValidator.valid?('narf@example.com') # boolean
|
46
160
|
```
|
47
161
|
|
162
|
+
### Requiring a FQDN
|
163
|
+
|
164
|
+
```ruby
|
165
|
+
EmailValidator.valid?('narf@somehost') # boolean false
|
166
|
+
EmailValidator.invalid?('narf@somehost', require_fqdn: false) # boolean true
|
167
|
+
```
|
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
|
+
|
173
|
+
### Requiring a specific domain
|
174
|
+
|
175
|
+
```ruby
|
176
|
+
EmailValidator.valid?('narf@example.com', domain: 'foo.com') # boolean false
|
177
|
+
EmailValidator.invalid?('narf@example.com', domain: 'foo.com') # boolean true
|
178
|
+
```
|
179
|
+
|
48
180
|
### Strict mode
|
49
181
|
|
50
182
|
```ruby
|
51
|
-
EmailValidator.regexp(:
|
183
|
+
EmailValidator.regexp(mode: :strict) # returns the regex
|
184
|
+
EmailValidator.valid?('narf@example.com', mode: :strict) # boolean
|
185
|
+
```
|
186
|
+
|
187
|
+
### RFC mode
|
188
|
+
|
189
|
+
```ruby
|
190
|
+
EmailValidator.regexp(mode: :rfc) # returns the regex
|
191
|
+
EmailValidator.valid?('narf@example.com', mode: :rfc) # boolean
|
52
192
|
```
|
53
193
|
|
54
194
|
## Thread safety
|
55
195
|
|
56
|
-
This gem is thread safe, with one caveat: `EmailValidator.default_options` must
|
196
|
+
This gem is thread safe, with one caveat: `EmailValidator.default_options` must
|
197
|
+
be configured before use in a multi-threaded environment. If you configure
|
198
|
+
`default_options` in a Rails initializer file, then you're good to go since
|
199
|
+
initializers are run before worker threads are spawned.
|
200
|
+
|
201
|
+
## Alternative gems
|
202
|
+
|
203
|
+
Do you prefer a different email validation gem? If so, open an issue with a brief
|
204
|
+
explanation of how it differs from this gem. I'll add a link to it in this README.
|
205
|
+
|
206
|
+
* [`email_address`](https://github.com/afair/email_address) (<https://github.com/K-and-R/email_validator/issues/58>)
|
207
|
+
* [`email_verifier`](https://github.com/kamilc/email_verifier) (<https://github.com/K-and-R/email_validator/issues/65>)
|
57
208
|
|
58
|
-
##
|
209
|
+
## Maintainers
|
59
210
|
|
60
|
-
|
211
|
+
All thanks is given to [Brian Alexander (balexand)](https://github.com/balexand)
|
212
|
+
for is initial work on this gem.
|
61
213
|
|
62
|
-
|
214
|
+
Currently maintained by:
|
63
215
|
|
216
|
+
* Karl Wilbur (<https://github.com/karlwilbur>)
|
217
|
+
* K&R Software (<https://github.com/K-and-R>)
|
data/lib/email_validator.rb
CHANGED
@@ -1,29 +1,165 @@
|
|
1
|
-
# encoding: UTF-8
|
2
1
|
# Based on work from http://thelucid.com/2010/01/08/sexy-validation-in-edge-rails-rails-3/
|
2
|
+
|
3
|
+
# EmailValidator class
|
3
4
|
class EmailValidator < ActiveModel::EachValidator
|
4
|
-
|
5
|
+
# rubocop:disable Style/ClassVars
|
6
|
+
@@default_options = {
|
7
|
+
:allow_nil => false,
|
8
|
+
:domain => nil,
|
9
|
+
:require_fqdn => nil,
|
10
|
+
:mode => :loose
|
11
|
+
}
|
12
|
+
# rubocop:enable Style/ClassVars
|
5
13
|
|
6
|
-
|
7
|
-
|
14
|
+
# EmailValidator::Error class
|
15
|
+
class Error < StandardError
|
16
|
+
def initialize(msg = 'EmailValidator error')
|
17
|
+
super
|
18
|
+
end
|
19
|
+
end
|
8
20
|
|
9
|
-
|
21
|
+
class << self
|
22
|
+
def default_options
|
23
|
+
@@default_options
|
24
|
+
end
|
10
25
|
|
11
|
-
|
12
|
-
|
26
|
+
def valid?(value, options = {})
|
27
|
+
options = parse_options(options)
|
28
|
+
return true if value.nil? && options[:allow_nil] == true
|
29
|
+
return false if value.nil?
|
30
|
+
# quickly fail if domain is required but doesn't match
|
31
|
+
return false unless options[:domain].nil? || value[/^.*@#{regexp_safe_domain(options)}$/]
|
32
|
+
!!(value =~ regexp(options))
|
33
|
+
end
|
13
34
|
|
14
|
-
|
15
|
-
|
16
|
-
|
35
|
+
def invalid?(value, options = {})
|
36
|
+
!valid?(value, options)
|
37
|
+
end
|
38
|
+
|
39
|
+
# Refs:
|
40
|
+
# https://tools.ietf.org/html/rfc2822 : 3.2. Lexical Tokens, 3.4.1. Addr-spec specification
|
41
|
+
# https://tools.ietf.org/html/rfc5321 : 4.1.2. Command Argument Syntax
|
42
|
+
def regexp(options = {})
|
43
|
+
options = parse_options(options)
|
44
|
+
case options[:mode]
|
45
|
+
when :loose
|
46
|
+
loose_regexp(options)
|
47
|
+
when :rfc
|
48
|
+
rfc_regexp(options)
|
49
|
+
when :strict
|
50
|
+
options[:require_fqdn] = true
|
51
|
+
strict_regexp(options)
|
52
|
+
else
|
53
|
+
fail EmailValidator::Error, "Validation mode '#{options[:mode]}' is not supported by EmailValidator"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
protected
|
58
|
+
|
59
|
+
def loose_regexp(options = {})
|
60
|
+
return /\A[^\s]+@[^\s]+\z/ if options[:domain].nil?
|
61
|
+
/\A[^\s]+@#{domain_part_pattern(options)}\z/
|
62
|
+
end
|
63
|
+
|
64
|
+
def strict_regexp(options = {})
|
65
|
+
/\A(?>#{local_part_pattern})@#{domain_part_pattern(options)}\z/i
|
66
|
+
end
|
67
|
+
|
68
|
+
def rfc_regexp(options = {})
|
69
|
+
/\A(?>#{local_part_pattern})(?:@#{domain_part_pattern(options)})?\z/i
|
70
|
+
end
|
71
|
+
|
72
|
+
def alpha
|
73
|
+
'[[:alpha:]]'
|
74
|
+
end
|
75
|
+
|
76
|
+
def alnum
|
77
|
+
'[[:alnum:]]'
|
78
|
+
end
|
79
|
+
|
80
|
+
def alnumhy
|
81
|
+
"(?:#{alnum}|-)"
|
82
|
+
end
|
83
|
+
|
84
|
+
def ipv4
|
85
|
+
'\d{1,3}(?:\.\d{1,3}){3}'
|
86
|
+
end
|
87
|
+
|
88
|
+
def ipv6
|
89
|
+
# only supporting full IPv6 addresses right now
|
90
|
+
'IPv6:[[:xdigit:]]{1,4}(?::[[:xdigit:]]{1,4}){7}'
|
91
|
+
end
|
17
92
|
|
18
|
-
|
19
|
-
|
93
|
+
def address_literal
|
94
|
+
"\\[(?:#{ipv4}|#{ipv6})\\]"
|
95
|
+
end
|
96
|
+
|
97
|
+
def host_label_pattern
|
98
|
+
"#{label_is_correct_length}" \
|
99
|
+
"#{alnum}(?:#{alnumhy}{,61}#{alnum})?"
|
100
|
+
end
|
101
|
+
|
102
|
+
# splitting this up into separate regex pattern for performance; let's not
|
103
|
+
# try the "contains" pattern unless we have to
|
104
|
+
def domain_label_pattern
|
105
|
+
"#{host_label_pattern}\\.#{tld_label_pattern}"
|
106
|
+
end
|
107
|
+
|
108
|
+
# While, techincally, TLDs can be numeric-only, this is not allowed by ICANN
|
109
|
+
# Ref: ICANN Application Guidebook for new TLDs (June 2012)
|
110
|
+
# says the following starting at page 64:
|
111
|
+
#
|
112
|
+
# > The ASCII label must consist entirely of letters (alphabetic characters a-z)
|
113
|
+
#
|
114
|
+
# -- https://newgtlds.icann.org/en/applicants/agb/guidebook-full-04jun12-en.pdf
|
115
|
+
def tld_label_pattern
|
116
|
+
"#{alpha}{1,64}"
|
117
|
+
end
|
118
|
+
|
119
|
+
def label_is_correct_length
|
120
|
+
'(?=[^.]{1,63}(?:\.|$))'
|
121
|
+
end
|
122
|
+
|
123
|
+
def domain_part_is_correct_length
|
124
|
+
'(?=.{1,255}$)'
|
125
|
+
end
|
126
|
+
|
127
|
+
def atom_char
|
128
|
+
# The `atext` spec
|
129
|
+
# We are looking at this without whitespace; no whitespace support here
|
130
|
+
"[-#{alpha}#{alnum}+_!\"'#$%^&*{}/=?`|~]"
|
131
|
+
end
|
132
|
+
|
133
|
+
def local_part_pattern
|
134
|
+
# the `dot-atom-text` spec, but with a 64 character limit
|
135
|
+
"#{atom_char}(?:\\.?#{atom_char}){,63}"
|
136
|
+
end
|
137
|
+
|
138
|
+
def domain_part_pattern(options)
|
139
|
+
return regexp_safe_domain(options) unless options[:domain].nil?
|
140
|
+
return fqdn_pattern if options[:require_fqdn]
|
141
|
+
"#{domain_part_is_correct_length}(?:#{address_literal}|(?:#{host_label_pattern}\\.)*#{tld_label_pattern})"
|
142
|
+
end
|
143
|
+
|
144
|
+
def fqdn_pattern
|
145
|
+
"(?=.{1,255}$)(?:#{host_label_pattern}\\.)*#{domain_label_pattern}"
|
146
|
+
end
|
147
|
+
|
148
|
+
private
|
149
|
+
|
150
|
+
def parse_options(options)
|
151
|
+
# `:strict` mode enables `:require_fqdn`, unless it is already explicitly disabled
|
152
|
+
options[:require_fqdn] = true if options[:require_fqdn].nil? && options[:mode] == :strict
|
153
|
+
default_options.merge(options)
|
154
|
+
end
|
155
|
+
|
156
|
+
def regexp_safe_domain(options)
|
157
|
+
options[:domain].sub(/\./, '\.')
|
158
|
+
end
|
20
159
|
end
|
21
160
|
|
22
161
|
def validate_each(record, attribute, value)
|
23
162
|
options = @@default_options.merge(self.options)
|
24
|
-
|
25
|
-
unless self.class.valid?(value, self.options)
|
26
|
-
record.errors.add(attribute, options[:message] || :invalid)
|
27
|
-
end
|
163
|
+
record.errors.add(attribute, options[:message] || :invalid) unless self.class.valid?(value, options)
|
28
164
|
end
|
29
165
|
end
|