email_address 0.1.9 → 0.1.10

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3825a1fafdf4659a5bc444b2bea01e83d4a52a0ae3faf57042c2cf83cae0d364
4
- data.tar.gz: e9c2f046f52648f7f7f2e0326457f1aaa11f36e075e87d40818a34de7a84f2f3
3
+ metadata.gz: b7864361d639e8c0d2609782b1d4d02a2d8c497bf3080a6bb563e5a8eac7bdc6
4
+ data.tar.gz: 1145528c90a7845ce092fae5791a8dde9d81a66709188d3a53eb9310a8e49e7e
5
5
  SHA512:
6
- metadata.gz: 39f199aab0bd33b42a57841df03a033142217aa5a39fe0652b779c4522509d450660178fc51eee23bc3111905a967475ac3625718d020d275ef9d697b672fe79
7
- data.tar.gz: e3ee79489ea98a0b6c11a3b438e84087833ce9782f16bf3865d7169514cd9a939f383a17e6ef2b695273351cbd427de2f36332d0d63e693c99c6f3fa7173430b
6
+ metadata.gz: a04d299269c34d29dc630335462bd8a6b778c9ce4eefa12ee5bb5a5f0e22fb6e435b4c84f413f6f194f8a2e8e4d94831d96f0cee3eef7fd28e8028bd839ffc85
7
+ data.tar.gz: 44184ef5b1c631e9a7cde11b8570c49473cceda7649cc625a386bd6c5ec8cd9fae5b024db82c06a99d237b025a249db92835492f99cc781a44654fb56d6999cf
@@ -1,7 +1,7 @@
1
1
  language: ruby
2
2
  rvm:
3
3
  - ruby-head
4
- - 2.2.2
4
+ - 2.3.7
5
5
  - jruby-9.0.4.0
6
6
  #- rbx
7
7
 
data/README.md CHANGED
@@ -22,6 +22,9 @@ address validator and attributes API custom datatypes.
22
22
 
23
23
  Requires Ruby 2.0 or later.
24
24
 
