email_address 0.2.6 โ 0.2.7
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/README.md +98 -231
- data/lib/email_address/address.rb +1 -1
- data/lib/email_address/config.rb +2 -2
- data/lib/email_address/local.rb +21 -33
- data/lib/email_address/version.rb +1 -1
- data/test/email_address/test_address.rb +10 -3
- data/test/email_address/test_config.rb +4 -4
- data/test/email_address/test_host.rb +6 -6
- data/test/email_address/test_local.rb +8 -3
- data/test/test_helper.rb +6 -0
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: '09a47fb94c722c1b77e1b88f60eb9b275c10b0af362b7e951688b16edb8b8956'
|
|
4
|
+
data.tar.gz: 518cd6502197567e1819218bff259a596eae8d5521d89c69a4dd3d691047b04a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ed80c20ef002dca0ec0280e2a3e418b4f77811dcac90ee338e186a39b88151817aed715e5cf50aea20755fcd1a3aec5df7dba9ed4381d540da861b51a33c1326
|
|
7
|
+
data.tar.gz: 387e799ca2eef4de99232f36d2a8be0bcc69d3616d49cb2f499c856595c6abb2ac7ae02b9d9d5c3b667356a645700ffc03a59124997daa00354d22b22d26d29d
|
data/README.md
CHANGED
|
@@ -4,29 +4,66 @@
|
|
|
4
4
|
[](https://github.com/afair/email_address/actions/workflows/ci.yml)
|
|
5
5
|
[](https://codeclimate.com/github/afair/email_address)
|
|
6
6
|
|
|
7
|
-
The `email_address` gem
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
7
|
+
The `email_address` ruby gem is an opinionated validation library for
|
|
8
|
+
email addresses. The [RFC 5322](https://www.rfc-editor.org/rfc/rfc5322#section-3.4)
|
|
9
|
+
address specification defines them as extensions to the email
|
|
10
|
+
header syntax, not as a useful method for creating email transport
|
|
11
|
+
systems with user accounts, mailboxes, and routing.
|
|
12
|
+
|
|
13
|
+
The library follows "real world" email address patterns for end-user addresses.
|
|
14
|
+
|
|
15
|
+
- "Conventional" format (the default) fits most user email accounts
|
|
16
|
+
as created by major email service providers and software.
|
|
17
|
+
Only 7-bit ASCII characters are supported in the local (left) part.
|
|
18
|
+
- "Relaxed" format loosely follows conventional, allowing a looser
|
|
19
|
+
punctuation format.
|
|
20
|
+
- "Standard" format follows the RFC. This is provided for non-user
|
|
21
|
+
addresses, such as uniquely-generated destinations for
|
|
22
|
+
consumption between automated systems.
|
|
23
|
+
|
|
24
|
+
RFC "Standard" Addresses allow syntaxes that most developers do not want:
|
|
25
|
+
|
|
26
|
+
- Mailboxes are case-sensitive.
|
|
27
|
+
- Double-quoted tokens can contain spaces, "@" symbols, and unusual punctuation.
|
|
28
|
+
- Parenthetical comment fields can appear at the beginning or end
|
|
29
|
+
of the local (left) part.
|
|
30
|
+
- Addresses do not have to have fully-qualified domain names
|
|
31
|
+
- The Host part (after the "@") can be an IP Address
|
|
32
|
+
|
|
33
|
+
Additionally, this library respects "address tags", a convention
|
|
34
|
+
not specified by the RFC, with which email providers and software
|
|
35
|
+
append an identifier or route to the mailbox, usually after a "+" symbol.
|
|
36
|
+
|
|
37
|
+
Configuration options include specialized address formats for the largest
|
|
38
|
+
ESP (Email service providers) to validate against their formats.
|
|
39
|
+
|
|
40
|
+
If you have false negatives with "conventional" format, try the
|
|
41
|
+
`local_format: :relaxed` option. To validate to the RFC only, use the
|
|
42
|
+
`local_format: :standard` option. When possible, confirm the address
|
|
43
|
+
with the user if conventional check fails but relaxed succeeds.
|
|
44
|
+
|
|
45
|
+
Remember: the only true way to validate an email address is to successfully
|
|
46
|
+
send email to it. SMTP checks can help, but should only be done politely
|
|
47
|
+
to avoid blacklisting your application. Several (unaffiliated) services
|
|
48
|
+
exist to do this for you.
|
|
49
|
+
|
|
50
|
+
Finally, there are conveniences to handle storage and management of
|
|
51
|
+
address digests for PII removal or sharing addresses without revealing them.
|
|
52
|
+
|
|
53
|
+
The gem requires ruby only, but includes a, optional Ruby on Rails helper for
|
|
54
|
+
those who need to use it with ActiveRecord.
|
|
24
55
|
|
|
25
56
|
Looking for a Javascript version of this library? Check out the
|
|
26
57
|
[email_address](https://www.npmjs.com/package/email_address) npm module.
|
|
27
58
|
|
|
28
59
|
## Quick Start
|
|
29
60
|
|
|
61
|
+
Install the gem to your project with bundler:
|
|
62
|
+
|
|
63
|
+
bundle add email_address
|
|
64
|
+
|
|
65
|
+
or with the gem command:
|
|
66
|
+
|
|
30
67
|
To quickly validate email addresses, use the valid? and error helpers.
|
|
31
68
|
`valid?` returns a boolean, and `error` returns nil if valid, otherwise
|
|
32
69
|
a basic error message.
|
|
@@ -38,19 +75,19 @@ EmailAddress.error "allen@bad-d0main.com" #=> "Invalid Host/Domain Name"
|
|
|
38
75
|
|
|
39
76
|
`EmailAddress` deeply validates your email addresses. It checks:
|
|
40
77
|
|
|
41
|
-
|
|
42
|
-
|
|
78
|
+
- Host name format and DNS setup
|
|
79
|
+
- Mailbox format according to "conventional" form. This matches most used user
|
|
43
80
|
email accounts, but is a subset of the RFC specification.
|
|
44
81
|
|
|
45
82
|
It does not check:
|
|
46
83
|
|
|
47
|
-
|
|
48
|
-
|
|
84
|
+
- The mail server is configured to accept connections
|
|
85
|
+
- The mailbox is valid and accepts email.
|
|
49
86
|
|
|
50
87
|
By default, MX records are required in DNS. MX or "mail exchanger" records
|
|
51
88
|
tell where to deliver email for the domain. Many domains run their
|
|
52
89
|
website on one provider (ISP, Heroku, etc.), and email on a different
|
|
53
|
-
provider (such as G Suite).
|
|
90
|
+
provider (such as G Suite). Note that `example.com`, while
|
|
54
91
|
a valid domain name, does not have MX records.
|
|
55
92
|
|
|
56
93
|
```ruby
|
|
@@ -71,134 +108,91 @@ The email address specification is complex and often not what you want
|
|
|
71
108
|
when working with personal email addresses in applications. This library
|
|
72
109
|
introduces terms to distinguish types of email addresses.
|
|
73
110
|
|
|
74
|
-
|
|
111
|
+
- _Normal_ - The edited form of any input email address. Typically, it
|
|
75
112
|
is lower-cased and minor "fixes" can be performed, depending on the
|
|
76
113
|
configurations and email address provider.
|
|
77
114
|
|
|
78
|
-
|
|
115
|
+
<CKENT@DAILYPLANET.NEWS> => <ckent@dailyplanet.news>
|
|
79
116
|
|
|
80
|
-
|
|
117
|
+
- _Conventional_ - Most personal account addresses are in this basic
|
|
81
118
|
format, one or more "words" separated by a single simple punctuation
|
|
82
119
|
character. It consists of a mailbox (user name or role account) and
|
|
83
120
|
an optional address "tag" assigned by the user.
|
|
84
121
|
|
|
85
|
-
|
|
122
|
+
miles.o'<brien@ncc-1701-d.ufp>
|
|
86
123
|
|
|
87
|
-
|
|
124
|
+
- _Relaxed_ - A less strict form of Conventional, same character set,
|
|
88
125
|
must begin and end with an alpha-numeric character, but order within
|
|
89
126
|
is not enforced.
|
|
90
127
|
|
|
91
|
-
|
|
128
|
+
<aasdf-34-.z@example.com>
|
|
92
129
|
|
|
93
|
-
|
|
130
|
+
- _Standard_ - The RFC-Compliant syntax of an email address. This is
|
|
94
131
|
useful when working with software-generated addresses or handling
|
|
95
132
|
existing email addresses, but otherwise not useful for personal
|
|
96
133
|
addresses.
|
|
97
134
|
|
|
98
|
-
|
|
135
|
+
madness!."()<>[]:,;@\\\"!#$%&'\*+-/=?^\_`{}| ~.a(comment )"@example.org
|
|
99
136
|
|
|
100
|
-
|
|
137
|
+
- _Base_ - A unique mailbox without tags. For gmail, is uses the incoming
|
|
101
138
|
punctation, essential when building an MD5, SHA1, or SHA256 to match services
|
|
102
139
|
like Gravatar, and email address digest interchange.
|
|
103
140
|
|
|
104
|
-
|
|
141
|
+
- _Canonical_ - An unique account address, lower-cased, without the
|
|
105
142
|
tag, and with irrelevant characters stripped.
|
|
106
143
|
|
|
107
|
-
|
|
144
|
+
<clark.kent+scoops@gmail.com> => <clarkkent@gmail.com>
|
|
108
145
|
|
|
109
|
-
|
|
146
|
+
- _Reference_ - The MD5 of the Base format, used to share account
|
|
110
147
|
references without exposing the private email address directly.
|
|
111
148
|
|
|
112
|
-
|
|
113
|
-
|
|
149
|
+
<Clark.Kent+scoops@gmail.com> =>
|
|
150
|
+
<clark.kent@gmail.com> => 1429a1dfc797d6e93075fef011c373fb
|
|
114
151
|
|
|
115
|
-
|
|
152
|
+
- _Redacted_ - A form of the email address where it is replaced by
|
|
116
153
|
a SHA1-based version to remove the original address from the
|
|
117
154
|
database, or to store the address privately, yet still keep it
|
|
118
155
|
accessible at query time by converting the queried address to
|
|
119
156
|
the redacted form.
|
|
120
157
|
|
|
121
|
-
|
|
158
|
+
<Clark.Kent+scoops@gmail.com> => {bea3f3560a757f8142d38d212a931237b218eb5e}@gmail.com
|
|
122
159
|
|
|
123
|
-
|
|
160
|
+
- _Munged_ - An obfuscated version of the email address suitable for
|
|
124
161
|
publishing on the internet, where email address harvesting
|
|
125
162
|
could occur.
|
|
126
163
|
|
|
127
|
-
|
|
164
|
+
<Clark.Kent+scoops@gmail.com> => cl\*\*\*\*\*@gm\*\*\*\*\*
|
|
128
165
|
|
|
129
166
|
Other terms:
|
|
130
167
|
|
|
131
|
-
|
|
168
|
+
- _Local_ - The left-hand side of the "@", representing the user,
|
|
132
169
|
mailbox, or role, and an optional "tag".
|
|
133
170
|
|
|
134
|
-
|
|
171
|
+
<mailbox+tag@example.com>; Local part: mailbox+tag
|
|
135
172
|
|
|
136
|
-
|
|
137
|
-
|
|
173
|
+
- _Mailbox_ - The destination user account or role account.
|
|
174
|
+
- _Tag_ - A parameter added after the mailbox, usually after the
|
|
138
175
|
"+" symbol, set by the user for mail filtering and sub-accounts.
|
|
139
176
|
Not all mail systems support this.
|
|
140
|
-
|
|
177
|
+
- _Host_ (sometimes called _Domain_) - The right-hand side of the "@"
|
|
141
178
|
indicating the domain or host name server to delivery the email.
|
|
142
179
|
If missing, "localhost" is assumed, or if not a fully-qualified
|
|
143
180
|
domain name, it assumed another computer on the same network, but
|
|
144
181
|
this is increasingly rare.
|
|
145
|
-
|
|
182
|
+
- _Provider_ - The Email Service Provider (ESP) providing the email
|
|
146
183
|
service. Each provider may have its own email address validation
|
|
147
184
|
and canonicalization rules.
|
|
148
|
-
|
|
185
|
+
- _Punycode_ - A host name with Unicode characters (International
|
|
149
186
|
Domain Name or IDN) needs conversion to this ASCII-encoded format
|
|
150
187
|
for DNS lookup.
|
|
151
188
|
|
|
152
|
-
|
|
189
|
+
"HIRO@ใใใซใกใฏไธ็.com" => "<hiro@xn--28j2a3ar1pp75ovm7c.com>"
|
|
153
190
|
|
|
154
191
|
Wikipedia has a great article on
|
|
155
192
|
[Email Addresses](https://en.wikipedia.org/wiki/Email_address),
|
|
156
193
|
much more readable than the section within
|
|
157
194
|
[RFC 5322](https://tools.ietf.org/html/rfc5322#section-3.4)
|
|
158
195
|
|
|
159
|
-
## Avoiding the Bad Parts of RFC Specification
|
|
160
|
-
|
|
161
|
-
Following the RFC specification sounds like a good idea, until you
|
|
162
|
-
learn about all the madness contained therein. This library can
|
|
163
|
-
validate the RFC syntax, but this is never useful, especially when
|
|
164
|
-
validating user email address submissions. By default, it validates
|
|
165
|
-
to the *conventional* format.
|
|
166
|
-
|
|
167
|
-
Here are a few parts of the RFC specification you should avoid:
|
|
168
|
-
|
|
169
|
-
* Case-sensitive local parts: `First.Last@example.com`
|
|
170
|
-
* Spaces and Special Characters: `"():;<>@[\\]`
|
|
171
|
-
* Quoting and Escaping Requirements: `"first \"nickname\" last"@example.com`
|
|
172
|
-
* Comment Parts: `(comment)mailbox@example.com`
|
|
173
|
-
* IP and IPv6 addresses as hosts: `mailbox@[127.0.0.1]`
|
|
174
|
-
* Non-ASCII (7-bit) characters in the local part: `Pelรฉ@example.com`
|
|
175
|
-
* Validation by voodoo regular expressions
|
|
176
|
-
* Gmail allows ".." in addresses since they are not meaningful, but
|
|
177
|
-
the standard does not.
|
|
178
|
-
|
|
179
|
-
## Installation With Rails or Bundler
|
|
180
|
-
|
|
181
|
-
If you are using Rails or a project with Bundler, add this line to your application's Gemfile:
|
|
182
|
-
|
|
183
|
-
gem 'email_address'
|
|
184
|
-
|
|
185
|
-
And then execute:
|
|
186
|
-
|
|
187
|
-
$ bundle
|
|
188
|
-
|
|
189
|
-
## Installation Without Bundler
|
|
190
|
-
|
|
191
|
-
If you are not using Bundler, you need to install the gem yourself.
|
|
192
|
-
|
|
193
|
-
$ gem install email_address
|
|
194
|
-
|
|
195
|
-
Require the gem inside your script.
|
|
196
|
-
|
|
197
|
-
```ruby
|
|
198
|
-
require 'rubygems'
|
|
199
|
-
require 'email_address'
|
|
200
|
-
```
|
|
201
|
-
|
|
202
196
|
## Usage
|
|
203
197
|
|
|
204
198
|
Use `EmailAddress` to do transformations and validations. You can also
|
|
@@ -231,7 +225,7 @@ email.valid? #=> true
|
|
|
231
225
|
|
|
232
226
|
Here are some other methods that are available.
|
|
233
227
|
|
|
234
|
-
|
|
228
|
+
````ruby
|
|
235
229
|
email.redact #=> "{bea3f3560a757f8142d38d212a931237b218eb5e}@gmail.com"
|
|
236
230
|
email.sha1 #=> "bea3f3560a757f8142d38d212a931237b218eb5e"
|
|
237
231
|
email.sha256 #=> "9e2a0270f2d6778e5f647fc9eaf6992705ca183c23d1ed1166586fd54e859f75"
|
|
@@ -248,17 +242,6 @@ EmailAddress.normal("HIRO@ใใใซใกใฏไธ็.com")
|
|
|
248
242
|
#=> "hiro@xn--28j2a3ar1pp75ovm7c.com"
|
|
249
243
|
EmailAddress.normal("hiro@xn--28j2a3ar1pp75ovm7c.com", host_encoding: :unicode)
|
|
250
244
|
#=> "hiro@ใใใซใกใฏไธ็.com"
|
|
251
|
-
```
|
|
252
|
-
As of release 0.1.17, exchanger_match is no longer used for host provider
|
|
253
|
-
determination, which designated the set of rules for that domain.
|
|
254
|
-
Sometimes, as in Google-hosted domains, the address
|
|
255
|
-
rules are different, notably the optional dots in mailboxes for gmail.com
|
|
256
|
-
accounts do not apply to other private domains hosted at google.
|
|
257
|
-
|
|
258
|
-
To access the provider service, you can now call:
|
|
259
|
-
|
|
260
|
-
EmailAddress.new("user@hosteddomain.com").host.hosted_provider
|
|
261
|
-
|
|
262
245
|
|
|
263
246
|
#### Rails Validator
|
|
264
247
|
|
|
@@ -271,7 +254,7 @@ Specify your email address attributes with `field: :user_email`, or
|
|
|
271
254
|
class User < ActiveRecord::Base
|
|
272
255
|
validates_with EmailAddress::ActiveRecordValidator, field: :email
|
|
273
256
|
end
|
|
274
|
-
|
|
257
|
+
````
|
|
275
258
|
|
|
276
259
|
#### Rails I18n
|
|
277
260
|
|
|
@@ -359,7 +342,7 @@ by the redacted form.
|
|
|
359
342
|
The only true validation is to send a message to the email address and
|
|
360
343
|
have the user (or process) verify it has been received. Syntax checks
|
|
361
344
|
help prevent erroneous input. Even sent messages can be silently
|
|
362
|
-
dropped, or bounced back after acceptance.
|
|
345
|
+
dropped, or bounced back after acceptance. Conditions such as a
|
|
363
346
|
"Mailbox Full" can mean the email address is known, but abandoned.
|
|
364
347
|
|
|
365
348
|
There are different levels of validations you can perform. By default, it will
|
|
@@ -389,14 +372,14 @@ e1 < e2 #=> true (Compares using normalized address)
|
|
|
389
372
|
|
|
390
373
|
Matching addresses by simple patterns:
|
|
391
374
|
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
375
|
+
- Top-Level-Domain: .org
|
|
376
|
+
- Domain Name: example.com
|
|
377
|
+
- Registration Name: hotmail. (matches any TLD)
|
|
378
|
+
- Domain Glob: \*.exampl?.com
|
|
379
|
+
- Provider Name: google
|
|
380
|
+
- Mailbox Name or Glob: user00\*@
|
|
381
|
+
- Address or Glob: postmaster@domain\*.com
|
|
382
|
+
- Provider or Registration: msn
|
|
400
383
|
|
|
401
384
|
Usage:
|
|
402
385
|
|
|
@@ -484,124 +467,8 @@ EmailAddress::Config.error_messages({
|
|
|
484
467
|
not_allowed: "Address is not allowed",
|
|
485
468
|
incomplete_domain: "Domain name is incomplete"}, 'en')
|
|
486
469
|
```
|
|
487
|
-
Note: Release 0.1.14 fixed setting error messages by locale.
|
|
488
|
-
Also, it will accept a ruby "collected" hash as before,
|
|
489
|
-
|
|
490
|
-
Full translation support would be ideal though.
|
|
491
|
-
|
|
492
|
-
### Available Configuration Settings
|
|
493
|
-
|
|
494
|
-
* sha1_secret -
|
|
495
|
-
This application-level secret is appended to the email_address to compute
|
|
496
|
-
the SHA1 Digest, making it unique to your application so it can't easily be
|
|
497
|
-
discovered by comparing against a known list of email/sha1 pairs.
|
|
498
|
-
|
|
499
|
-
* sha256_secret -
|
|
500
|
-
This application-level secret is appended to the email_address to compute
|
|
501
|
-
the SHA256 Digest, making it unique to your application so it can't easily be
|
|
502
|
-
discovered by comparing against a known list of email/sha256 pairs.
|
|
503
470
|
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
For local part configuration:
|
|
507
|
-
|
|
508
|
-
* local_downcase: true.
|
|
509
|
-
Downcase the local part. You probably want this for uniqueness.
|
|
510
|
-
RFC says local part is case insensitive, that's a bad part.
|
|
511
|
-
|
|
512
|
-
* local_fix: true.
|
|
513
|
-
Make simple fixes when available, remove spaces, condense multiple punctuations
|
|
514
|
-
|
|
515
|
-
* local_encoding: :ascii, :unicode,
|
|
516
|
-
Enable Unicode in local part. Most mail systems do not yet support this.
|
|
517
|
-
You probably want to stay with ASCII for now.
|
|
518
|
-
|
|
519
|
-
* local_parse: nil, ->(local) { [mailbox, tag, comment] }
|
|
520
|
-
Specify an optional lambda/Proc to parse the local part. It should return an
|
|
521
|
-
array (tuple) of mailbox, tag, and comment.
|
|
522
|
-
|
|
523
|
-
* local_format:
|
|
524
|
-
* :conventional - word ( puncuation{1} word )*
|
|
525
|
-
* :relaxed - alphanum ( allowed_characters)* alphanum
|
|
526
|
-
* :standard - RFC Compliant email addresses (anything goes!)
|
|
527
|
-
|
|
528
|
-
* local_size: 1..64,
|
|
529
|
-
A Range specifying the allowed size for mailbox + tags + comment
|
|
530
|
-
|
|
531
|
-
* tag_separator: nil, character (+)
|
|
532
|
-
Nil, or a character used to split the tag from the mailbox
|
|
533
|
-
|
|
534
|
-
For the mailbox (AKA account, role), without the tag
|
|
535
|
-
* mailbox_size: 1..64
|
|
536
|
-
A Range specifying the allowed size for mailbox
|
|
537
|
-
|
|
538
|
-
* mailbox_canonical: nil, ->(mailbox) { mailbox }
|
|
539
|
-
An optional lambda/Proc taking a mailbox name, returning a canonical
|
|
540
|
-
version of it. (E.G.: gmail removes '.' characters)
|
|
541
|
-
|
|
542
|
-
* mailbox_validator: nil, ->(mailbox) { true }
|
|
543
|
-
An optional lambda/Proc taking a mailbox name, returning true or false.
|
|
544
|
-
|
|
545
|
-
* host_encoding: :punycode, :unicode,
|
|
546
|
-
How to treat International Domain Names (IDN). Note that most mail and
|
|
547
|
-
DNS systems do not support unicode, so punycode needs to be passed.
|
|
548
|
-
:punycode Convert Unicode names to punycode representation
|
|
549
|
-
:unicode Keep Unicode names as is.
|
|
550
|
-
|
|
551
|
-
* host_validation:
|
|
552
|
-
:mx Ensure host is configured with DNS MX records
|
|
553
|
-
:a Ensure host is known to DNS (A Record)
|
|
554
|
-
:syntax Validate by syntax only, no Network verification
|
|
555
|
-
:connect Attempt host connection (Experimental and Dangerous: Do not use)
|
|
556
|
-
The :host_timeout setting is the maximum number
|
|
557
|
-
of seconds to wait during the :connect validation
|
|
558
|
-
|
|
559
|
-
* host_size: 1..253,
|
|
560
|
-
A range specifying the size limit of the host part,
|
|
561
|
-
|
|
562
|
-
* host_allow_ip: false,
|
|
563
|
-
Allow IP address format in host: [127.0.0.1], [IPv6:::1]
|
|
564
|
-
|
|
565
|
-
* address_validation: :parts, :smtp, ->(address) { true }
|
|
566
|
-
Address validation policy
|
|
567
|
-
:parts Validate local and host.
|
|
568
|
-
:smtp Validate via SMTP (not implemented, BAD!)
|
|
569
|
-
A lambda/Proc taking the address string, returning true or false
|
|
570
|
-
|
|
571
|
-
* address_size: 3..254,
|
|
572
|
-
A range specifying the size limit of the complete address
|
|
573
|
-
|
|
574
|
-
For provider rules to match to domain names and Exchanger hosts
|
|
575
|
-
The value is an array of match tokens.
|
|
576
|
-
* host_match: %w(.org example.com hotmail. user*@ sub.*.com)
|
|
577
|
-
* exchanger_match: %w(google.com 127.0.0.1 10.9.8.0/24 ::1/64)
|
|
578
|
-
|
|
579
|
-
### Namespace conflict resolution
|
|
580
|
-
|
|
581
|
-
If your application already uses the `EmailAddress` class name,
|
|
582
|
-
it's possible to create an alias prior to loading your code:
|
|
583
|
-
|
|
584
|
-
For a Rails application, you can do this in `config/application.rb`
|
|
585
|
-
after the `Bundler.require` line, usually:
|
|
586
|
-
|
|
587
|
-
```ruby
|
|
588
|
-
Bundler.require(*Rails.groups)
|
|
589
|
-
```
|
|
590
|
-
|
|
591
|
-
Add these lines immediately after that point:
|
|
592
|
-
|
|
593
|
-
```ruby
|
|
594
|
-
EmailAddressValidator = EmailAddress
|
|
595
|
-
Object.send(:remove_const, :EmailAddress)
|
|
596
|
-
```
|
|
597
|
-
|
|
598
|
-
Then your application loads with your EmailAddress class. You may
|
|
599
|
-
then use this gem with `EmailAddressValidator` or whatever name you
|
|
600
|
-
gave it above:
|
|
601
|
-
|
|
602
|
-
```ruby
|
|
603
|
-
EmailAddressValidator.valid?("clark.kent@gmail.com") # => true
|
|
604
|
-
```
|
|
471
|
+
Complete settings and methods are found in the config.rb file within.
|
|
605
472
|
|
|
606
473
|
## Notes
|
|
607
474
|
|
|
@@ -661,5 +528,5 @@ This project lives at [https://github.com/afair/email_address/](https://github.c
|
|
|
661
528
|
|
|
662
529
|
#### Authors
|
|
663
530
|
|
|
664
|
-
|
|
531
|
+
- [Allen Fair](https://github.com/afair) ([@allenfair](https://twitter.com/allenfair)):
|
|
665
532
|
I've worked with email-based applications and email addresses since 1999.
|
data/lib/email_address/config.rb
CHANGED
|
@@ -112,7 +112,7 @@ module EmailAddress
|
|
|
112
112
|
|
|
113
113
|
class Config
|
|
114
114
|
@config = {
|
|
115
|
-
dns_lookup: :
|
|
115
|
+
dns_lookup: :a, # :mx, :a, :off
|
|
116
116
|
dns_timeout: nil,
|
|
117
117
|
sha1_secret: "",
|
|
118
118
|
sha256_secret: "",
|
|
@@ -159,7 +159,7 @@ module EmailAddress
|
|
|
159
159
|
msn: {
|
|
160
160
|
host_match: %w[msn. hotmail. outlook. live.],
|
|
161
161
|
exchanger_match: %w[outlook.com],
|
|
162
|
-
mailbox_validator: ->(m, t) { m =~ /\A\w[
|
|
162
|
+
mailbox_validator: ->(m, t) { m =~ /\A\w[-\w]*(?:\.[-\w]+)*\z/i }
|
|
163
163
|
},
|
|
164
164
|
yahoo: {
|
|
165
165
|
host_match: %w[yahoo. ymail. rocketmail.],
|
data/lib/email_address/local.rb
CHANGED
|
@@ -101,10 +101,10 @@ module EmailAddress
|
|
|
101
101
|
|
|
102
102
|
REDACTED_REGEX = /\A \{ [0-9a-f]{40} \} \z/x # {sha1}
|
|
103
103
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
104
|
+
# Conventional Tag: word ([,-+'='] word)...
|
|
105
|
+
CONVENTIONAL_TAG_REGEX = /\A [\p{L}\p{N}_]+ (?: [.\-+'=] [\p{L}\p{N}_]+ )* \z/x # word(<punctuation>word)*...
|
|
106
|
+
# Relexed Tag: token ( . token)... token is most punctuation, but not: . \ " space
|
|
107
|
+
RELAXED_TAG_REGEX = %r/^[\w!\#$%&'*+\-\/=?\^`{|}~]+ (\.[\w!\#$%&'*+\-\/=?\^`{|}~])* $/ix
|
|
108
108
|
|
|
109
109
|
def initialize(local, config = {}, host = nil, locale = "en")
|
|
110
110
|
@config = config.is_a?(Hash) ? Config.new(config) : config
|
|
@@ -333,14 +333,11 @@ module EmailAddress
|
|
|
333
333
|
# True if the part matches the conventional format
|
|
334
334
|
def conventional?
|
|
335
335
|
self.syntax = :invalid
|
|
336
|
-
if tag
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
end
|
|
342
|
-
valid_size? or return false
|
|
343
|
-
valid_encoding? or return false
|
|
336
|
+
return false if tag && tag !~ CONVENTIONAL_TAG_REGEX
|
|
337
|
+
return false unless mailbox =~ CONVENTIONAL_MAILBOX_REGEX
|
|
338
|
+
return false if comment
|
|
339
|
+
return false unless valid_size?
|
|
340
|
+
return false unless valid_encoding?
|
|
344
341
|
self.syntax = :conventional
|
|
345
342
|
true
|
|
346
343
|
end
|
|
@@ -348,32 +345,23 @@ module EmailAddress
|
|
|
348
345
|
# Relaxed conventional is not so strict about character order.
|
|
349
346
|
def relaxed?
|
|
350
347
|
self.syntax = :invalid
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
if
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
elsif RELAXED_MAILBOX_REGEX.match?(local)
|
|
359
|
-
self.syntax = :relaxed
|
|
360
|
-
true
|
|
361
|
-
else
|
|
362
|
-
false
|
|
363
|
-
end
|
|
348
|
+
return false if tag && tag !~ RELAXED_TAG_REGEX
|
|
349
|
+
return false unless mailbox =~ RELAXED_MAILBOX_REGEX
|
|
350
|
+
return false if comment
|
|
351
|
+
return false unless valid_size?
|
|
352
|
+
return false unless valid_encoding?
|
|
353
|
+
self.syntax = :relaxed
|
|
354
|
+
true
|
|
364
355
|
end
|
|
365
356
|
|
|
366
357
|
# True if the part matches the RFC standard format
|
|
367
358
|
def standard?
|
|
368
359
|
self.syntax = :invalid
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
else
|
|
375
|
-
false
|
|
376
|
-
end
|
|
360
|
+
return false unless STANDARD_LOCAL_REGEX.match?(local)
|
|
361
|
+
return false unless valid_size?
|
|
362
|
+
return false unless valid_encoding?
|
|
363
|
+
self.syntax = :standard
|
|
364
|
+
true
|
|
377
365
|
end
|
|
378
366
|
|
|
379
367
|
# Matches configured formated form against File glob strings given.
|
|
@@ -102,9 +102,9 @@ class TestAddress < Minitest::Test
|
|
|
102
102
|
assert_equal "", e.hostname
|
|
103
103
|
assert_equal false, e.valid? # localhost not allowed by default
|
|
104
104
|
assert_equal EmailAddress.error("user1"), "Invalid Domain Name"
|
|
105
|
-
assert_equal EmailAddress.error("user1", host_local: true), "This domain is not configured to accept email"
|
|
105
|
+
#assert_equal EmailAddress.error("user1", host_local: true), "This domain is not configured to accept email"
|
|
106
106
|
assert_equal EmailAddress.error("user1", host_local: true, host_auto_append: false), "Invalid Domain Name"
|
|
107
|
-
assert_equal EmailAddress.error("user1@localhost", host_local: true), "This domain is not configured to accept email"
|
|
107
|
+
#assert_equal EmailAddress.error("user1@localhost", host_local: true), "This domain is not configured to accept email"
|
|
108
108
|
assert_equal EmailAddress.error("user1@localhost", host_local: false, host_validation: :syntax), "localhost is not allowed for your domain name"
|
|
109
109
|
assert_equal EmailAddress.error("user1@localhost", host_local: false, dns_lookup: :off), "localhost is not allowed for your domain name"
|
|
110
110
|
assert_nil EmailAddress.error("user2@localhost", host_local: true, dns_lookup: :off, host_validation: :syntax)
|
|
@@ -149,6 +149,13 @@ class TestAddress < Minitest::Test
|
|
|
149
149
|
end
|
|
150
150
|
|
|
151
151
|
def test_nonstandard_tag
|
|
152
|
-
assert EmailAddress.valid?("asdfas+-@icloud.com")
|
|
152
|
+
# assert EmailAddress.valid?("asdfas+-@icloud.com")
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def test_newline_characters
|
|
156
|
+
assert !EmailAddress.valid?("user@foo.com\nother@bar.com")
|
|
157
|
+
assert !EmailAddress.valid?("user@foo.com\r\nother@bar.com")
|
|
158
|
+
assert EmailAddress.valid?("\nuser@foo.com") # valid because strip processing removes \n
|
|
159
|
+
assert EmailAddress.valid?("user@foo.com\r\n") # valid because strip processing removes \n
|
|
153
160
|
end
|
|
154
161
|
end
|
|
@@ -2,19 +2,19 @@ require_relative "../test_helper"
|
|
|
2
2
|
|
|
3
3
|
class TestConfig < MiniTest::Test
|
|
4
4
|
def test_setting
|
|
5
|
-
assert_equal :
|
|
5
|
+
assert_equal :a, EmailAddress::Config.setting(:dns_lookup)
|
|
6
6
|
assert_equal :off, EmailAddress::Config.setting(:dns_lookup, :off)
|
|
7
7
|
assert_equal :off, EmailAddress::Config.setting(:dns_lookup)
|
|
8
|
-
EmailAddress::Config.setting(:dns_lookup, :
|
|
8
|
+
EmailAddress::Config.setting(:dns_lookup, :a)
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
def test_configure
|
|
12
|
-
assert_equal :
|
|
12
|
+
assert_equal :a, EmailAddress::Config.setting(:dns_lookup)
|
|
13
13
|
assert_equal true, EmailAddress::Config.setting(:local_downcase)
|
|
14
14
|
EmailAddress::Config.configure(local_downcase: false, dns_lookup: :off)
|
|
15
15
|
assert_equal :off, EmailAddress::Config.setting(:dns_lookup)
|
|
16
16
|
assert_equal false, EmailAddress::Config.setting(:local_downcase)
|
|
17
|
-
EmailAddress::Config.configure(local_downcase: true, dns_lookup: :
|
|
17
|
+
EmailAddress::Config.configure(local_downcase: true, dns_lookup: :a)
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
def test_provider
|
|
@@ -142,7 +142,7 @@ class TestHost < MiniTest::Test
|
|
|
142
142
|
|
|
143
143
|
def test_errors
|
|
144
144
|
assert_nil EmailAddress::Host.new("yahoo.com").error
|
|
145
|
-
assert_equal EmailAddress::Host.new("example.com").error, "This domain is not configured to accept email"
|
|
145
|
+
#assert_equal EmailAddress::Host.new("example.com").error, "This domain is not configured to accept email"
|
|
146
146
|
assert_equal EmailAddress::Host.new("yahoo.wtf").error, "Domain name not registered"
|
|
147
147
|
assert_nil EmailAddress::Host.new("ajsdfhajshdfklasjhd.wtf", host_validation: :syntax).error
|
|
148
148
|
assert_equal EmailAddress::Host.new("ya hoo.com", host_validation: :syntax).error, "Invalid Domain Name"
|
|
@@ -156,11 +156,11 @@ class TestHost < MiniTest::Test
|
|
|
156
156
|
end
|
|
157
157
|
|
|
158
158
|
# When a domain is not configured to receive email (missing MX record),
|
|
159
|
-
# Though some MTA's will fallback to the A/AAAA host record
|
|
160
|
-
def test_no_mx
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
end
|
|
159
|
+
# Though some MTA's will fallback to the A/AAAA host record, so this isn't a good test
|
|
160
|
+
#def test_no_mx
|
|
161
|
+
# assert !EmailAddress::Host.new("zaboz.com").valid?
|
|
162
|
+
# assert EmailAddress::Host.new("zaboz.com", dns_lookup: :a).valid?
|
|
163
|
+
#end
|
|
164
164
|
|
|
165
165
|
# Issue #102 off---white.com should be valid
|
|
166
166
|
def test_triple_dash_domain
|
|
@@ -63,13 +63,13 @@ class TestLocal < MiniTest::Test
|
|
|
63
63
|
end
|
|
64
64
|
|
|
65
65
|
def test_valid
|
|
66
|
-
|
|
67
|
-
|
|
66
|
+
refute EmailAddress::Local.new("first(comment)", local_format: :conventional).valid?
|
|
67
|
+
assert EmailAddress::Local.new("first(comment)", local_format: :standard).valid?
|
|
68
68
|
end
|
|
69
69
|
|
|
70
70
|
def test_format
|
|
71
71
|
assert_equal :conventional, EmailAddress::Local.new("can1").format?
|
|
72
|
-
assert_equal :standard, EmailAddress::Local.new(%("
|
|
72
|
+
assert_equal :standard, EmailAddress::Local.new(%("can 1")).format?
|
|
73
73
|
assert_equal "can1", EmailAddress::Local.new(%{"can1(commment)"}).format(:conventional)
|
|
74
74
|
end
|
|
75
75
|
|
|
@@ -109,4 +109,9 @@ class TestLocal < MiniTest::Test
|
|
|
109
109
|
def test_relaxed_tag
|
|
110
110
|
assert EmailAddress.valid? "foo+abc@example.com", host_validation: :syntax, local_format: :relaxed
|
|
111
111
|
end
|
|
112
|
+
|
|
113
|
+
def test_tag_punctuation
|
|
114
|
+
refute EmailAddress.valid?("name+tag.@domain.com", host_validation: :syntax)
|
|
115
|
+
assert EmailAddress.valid?("name+tag.-@domain.com", host_validation: :syntax, local_format: :relaxed)
|
|
116
|
+
end
|
|
112
117
|
end
|
data/test/test_helper.rb
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
################################################################################
|
|
2
|
+
# EmailAddress Testing
|
|
3
|
+
# - ๐ฅ rake
|
|
4
|
+
# - ๐๏ธ ruby test/email_address/test_local.rb --name test_tag_punctuation
|
|
5
|
+
# - ๐งช rake console
|
|
6
|
+
################################################################################
|
|
1
7
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
|
|
2
8
|
|
|
3
9
|
require "pry"
|