email_address 0.2.3 → 0.2.5
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/.github/workflows/ci.yml +2 -2
- data/.gitignore +1 -0
- data/README.md +4 -2
- data/email_address.gemspec +10 -7
- data/lib/email_address/active_record_validator.rb +6 -1
- data/lib/email_address/config.rb +2 -1
- data/lib/email_address/host.rb +17 -10
- data/lib/email_address/local.rb +1 -1
- data/lib/email_address/version.rb +1 -1
- data/test/activerecord/test_ar.rb +10 -0
- data/test/activerecord/user.rb +3 -0
- data/test/email_address/test_host.rb +13 -2
- data/test/email_address/test_local.rb +1 -1
- metadata +81 -25
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5a0acf217d99455d8e47f25dc21b4ff25478234932c8618f3d5fe0fe4629e433
|
4
|
+
data.tar.gz: 5da4449168ec63611c8e510efd010b12995502b3162c67d3222c46cbabbbe6e8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1703377fdf988adabaaf4d728db211320a1f33cf0daeeabd68448cf4a4d02b8647fcb9aad636d0aa14250386b8c8d2ede3cb89b42b55ffa2af793b1f788a9a08
|
7
|
+
data.tar.gz: 15d5b84368e692e6ce08db5ad596ec1ef684f87c70a8db4d1a2d69ab977c72ed5b5f80d9945fc6cdf42af3af5581a9f3a55b26c9138370ce228ad663c758f387
|
data/.github/workflows/ci.yml
CHANGED
@@ -5,9 +5,9 @@ jobs:
|
|
5
5
|
runs-on: ubuntu-latest
|
6
6
|
strategy:
|
7
7
|
matrix:
|
8
|
-
ruby-version: [
|
8
|
+
ruby-version: [3.2, 3.3, 3.4]
|
9
9
|
steps:
|
10
|
-
- uses: actions/checkout@
|
10
|
+
- uses: actions/checkout@v3
|
11
11
|
- uses: ruby/setup-ruby@v1
|
12
12
|
with:
|
13
13
|
ruby-version: ${{ matrix.ruby-version }}
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -241,7 +241,7 @@ email.provider #=> :google
|
|
241
241
|
email.mailbox #=> "clark.kent"
|
242
242
|
email.tag #=> "scoops"
|
243
243
|
|
244
|
-
email.host.
|
244
|
+
email.host.exchangers.first[:ip] #=> "2a00:1450:400b:c02::1a"
|
245
245
|
email.host.txt_hash #=> {:v=>"spf1", :redirect=>"\_spf.google.com"}
|
246
246
|
|
247
247
|
EmailAddress.normal("HIRO@こんにちは世界.com")
|
@@ -552,7 +552,9 @@ For the mailbox (AKA account, role), without the tag
|
|
552
552
|
:mx Ensure host is configured with DNS MX records
|
553
553
|
:a Ensure host is known to DNS (A Record)
|
554
554
|
:syntax Validate by syntax only, no Network verification
|
555
|
-
:connect Attempt host connection (Dangerous: Do not use)
|
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
|
556
558
|
|
557
559
|
* host_size: 1..253,
|
558
560
|
A range specifying the size limit of the host part,
|
data/email_address.gemspec
CHANGED
@@ -15,23 +15,26 @@ Gem::Specification.new do |spec|
|
|
15
15
|
spec.required_ruby_version = ">= 2.5", "< 4"
|
16
16
|
spec.files = `git ls-files`.split($/)
|
17
17
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
-
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
18
|
spec.require_paths = ["lib"]
|
20
19
|
|
21
20
|
spec.add_development_dependency "rake"
|
22
21
|
spec.add_development_dependency "minitest", "~> 5.11"
|
23
22
|
spec.add_development_dependency "bundler" # , "~> 1.16.0"
|
24
23
|
if RUBY_PLATFORM == "java"
|
25
|
-
spec.add_development_dependency "activerecord", "~>
|
26
|
-
spec.add_development_dependency "activerecord-jdbcsqlite3-adapter", "~>
|
24
|
+
spec.add_development_dependency "activerecord", "~> 7.2.0"
|
25
|
+
spec.add_development_dependency "activerecord-jdbcsqlite3-adapter", "~> 70.2"
|
27
26
|
else
|
28
|
-
spec.add_development_dependency "activerecord", "~>
|
29
|
-
spec.add_development_dependency "sqlite3"
|
30
|
-
spec.add_development_dependency "standard"
|
27
|
+
spec.add_development_dependency "activerecord", "~> 8.0.0"
|
28
|
+
spec.add_development_dependency "sqlite3", "~> 2.1"
|
29
|
+
spec.add_development_dependency "standard"
|
31
30
|
end
|
32
|
-
|
31
|
+
spec.add_development_dependency "net-smtp"
|
33
32
|
spec.add_development_dependency "simplecov"
|
34
33
|
spec.add_development_dependency "pry"
|
34
|
+
spec.add_development_dependency "bigdecimal"
|
35
|
+
spec.add_development_dependency "mutex_m"
|
36
|
+
spec.add_development_dependency "irb"
|
35
37
|
|
38
|
+
spec.add_dependency "base64"
|
36
39
|
spec.add_dependency "simpleidn"
|
37
40
|
end
|
@@ -12,8 +12,12 @@ module EmailAddress
|
|
12
12
|
# * field: email,
|
13
13
|
# * fields: [:email1, :email2]
|
14
14
|
#
|
15
|
+
# * code: custom error code (default: :invalid_address)
|
16
|
+
# * message: custom error message (default: "Invalid Email Address")
|
17
|
+
#
|
15
18
|
# Default field: :email or :email_address (first found)
|
16
19
|
#
|
20
|
+
#
|
17
21
|
class ActiveRecordValidator < ActiveModel::Validator
|
18
22
|
def initialize(options = {})
|
19
23
|
@opt = options
|
@@ -35,10 +39,11 @@ module EmailAddress
|
|
35
39
|
return if r[f].nil?
|
36
40
|
e = Address.new(r[f])
|
37
41
|
unless e.valid?
|
42
|
+
error_code = @opt[:code] || :invalid_address
|
38
43
|
error_message = @opt[:message] ||
|
39
44
|
Config.error_message(:invalid_address, I18n.locale.to_s) ||
|
40
45
|
"Invalid Email Address"
|
41
|
-
r.errors.add(f, error_message)
|
46
|
+
r.errors.add(f, error_code, message: error_message)
|
42
47
|
end
|
43
48
|
end
|
44
49
|
end
|
data/lib/email_address/config.rb
CHANGED
@@ -137,6 +137,7 @@ module EmailAddress
|
|
137
137
|
host_local: false,
|
138
138
|
host_fqdn: true,
|
139
139
|
host_auto_append: true,
|
140
|
+
host_timeout: 3,
|
140
141
|
|
141
142
|
address_validation: :parts, # :parts, :smtp, Proc
|
142
143
|
address_size: 3..254,
|
@@ -151,7 +152,7 @@ module EmailAddress
|
|
151
152
|
google: {
|
152
153
|
host_match: %w[gmail.com googlemail.com],
|
153
154
|
exchanger_match: %w[google.com googlemail.com],
|
154
|
-
local_size:
|
155
|
+
local_size: 3..64,
|
155
156
|
local_private_size: 1..64, # When hostname not in host_match (private label)
|
156
157
|
mailbox_canonical: ->(m) { m.delete(".") }
|
157
158
|
},
|
data/lib/email_address/host.rb
CHANGED
@@ -381,18 +381,21 @@ module EmailAddress
|
|
381
381
|
# Returns true if the host name is valid according to the current configuration
|
382
382
|
def valid?(rules = {})
|
383
383
|
host_validation = rules[:host_validation] || @config[:host_validation] || :mx
|
384
|
-
dns_lookup = rules[:dns_lookup] || host_validation
|
384
|
+
dns_lookup = rules[:dns_lookup] || @config[:dns_lookup] || host_validation
|
385
385
|
self.error_message = nil
|
386
|
+
if host_name && !host_name.empty? && !@config[:host_size].include?(host_name.size)
|
387
|
+
return set_error(:invalid_host)
|
388
|
+
end
|
386
389
|
if ip_address
|
387
390
|
valid_ip?
|
388
391
|
elsif !valid_format?
|
389
392
|
false
|
390
393
|
elsif dns_lookup == :connect
|
391
394
|
valid_mx? && connect
|
395
|
+
elsif dns_lookup == :a || host_validation == :a
|
396
|
+
valid_dns?
|
392
397
|
elsif dns_lookup == :mx
|
393
398
|
valid_mx?
|
394
|
-
elsif dns_lookup == :a
|
395
|
-
valid_dns?
|
396
399
|
else
|
397
400
|
true
|
398
401
|
end
|
@@ -462,11 +465,15 @@ module EmailAddress
|
|
462
465
|
# as an email address check, but is provided to assist in problem resolution.
|
463
466
|
# If you abuse this, you *could* be blocked by the ESP.
|
464
467
|
#
|
465
|
-
#
|
466
|
-
#
|
467
|
-
#
|
468
|
-
|
468
|
+
# timeout is the number of seconds to wait before timing out the request and
|
469
|
+
# returns false as the connection was unsuccessful.
|
470
|
+
#
|
471
|
+
# > NOTE: As of Ruby 3.1, Net::SMTP was moved from the standard library to the
|
472
|
+
# > 'net-smtp' gem. In order to avoid adding that dependency for this *experimental*
|
473
|
+
# > feature, please add the gem to your Gemfile and require it to use this feature.
|
474
|
+
def connect(timeout = nil)
|
469
475
|
smtp = Net::SMTP.new(host_name || ip_address)
|
476
|
+
smtp.open_timeout = timeout || @config[:host_timeout]
|
470
477
|
smtp.start(@config[:helo_name] || "localhost")
|
471
478
|
smtp.finish
|
472
479
|
true
|
@@ -474,10 +481,10 @@ module EmailAddress
|
|
474
481
|
set_error(:server_not_available, e.to_s)
|
475
482
|
rescue SocketError => e
|
476
483
|
set_error(:server_not_available, e.to_s)
|
484
|
+
rescue Net::OpenTimeout => e
|
485
|
+
set_error(:server_not_available, e.to_s)
|
477
486
|
ensure
|
478
|
-
if smtp&.started?
|
479
|
-
smtp.finish
|
480
|
-
end
|
487
|
+
smtp.finish if smtp&.started?
|
481
488
|
end
|
482
489
|
|
483
490
|
def set_error(err, reason = nil)
|
data/lib/email_address/local.rb
CHANGED
@@ -116,7 +116,7 @@ module EmailAddress
|
|
116
116
|
|
117
117
|
def local=(raw)
|
118
118
|
self.original = raw
|
119
|
-
raw.downcase
|
119
|
+
raw = raw.downcase if @config[:local_downcase].nil? || @config[:local_downcase]
|
120
120
|
@local = raw
|
121
121
|
|
122
122
|
if @config[:local_parse].is_a?(Proc)
|
@@ -9,11 +9,21 @@ class TestAR < MiniTest::Test
|
|
9
9
|
user = User.new(email: "Pat.Jones+ASDF#GMAIL.com")
|
10
10
|
assert_equal false, user.valid?
|
11
11
|
assert user.errors.messages[:email].first
|
12
|
+
|
12
13
|
user = User.new(email: "Pat.Jones+ASDF@GMAIL.com")
|
13
14
|
assert_equal true, user.valid?
|
14
15
|
end
|
15
16
|
end
|
16
17
|
|
18
|
+
def test_validation_error_message
|
19
|
+
if RUBY_PLATFORM != "java" # jruby
|
20
|
+
user = User.new(alternate_email: "Pat.Jones+ASDF#GMAIL.com")
|
21
|
+
assert_equal false, user.valid?
|
22
|
+
assert user.errors.messages[:alternate_email].first.include?("Check your email")
|
23
|
+
assert_equal :some_error_code, user.errors.details[:alternate_email].first[:error]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
17
27
|
def test_datatype
|
18
28
|
# Disabled JRuby checks... weird CI failures. Hopefully someone can help?
|
19
29
|
if RUBY_PLATFORM != "java" # jruby
|
data/test/activerecord/user.rb
CHANGED
@@ -48,10 +48,13 @@ class User < ApplicationRecord
|
|
48
48
|
if defined?(ActiveRecord) && ::ActiveRecord::VERSION::MAJOR >= 5
|
49
49
|
attribute :email, :email_address
|
50
50
|
attribute :canonical_email, :canonical_email_address
|
51
|
+
attribute :alternate_email, :email_address
|
51
52
|
end
|
52
53
|
|
53
54
|
validates_with EmailAddress::ActiveRecordValidator,
|
54
55
|
fields: %i[email canonical_email]
|
56
|
+
validates_with EmailAddress::ActiveRecordValidator,
|
57
|
+
field: :alternate_email, code: :some_error_code, message: "Check your email"
|
55
58
|
|
56
59
|
def email=(email_address)
|
57
60
|
self[:canonical_email] = email_address
|
@@ -52,7 +52,7 @@ class TestHost < MiniTest::Test
|
|
52
52
|
def test_dmarc
|
53
53
|
d = EmailAddress::Host.new("yahoo.com").dmarc
|
54
54
|
assert_equal "reject", d[:p]
|
55
|
-
d = EmailAddress::Host.new("
|
55
|
+
d = EmailAddress::Host.new("calculator.net").dmarc
|
56
56
|
assert_equal true, d.empty?
|
57
57
|
end
|
58
58
|
|
@@ -127,7 +127,7 @@ class TestHost < MiniTest::Test
|
|
127
127
|
def test_hosted_service
|
128
128
|
# Is there a gmail-hosted domain that will continue to exist? Removing until then
|
129
129
|
# assert EmailAddress.valid?("test@jiff.com", dns_lookup: :mx)
|
130
|
-
assert !EmailAddress.valid?("
|
130
|
+
assert !EmailAddress.valid?("t@gmail.com", dns_lookup: :mx)
|
131
131
|
end
|
132
132
|
|
133
133
|
def test_yahoo_bad_tld
|
@@ -150,4 +150,15 @@ class TestHost < MiniTest::Test
|
|
150
150
|
assert_equal EmailAddress::Host.new("[127.0.0.666]", host_allow_ip: true).error, "This is not a valid IPv4 address"
|
151
151
|
assert_equal EmailAddress::Host.new("[IPv6::12t]", host_allow_ip: true).error, "This is not a valid IPv6 address"
|
152
152
|
end
|
153
|
+
|
154
|
+
def test_host_size
|
155
|
+
assert !EmailAddress::Host.new("stackoverflow.com", {host_size: 1..3}).valid?
|
156
|
+
end
|
157
|
+
|
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
|
+
assert !EmailAddress::Host.new("zaboz.com").valid?
|
162
|
+
assert EmailAddress::Host.new("zaboz.com", dns_lookup: :a).valid?
|
163
|
+
end
|
153
164
|
end
|
@@ -92,7 +92,7 @@ class TestLocal < MiniTest::Test
|
|
92
92
|
|
93
93
|
def test_hosted
|
94
94
|
assert EmailAddress.valid?("x@exposure.co")
|
95
|
-
assert EmailAddress.error("
|
95
|
+
assert EmailAddress.error("xx+subscriber@gmail.com")
|
96
96
|
assert EmailAddress.valid?("xxxxx+subscriber@gmail.com")
|
97
97
|
end
|
98
98
|
|
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: email_address
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Allen Fair
|
8
|
-
autorequire:
|
9
8
|
bindir: bin
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 2025-01-09 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: rake
|
@@ -58,16 +57,30 @@ dependencies:
|
|
58
57
|
requirements:
|
59
58
|
- - "~>"
|
60
59
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
60
|
+
version: 8.0.0
|
62
61
|
type: :development
|
63
62
|
prerelease: false
|
64
63
|
version_requirements: !ruby/object:Gem::Requirement
|
65
64
|
requirements:
|
66
65
|
- - "~>"
|
67
66
|
- !ruby/object:Gem::Version
|
68
|
-
version:
|
67
|
+
version: 8.0.0
|
69
68
|
- !ruby/object:Gem::Dependency
|
70
69
|
name: sqlite3
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - "~>"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '2.1'
|
75
|
+
type: :development
|
76
|
+
prerelease: false
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - "~>"
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '2.1'
|
82
|
+
- !ruby/object:Gem::Dependency
|
83
|
+
name: standard
|
71
84
|
requirement: !ruby/object:Gem::Requirement
|
72
85
|
requirements:
|
73
86
|
- - ">="
|
@@ -81,19 +94,19 @@ dependencies:
|
|
81
94
|
- !ruby/object:Gem::Version
|
82
95
|
version: '0'
|
83
96
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
97
|
+
name: net-smtp
|
85
98
|
requirement: !ruby/object:Gem::Requirement
|
86
99
|
requirements:
|
87
|
-
- - "
|
100
|
+
- - ">="
|
88
101
|
- !ruby/object:Gem::Version
|
89
|
-
version:
|
102
|
+
version: '0'
|
90
103
|
type: :development
|
91
104
|
prerelease: false
|
92
105
|
version_requirements: !ruby/object:Gem::Requirement
|
93
106
|
requirements:
|
94
|
-
- - "
|
107
|
+
- - ">="
|
95
108
|
- !ruby/object:Gem::Version
|
96
|
-
version:
|
109
|
+
version: '0'
|
97
110
|
- !ruby/object:Gem::Dependency
|
98
111
|
name: simplecov
|
99
112
|
requirement: !ruby/object:Gem::Requirement
|
@@ -122,6 +135,62 @@ dependencies:
|
|
122
135
|
- - ">="
|
123
136
|
- !ruby/object:Gem::Version
|
124
137
|
version: '0'
|
138
|
+
- !ruby/object:Gem::Dependency
|
139
|
+
name: bigdecimal
|
140
|
+
requirement: !ruby/object:Gem::Requirement
|
141
|
+
requirements:
|
142
|
+
- - ">="
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: '0'
|
145
|
+
type: :development
|
146
|
+
prerelease: false
|
147
|
+
version_requirements: !ruby/object:Gem::Requirement
|
148
|
+
requirements:
|
149
|
+
- - ">="
|
150
|
+
- !ruby/object:Gem::Version
|
151
|
+
version: '0'
|
152
|
+
- !ruby/object:Gem::Dependency
|
153
|
+
name: mutex_m
|
154
|
+
requirement: !ruby/object:Gem::Requirement
|
155
|
+
requirements:
|
156
|
+
- - ">="
|
157
|
+
- !ruby/object:Gem::Version
|
158
|
+
version: '0'
|
159
|
+
type: :development
|
160
|
+
prerelease: false
|
161
|
+
version_requirements: !ruby/object:Gem::Requirement
|
162
|
+
requirements:
|
163
|
+
- - ">="
|
164
|
+
- !ruby/object:Gem::Version
|
165
|
+
version: '0'
|
166
|
+
- !ruby/object:Gem::Dependency
|
167
|
+
name: irb
|
168
|
+
requirement: !ruby/object:Gem::Requirement
|
169
|
+
requirements:
|
170
|
+
- - ">="
|
171
|
+
- !ruby/object:Gem::Version
|
172
|
+
version: '0'
|
173
|
+
type: :development
|
174
|
+
prerelease: false
|
175
|
+
version_requirements: !ruby/object:Gem::Requirement
|
176
|
+
requirements:
|
177
|
+
- - ">="
|
178
|
+
- !ruby/object:Gem::Version
|
179
|
+
version: '0'
|
180
|
+
- !ruby/object:Gem::Dependency
|
181
|
+
name: base64
|
182
|
+
requirement: !ruby/object:Gem::Requirement
|
183
|
+
requirements:
|
184
|
+
- - ">="
|
185
|
+
- !ruby/object:Gem::Version
|
186
|
+
version: '0'
|
187
|
+
type: :runtime
|
188
|
+
prerelease: false
|
189
|
+
version_requirements: !ruby/object:Gem::Requirement
|
190
|
+
requirements:
|
191
|
+
- - ">="
|
192
|
+
- !ruby/object:Gem::Version
|
193
|
+
version: '0'
|
125
194
|
- !ruby/object:Gem::Dependency
|
126
195
|
name: simpleidn
|
127
196
|
requirement: !ruby/object:Gem::Requirement
|
@@ -177,7 +246,6 @@ homepage: https://github.com/afair/email_address
|
|
177
246
|
licenses:
|
178
247
|
- MIT
|
179
248
|
metadata: {}
|
180
|
-
post_install_message:
|
181
249
|
rdoc_options: []
|
182
250
|
require_paths:
|
183
251
|
- lib
|
@@ -195,22 +263,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
195
263
|
- !ruby/object:Gem::Version
|
196
264
|
version: '0'
|
197
265
|
requirements: []
|
198
|
-
rubygems_version: 3.
|
199
|
-
signing_key:
|
266
|
+
rubygems_version: 3.6.2
|
200
267
|
specification_version: 4
|
201
268
|
summary: This gem provides a ruby language library for working with and validating
|
202
269
|
email addresses. By default, it validates against conventional usage, the format
|
203
270
|
preferred for user email addresses. It can be configured to validate against RFC
|
204
271
|
“Standard” formats, common email service provider formats, and perform DNS validation.
|
205
|
-
test_files:
|
206
|
-
- test/activerecord/test_ar.rb
|
207
|
-
- test/activerecord/user.rb
|
208
|
-
- test/email_address/test_address.rb
|
209
|
-
- test/email_address/test_config.rb
|
210
|
-
- test/email_address/test_exchanger.rb
|
211
|
-
- test/email_address/test_host.rb
|
212
|
-
- test/email_address/test_local.rb
|
213
|
-
- test/email_address/test_rewriter.rb
|
214
|
-
- test/test_aliasing.rb
|
215
|
-
- test/test_email_address.rb
|
216
|
-
- test/test_helper.rb
|
272
|
+
test_files: []
|