25
+ Looking for a Javascript version of this library? Check out the
26
+ [email_address](https://www.npmjs.com/package/email_address) npm module.
27
+
25
28
  ## Quick Start
26
29
 
27
30
  To quickly validate email addresses, use the valid? and error helpers.
@@ -20,12 +20,12 @@ Gem::Specification.new do |spec|
20
20
 
21
21
  spec.add_development_dependency "rake"
22
22
  spec.add_development_dependency "minitest", "~> 5.11"
23
- spec.add_development_dependency "bundler", "~> 1.3"
23
+ spec.add_development_dependency "bundler", "~> 1.16.0"
24
24
  if RUBY_PLATFORM == 'java'
25
- spec.add_development_dependency "activerecord", "= 4.2.5"
26
- spec.add_development_dependency "activerecord-jdbcsqlite3-adapter", '=1.3.19'
25
+ spec.add_development_dependency "activerecord", "= 4.2.10"
26
+ spec.add_development_dependency "activerecord-jdbcsqlite3-adapter", '~> 1.3.24'
27
27
  else
28
- spec.add_development_dependency "activerecord", "~> 5.2.0.rc2"
28
+ spec.add_development_dependency "activerecord", "~> 5.2.0"
29
29
  spec.add_development_dependency "sqlite3"
30
30
  end
31
31
  spec.add_development_dependency "codeclimate-test-reporter"
@@ -1,4 +1,7 @@
1
+ # frozen_string_literal: true
1
2
 
3
+ # EmailAddress parses and validates email addresses against RFC standard,
4
+ # conventional, canonical, formats and other special uses.
2
5
  module EmailAddress
3
6
 
4
7
  require "email_address/config"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module EmailAddress
2
4
 
3
5
  # ActiveRecord validator class for validating an email
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'digest/sha1'
2
4
  require 'digest/md5'
3
5
 
@@ -30,6 +32,7 @@ module EmailAddress
30
32
  @host = EmailAddress::Host.new(host, config)
31
33
  @config = @host.config
32
34
  @local = EmailAddress::Local.new(local, @config, @host)
35
+ @error = @error_message = nil
33
36
  end
34
37
 
35
38
  # Given an email address, this returns an array of [local, host] parts
@@ -228,7 +231,7 @@ module EmailAddress
228
231
  def valid?(options={})
229
232
  @error = nil
230
233
  unless self.local.valid?
231
- return set_error :invalid_mailbox
234
+ return set_error self.local.error
232
235
  end
233
236
  unless self.host.valid?
234
237
  return set_error self.host.error_message
@@ -259,7 +262,7 @@ module EmailAddress
259
262
  smtp.start(@config[:smtp_helo_name] || 'localhost')
260
263
  smtp.mailfrom @config[:smtp_mail_from] || 'postmaster@localhost'
261
264
  smtp.rcptto self.to_s
262
- p [:connect]
265
+ #p [:connect]
263
266
  smtp.finish
264
267
  true
265
268
  rescue Net::SMTPUnknownError => e
@@ -277,17 +280,18 @@ module EmailAddress
277
280
  end
278
281
 
279
282
  def set_error(err, reason=nil)
280
- @error = EmailAddress::Config.error_messages.fetch(err) { err }
283
+ @error = err
281
284
  @reason= reason
285
+ @error_message = EmailAddress::Config.error_message(err)
282
286
  false
283
287
  end
284
288
 
285
289
  def error_message
286
- @error
290
+ @error_message
287
291
  end
288
292
 
289
293
  def error
290
- self.valid? ? nil : @error
294
+ self.valid? ? nil : @error_message
291
295
  end
292
296
 
293
297
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  ################################################################################
2
4
  # ActiveRecord v5.0 Custom Type
3
5
  #
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module EmailAddress
2
4
  # Global configurations and for default/unknown providers. Settings are:
3
5
  #
@@ -92,6 +94,8 @@ module EmailAddress
92
94
  # * exchanger_match: %w(google.com 127.0.0.1 10.9.8.0/24 ::1/64)
93
95
  #
94
96
 
97
+ require 'yaml'
98
+
95
99
  class Config
96
100
  @config = {
97
101
  dns_lookup: :mx, # :mx, :a, :off
@@ -121,6 +125,7 @@ module EmailAddress
121
125
  address_fqdn_domain: nil, # Fully Qualified Domain Name = [host].[domain.tld]
122
126
  }
123
127
 
128
+ # 2018-04: AOL and Yahoo now under "oath.com", owned by Verizon. Keeping separate for now
124
129
  @providers = {
125
130
  aol: {
126
131
  host_match: %w(aol. compuserve. netscape. aim. cs.),
@@ -142,14 +147,10 @@ module EmailAddress
142
147
  },
143
148
  }
144
149
 
145
- @errors = {
146
- invalid_address: "Invalid Email Address",
147
- invalid_mailbox: "Invalid Recipient/Mailbox",
148
- invalid_host: "Invalid Host/Domain Name",
149
- exceeds_size: "Address too long",
150
- not_allowed: "Address is not allowed",
151
- incomplete_domain: "Domain name is incomplete",
152
- }
150
+
151
+ # Loads messages: {"en"=>{"email_address"=>{"invalid_address"=>"Invalid Email Address",...}}}
152
+ # Rails/I18n gem: t(email_address.error, scope: "email_address")
153
+ @errors = YAML.load_file(File.dirname(__FILE__)+"/messages.yaml")
153
154
 
154
155
  # Set multiple default configuration settings
155
156
  def self.configure(config={})
@@ -177,6 +178,10 @@ module EmailAddress
177
178
  @providers[name]
178
179
  end
179
180
 
181
+ def self.error_message(name, locale="en")
182
+ @errors[locale]["email_address"][name.to_s] || name.to_s
183
+ end
184
+
180
185
  # Customize your own error message text.
181
186
  def self.error_messages(hash=nil)
182
187
  @errors = @errors.merge(hash) if hash
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  ################################################################################
2
4
  # ActiveRecord v5.0 Custom Type
3
5
  #
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'resolv'
2
4
  require 'netaddr'
3
5
  require 'socket'
@@ -6,7 +8,7 @@ module EmailAddress
6
8
  class Exchanger
7
9
  include Enumerable
8
10
 
9
- def self.cached(host)
11
+ def self.cached(host, config={})
10
12
  @host_cache ||= {}
11
13
  @cache_size ||= ENV['EMAIL_ADDRESS_CACHE_SIZE'].to_i || 100
12
14
  if @host_cache.has_key?(host)
@@ -14,9 +16,9 @@ module EmailAddress
14
16
  @host_cache[host] = o # LRU cache, move to end
15
17
  elsif @host_cache.size >= @cache_size
16
18
  @host_cache.delete(@host_cache.keys.first)
17
- @host_cache[host] = new(host)
19
+ @host_cache[host] = new(host, config)
18
20
  else
19
- @host_cache[host] = new(host)
21
+ @host_cache[host] = new(host, config)
20
22
  end
21
23
  end
22
24
 
@@ -44,7 +46,11 @@ module EmailAddress
44
46
 
45
47
  # Returns: [["mta7.am0.yahoodns.net", "66.94.237.139", 1], ["mta5.am0.yahoodns.net", "67.195.168.230", 1], ["mta6.am0.yahoodns.net", "98.139.54.60", 1]]
46
48
  # If not found, returns []
49
+ # Returns a dummy record when dns_lookup is turned off since it may exists, though
50
+ # may not find provider by MX name or IP. I'm not sure about the "0.0.0.0" ip, it should
51
+ # be good in this context, but in "listen" context it means "all bound IP's"
47
52
  def mxers
53
+ return [["example.com", "0.0.0.0", 1]] if @config[:dns_lookup] == :off
48
54
  @mxers ||= Resolv::DNS.open do |dns|
49
55
  ress = dns.getresources(@host, Resolv::DNS::Resource::IN::MX)
50
56
  records = ress.map do |r|
@@ -69,6 +75,7 @@ module EmailAddress
69
75
 
70
76
  # Returns an array of MX IP address (String) for the given email domain
71
77
  def mx_ips
78
+ return ["0.0.0.0"] if @config[:dns_lookup] == :off
72
79
  mxers.map {|m| m[1] }
73
80
  end
74
81
 
@@ -1,3 +1,4 @@
1
+
1
2
  require 'simpleidn'
2
3
  require 'resolv'
3
4
  require 'netaddr'
@@ -88,6 +89,7 @@ module EmailAddress
88
89
  @original = host_name ||= ''
89
90
  config[:host_type] ||= :email
90
91
  @config = config
92
+ @error = @error_message = nil
91
93
  parse(host_name)
92
94
  end
93
95
 
@@ -334,6 +336,7 @@ module EmailAddress
334
336
 
335
337
  # Returns: [official_hostname, alias_hostnames, address_family, *address_list]
336
338
  def dns_a_record
339
+ @_dns_a_record = "0.0.0.0" if @config[:dns_lookup] == :off
337
340
  @_dns_a_record ||= Socket.gethostbyname(self.dns_name)
338
341
  rescue SocketError # not found, but could also mean network not work
339
342
  @_dns_a_record ||= []
@@ -343,7 +346,7 @@ module EmailAddress
343
346
  # The array will be empty if none are configured.
344
347
  def exchangers
345
348
  return nil if @config[:host_type] != :email || !self.dns_enabled?
346
- @_exchangers ||= EmailAddress::Exchanger.cached(self.dns_name)
349
+ @_exchangers ||= EmailAddress::Exchanger.cached(self.dns_name, @config)
347
350
  end
348
351
 
349
352
  # Returns a DNS TXT Record
@@ -398,11 +401,6 @@ module EmailAddress
398
401
  end
399
402
  end
400
403
 
401
- # The inverse of valid? -- Returns nil (falsey) if valid, otherwise error message
402
- def error
403
- valid? ? nil : @error_message
404
- end
405
-
406
404
  # True if the host name has a DNS A Record
407
405
  def valid_dns?
408
406
  bool = dns_a_record.size > 0 || set_error(:domain_unknown)
@@ -414,7 +412,9 @@ module EmailAddress
414
412
 
415
413
  # True if the host name has valid MX servers configured in DNS
416
414
  def valid_mx?
417
- if self.exchangers.mx_ips.size > 0
415
+ if self.exchangers.blank?
416
+ set_error(:domain_unknown)
417
+ elsif self.exchangers.mx_ips.size > 0
418
418
  if self.localhost? && !@config[:host_local]
419
419
  set_error(:domain_no_localhost)
420
420
  else
@@ -457,11 +457,11 @@ module EmailAddress
457
457
  if self.ip_address
458
458
  rel =
459
459
  if self.ip_address.include?(":")
460
- NetAddr::IPv6Net.parse("::1").rel(
460
+ NetAddr::IPv6Net.parse(""+"::1").rel(
461
461
  NetAddr::IPv6Net.parse(self.ip_address)
462
462
  )
463
463
  else
464
- NetAddr::IPv4Net.parse("127.0.0.0/8").rel(
464
+ NetAddr::IPv4Net.parse(""+"127.0.0.0/8").rel(
465
465
  NetAddr::IPv4Net.parse(self.ip_address)
466
466
  )
467
467
  end
@@ -492,10 +492,16 @@ module EmailAddress
492
492
  end
493
493
 
494
494
  def set_error(err, reason=nil)
495
- @error_message = EmailAddress::Config.error_messages.fetch(err) { err }
495
+ @error = err
496
496
  @reason = reason
497
+ @error_message = EmailAddress::Config.error_message(err)
497
498
  false
498
499
  end
499
500
 
501
+ # The inverse of valid? -- Returns nil (falsey) if valid, otherwise error message
502
+ def error
503
+ self.valid? ? nil : @error_message
504
+ end
505
+
500
506
  end
501
507
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module EmailAddress
2
4
  ##############################################################################
3
5
  # EmailAddress Local part consists of
@@ -103,6 +105,7 @@ module EmailAddress
103
105
  self.config = config.empty? ? EmailAddress::Config.all_settings : config
104
106
  self.local = local
105
107
  @host = host
108
+ @error = @error_message = nil
106
109
  end
107
110
 
108
111
  def local=(raw)
@@ -189,7 +192,7 @@ module EmailAddress
189
192
  self.conventional
190
193
  elsif form == :canonical
191
194
  self.canonical
192
- elsif form == :relax
195
+ elsif form == :relaxed
193
196
  self.relax
194
197
  elsif form == :standard
195
198
  self.standard
@@ -301,21 +304,23 @@ module EmailAddress
301
304
  end
302
305
 
303
306
  def valid_size?
307
+ return set_error(:local_size_long) if self.local.size > STANDARD_MAX_SIZE
304
308
  if @host && @host.hosted_service?
305
- return false if @config[:local_private_size] &&
306
- !@config[:local_private_size].include?(self.local.size)
307
- else
308
- return false if @config[:local_size] &&
309
- !@config[:local_size].include?(self.local.size)
309
+ return false if @config[:local_private_size] && !valid_size_checks(@config[:local_private_size])
310
310
  end
311
- return false if @config[:mailbox_size] && !@config[:mailbox_size].include?(self.mailbox.size)
312
- return false if self.local.size > STANDARD_MAX_SIZE
311
+ return false if @config[:local_size] && !valid_size_checks(@config[:local_size])
312
+ return false if @config[:mailbox_size] && !valid_size_checks(@config[:mailbox_size])
313
+ true
314
+ end
315
+
316
+ def valid_size_checks(range)
317
+ return set_error(:local_size_short) if self.mailbox.size < range.first
318
+ return set_error(:local_size_long) if self.mailbox.size > range.last
313
319
  true
314
320
  end
315
321
 
316
322
  def valid_encoding?(enc=@config[:local_encoding]||:ascii)
317
323
  return false if enc == :ascii && self.unicode?
318
- #return false if enc == :unicode && self.ascii?
319
324
  true
320
325
  end
321
326
 
@@ -365,5 +370,21 @@ module EmailAddress
365
370
  end
366
371
  false
367
372
  end
373
+
374
+ def set_error(err, reason=nil)
375
+ @error = err
376
+ @reason= reason
377
+ @error_message = EmailAddress::Config.error_message(err)
378
+ false
379
+ end
380
+
381
+ def error_message
382
+ @error_message
383
+ end
384
+
385
+ def error
386
+ self.valid? ? nil : @error
387
+ end
388
+
368
389
  end
369
390
  end
@@ -0,0 +1,20 @@
1
+ en:
2
+ email_address:
3
+ address_unknown: "Unknown Email Address"
4
+ domain_does_not_accept_email: "This domain is not configured to accept email"
5
+ domain_invalid: "Invalid Domain Name"
6
+ domain_no_localhost: "localhost is not allowed for your domain name"
7
+ domain_unknown: "Domain name not registered"
8
+ exceeds_size: "Address too long"
9
+ incomplete_domain: "Domain name is incomplete"
10
+ invalid_address: "Invalid Email Address"
11
+ invalid_host: "Invalid Host/Domain Name"
12
+ invalid_mailbox: "Invalid Mailbox"
13
+ ip_address_forbidden: "IP Addresses are not allowed"
14
+ ip_address_no_localhost: "Localhost IP addresses are not allowed"
15
+ ipv4_address_invalid: "This is not a valid IPv4 address"
16
+ ipv6_address_invalid: "This is not a valid IPv6 address"
17
+ local_size_long: "Mailbox name too long"
18
+ local_size_short: "Mailbox name too short"
19
+ not_allowed: "Address is not allowed"
20
+ server_not_available: "The remote email server is not available"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'base64'
2
4
 
3
5
  module EmailAddress::Rewriter
@@ -1,3 +1,3 @@
1
1
  module EmailAddress
2
- VERSION = "0.1.9"
2
+ VERSION = "0.1.10"
3
3
  end
@@ -77,9 +77,9 @@ class TestAddress < Minitest::Test
77
77
  e = EmailAddress.new("User+tag.gmail.ws") # No domain means localhost
78
78
  assert_equal '', e.hostname
79
79
  assert_equal false, e.valid? # localhost not allowed by default
80
- assert_equal EmailAddress.error("user1"), :domain_invalid
81
- assert_equal EmailAddress.error("user1", host_local:true), :domain_does_not_accept_email
82
- assert_equal EmailAddress.error("user1@localhost", host_local:true), :domain_does_not_accept_email
80
+ assert_equal EmailAddress.error("user1"), "Invalid Domain Name"
81
+ assert_equal EmailAddress.error("user1", host_local:true), "This domain is not configured to accept email"
82
+ assert_equal EmailAddress.error("user1@localhost", host_local:true), "This domain is not configured to accept email"
83
83
  assert_nil EmailAddress.error("user2@localhost", host_local:true, dns_lookup: :off, host_validation: :syntax)
84
84
  end
85
85
 
@@ -112,4 +112,8 @@ class TestAddress < Minitest::Test
112
112
  assert ! EmailAddress.valid?('example.user@foo.com/')
113
113
  end
114
114
 
115
+ def test_relaxed_normal
116
+ assert ! EmailAddress.new('a.c.m.e.-industries@foo.com').valid?
117
+ assert true, EmailAddress.new('a.c.m.e.-industries@foo.com', local_format: :relaxed).valid?
118
+ end
115
119
  end
@@ -114,12 +114,12 @@ class TestHost < MiniTest::Test
114
114
 
115
115
  def test_errors
116
116
  assert_nil EmailAddress::Host.new("yahoo.com").error
117
- assert_equal EmailAddress::Host.new("example.com").error, :domain_does_not_accept_email
118
- assert_equal EmailAddress::Host.new("yahoo.wtf").error, :domain_unknown
117
+ assert_equal EmailAddress::Host.new("example.com").error, "This domain is not configured to accept email"
118
+ assert_equal EmailAddress::Host.new("yahoo.wtf").error, "Domain name not registered"
119
119
  assert_nil EmailAddress::Host.new("ajsdfhajshdfklasjhd.wtf", host_validation: :syntax).error
120
- assert_equal EmailAddress::Host.new("ya hoo.com", host_validation: :syntax).error, :domain_invalid
121
- assert_equal EmailAddress::Host.new("[127.0.0.1]").error, :ip_address_forbidden
122
- assert_equal EmailAddress::Host.new("[127.0.0.666]", host_allow_ip:true).error, :ipv4_address_invalid
123
- assert_equal EmailAddress::Host.new("[IPv6::12t]", host_allow_ip:true).error, :ipv6_address_invalid
120
+ assert_equal EmailAddress::Host.new("ya hoo.com", host_validation: :syntax).error, "Invalid Domain Name"
121
+ assert_equal EmailAddress::Host.new("[127.0.0.1]").error, "IP Addresses are not allowed"
122
+ assert_equal EmailAddress::Host.new("[127.0.0.666]", host_allow_ip:true).error, "This is not a valid IPv4 address"
123
+ assert_equal EmailAddress::Host.new("[IPv6::12t]", host_allow_ip:true).error, "This is not a valid IPv6 address"
124
124
  end
125
125
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: email_address
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.9
4
+ version: 0.1.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Allen Fair
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-03-26 00:00:00.000000000 Z
11
+ date: 2018-07-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -44,28 +44,28 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '1.3'
47
+ version: 1.16.0
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '1.3'
54
+ version: 1.16.0
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: activerecord
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: 5.2.0.rc2
61
+ version: 5.2.0
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: 5.2.0.rc2
68
+ version: 5.2.0
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: sqlite3
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -145,6 +145,7 @@ files:
145
145
  - lib/email_address/exchanger.rb
146
146
  - lib/email_address/host.rb
147
147
  - lib/email_address/local.rb
148
+ - lib/email_address/messages.yaml
148
149
  - lib/email_address/rewriter.rb
149
150
  - lib/email_address/version.rb
150
151
  - test/activerecord/test_ar.rb
@@ -177,7 +178,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
177
178
  version: '0'
178
179
  requirements: []
179
180
  rubyforge_project:
180
- rubygems_version: 2.7.3
181
+ rubygems_version: 2.7.6
181
182
  signing_key:
182
183
  specification_version: 4
183
184
  summary: This gem provides a ruby language library for working with and validating