email_address 0.1.1 → 0.1.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: aecafb936eb2bce2258d43020087efa6fb7a352b
4
- data.tar.gz: 9db91ef371beae264be3ddbc8e50b8e3cbbfb02e
3
+ metadata.gz: b6a59891931ddfd551f8ead37a376795d22e70eb
4
+ data.tar.gz: 8b71384418e8b1a4eb505faa5e95e021f0b30b7d
5
5
  SHA512:
6
- metadata.gz: e715c704ca4c78fc6dbce5e77e3545a7ba3dea40278dc114e79315dfced08af8088c711507569e0a98ad5738e7088727e961300426966a12180d20880e4a2fed
7
- data.tar.gz: 0f07a721fff632161f1d30893acf30f423162371d18be4be54a381c4211b18605a16dfd994ef1320e54102df6922361c19427fd43f21d934805d36a2265225a3
6
+ metadata.gz: 62af3189a51354059a4d05e03c294e12a3e76839bb4cafd0697231fae638cbe5959324034cbdeea4d83f8a10303e6f7e6bad4c7aa0d2bd90bd7ef3bbafc0c930
7
+ data.tar.gz: 34d7af8021c044f4cc4e1e00c4d2aa0e0066881178f7300c6322ccad52dd7787448b0929efb1148cfc582e6b073d9ae318fe515937bab9085a94e6ddfa98ab3b
data/README.md CHANGED
@@ -365,6 +365,21 @@ configuration options:
365
365
  EmailAddress::Config.provider(:github,
366
366
  host_match: %w(github.com), local_format: :standard)
367
367
 
368
+ #### Override Error Messaegs
369
+
370
+ You can override the default error messages as follows:
371
+
372
+ EmailAddress::Config.error_messages(
373
+ invalid_address: "Invalid Email Address",
374
+ invalid_mailbox: "Invalid Recipient/Mailbox",
375
+ invalid_host: "Invalid Host/Domain Name",
376
+ exceeds_size: "Address too long",
377
+ not_allowed: "Address is not allowed",
378
+ incomplete_domain: "Domain name is incomplete")
379
+
380
+ Full translation support would be ideal though.
381
+
382
+
368
383
  ### Available Configuration Settings
369
384
 
370
385
  * dns_lookup: Enables DNS lookup for validation by
@@ -21,7 +21,7 @@ Gem::Specification.new do |spec|
21
21
  spec.add_development_dependency "rake"
22
22
  spec.add_development_dependency "minitest", "~> 5.8.3"
23
23
  spec.add_development_dependency "bundler", "~> 1.3"
24
- spec.add_development_dependency "activerecord", "~> 5.0.0.beta1" if RUBY_PLATFORM != 'java'
24
+ spec.add_development_dependency "activerecord", "~> 5.0.1" if RUBY_PLATFORM != 'java'
25
25
  spec.add_development_dependency "activerecord", "~> 4.2.5" if RUBY_PLATFORM == 'java'
26
26
  spec.add_development_dependency "sqlite3" if RUBY_PLATFORM != 'java'
27
27
  spec.add_development_dependency "activerecord-jdbcsqlite3-adapter" if RUBY_PLATFORM == 'java'
@@ -34,7 +34,11 @@ module EmailAddress
34
34
  def validate_email(r,f)
35
35
  return if r[f].nil?
36
36
  e = EmailAddress.new(r[f])
37
- r.errors[f] << "Email Address Not Valid" unless e.valid?
37
+ unless e.valid?
38
+ r.errors[f] << (@opt[:message] ||
39
+ EmailAddress::Config.error_messages[:invalid_address] ||
40
+ "Invalid Email Address")
41
+ end
38
42
  end
39
43
 
40
44
  end
@@ -6,12 +6,14 @@ module EmailAddress
6
6
  # (EmailAddress::Local) and Host (Email::AddressHost) parts.
7
7
  class Address
8
8
  include Comparable
9
- attr_accessor :original, :local, :host, :config, :error
9
+ attr_accessor :original, :local, :host, :config
10
10
 
11
11
  CONVENTIONAL_REGEX = /\A#{::EmailAddress::Local::CONVENTIONAL_MAILBOX_WITHIN}
12
12
  @#{::EmailAddress::Host::DNS_HOST_REGEX}\z/x
13
13
  STANDARD_REGEX = /\A#{::EmailAddress::Local::STANDARD_LOCAL_WITHIN}
14
14
  @#{::EmailAddress::Host::DNS_HOST_REGEX}\z/x
15
+ RELAXED_REGEX = /\A#{::EmailAddress::Local::RELAXED_MAILBOX_WITHIN}
16
+ @#{::EmailAddress::Host::DNS_HOST_REGEX}\z/x
15
17
 
16
18
  # Given an email address of the form "local@hostname", this sets up the
17
19
  # instance, and initializes the address to the "normalized" format of the
@@ -109,7 +111,9 @@ module EmailAddress
109
111
  # spaves and comments and tags, and any extraneous part of the address
110
112
  # not considered a unique account by the provider.
111
113
  def canonical
112
- [self.local.canonical, @host.canonical].join('@')
114
+ c = self.local.canonical
115
+ c += "@" + self.host.canonical if self.host.canonical && self.host.canonical > " "
116
+ c
113
117
  end
114
118
 
115
119
  # True if the given address is already in it's canonical form.
@@ -119,9 +123,13 @@ module EmailAddress
119
123
 
120
124
  # Returns the redacted form of the address
121
125
  # This format is defined by this libaray, and may change as usage increases.
122
- def redact
126
+ # Takes either :sha1 (default) or :md5 as the argument
127
+ def redact(digest=:sha1)
128
+ raise "Unknown Digest type: #{digest}" unless %i(sha1 md5).include?(digest)
123
129
  return self.to_s if self.local.redacted?
124
- %Q({#{self.sha1}}@#{self.host.to_s})
130
+ r = %Q({#{send(digest)}})
131
+ r += "@" + self.host.to_s if self.host.to_s && self.host.to_s > " "
132
+ r
125
133
  end
126
134
 
127
135
  # True if the address is already in the redacted state.
@@ -147,7 +155,7 @@ module EmailAddress
147
155
  # This returns the SHA1 digest (in a hex string) of the canonical email
148
156
  # address. See #md5 for more background.
149
157
  def sha1
150
- Digest::SHA1.hexdigest(canonical + @config[:sha1_secret])
158
+ Digest::SHA1.hexdigest((canonical||"") + (@config[:sha1_secret]||""))
151
159
  end
152
160
 
153
161
  #---------------------------------------------------------------------------
@@ -204,35 +212,35 @@ module EmailAddress
204
212
  # Returns true if this address is considered valid according to the format
205
213
  # configured for its provider, It test the normalized form.
206
214
  def valid?(options={})
207
- self.error = nil
215
+ @error = nil
208
216
  unless self.local.valid?
209
- self.error = "Invalid Mailbox"
210
- return false
217
+ return set_error :invalid_mailbox
211
218
  end
212
219
  unless self.host.valid?
213
- self.error = "Invalid Host"
214
- return false
220
+ return set_error :invalid_host
215
221
  end
216
222
  if @config[:address_size] && !@config[:address_size].include?(self.to_s.size)
217
- self.error = "Exceeds size"
218
- return false
223
+ return set_error :exceeds_size
219
224
  end
220
225
  if @config[:address_validation].is_a?(Proc)
221
226
  unless @config[:address_validation].call(self.to_s)
222
- self.error = "Not allowed"
223
- return false
227
+ return set_error :not_allowed
224
228
  end
225
229
  else
226
230
  return false unless self.local.valid?
227
231
  return false unless self.host.valid?
228
232
  end
229
233
  if !@config[:address_local] && !self.hostname.include?(".")
230
- self.error = "Incomplete Domain"
231
- return false
234
+ return set_error :incomplete_domain
232
235
  end
233
236
  true
234
237
  end
235
238
 
239
+ def set_error(err)
240
+ @error = EmailAddress::Config.error_messages[err] || err
241
+ false
242
+ end
243
+
236
244
  def error
237
245
  self.valid? ? nil : @error
238
246
  end
@@ -84,6 +84,7 @@ module EmailAddress
84
84
  # The value is an array of match tokens.
85
85
  # * host_match: %w(.org example.com hotmail. user*@ sub.*.com)
86
86
  # * exchanger_match: %w(google.com 127.0.0.1 10.9.8.0/24 ::1/64)
87
+ #
87
88
 
88
89
  class Config
89
90
  @config = {
@@ -132,6 +133,15 @@ module EmailAddress
132
133
  },
133
134
  }
134
135
 
136
+ @errors = {
137
+ invalid_address: "Invalid Email Address",
138
+ invalid_mailbox: "Invalid Recipient/Mailbox",
139
+ invalid_host: "Invalid Host/Domain Name",
140
+ exceeds_size: "Address too long",
141
+ not_allowed: "Address is not allowed",
142
+ incomplete_domain: "Domain name is incomplete",
143
+ }
144
+
135
145
  # Set multiple default configuration settings
136
146
  def self.configure(config={})
137
147
  @config.merge!(config)
@@ -158,6 +168,12 @@ module EmailAddress
158
168
  @providers[name]
159
169
  end
160
170
 
171
+ # Customize your own error message text.
172
+ def self.error_messages(hash=nil)
173
+ @errors = @errors.merge(hash) if hash
174
+ @errors
175
+ end
176
+
161
177
  def self.all_settings(*configs)
162
178
  config = @config.clone
163
179
  configs.each {|c| config.merge!(c) }
@@ -33,7 +33,7 @@ module EmailAddress
33
33
 
34
34
  # Returns the provider name based on the MX-er host names, or nil if not matched
35
35
  def provider
36
- return @provider if @provider
36
+ return @provider if defined? @provider
37
37
  EmailAddress::Config.providers.each do |provider, config|
38
38
  if config[:exchanger_match] && self.matches?(config[:exchanger_match])
39
39
  return @provider = provider
@@ -47,10 +47,15 @@ module EmailAddress
47
47
  def mxers
48
48
  @mxers ||= Resolv::DNS.open do |dns|
49
49
  ress = dns.getresources(@host, Resolv::DNS::Resource::IN::MX)
50
- ress.map { |r| [r.exchange.to_s, IPSocket::getaddress(r.exchange.to_s), r.preference] }
50
+ records = ress.map do |r|
51
+ begin
52
+ [r.exchange.to_s, IPSocket::getaddress(r.exchange.to_s), r.preference]
53
+ rescue SocketError # not found, but could also mean network not work or it could mean one record doesn't resolve an address
54
+ nil
55
+ end
56
+ end
57
+ records.compact
51
58
  end
52
- rescue SocketError # not found, but could also mean network not work
53
- @_dns_a_record ||= []
54
59
  end
55
60
 
56
61
  # Returns Array of domain names for the MX'ers, used to determine the Provider
@@ -30,7 +30,8 @@ module EmailAddress
30
30
  # that provider.
31
31
  ##############################################################################
32
32
  class Host
33
- attr_accessor :host_name, :dns_name, :domain_name, :registration_name,
33
+ attr_reader :host_name
34
+ attr_accessor :dns_name, :domain_name, :registration_name,
34
35
  :tld, :tld2, :subdomains, :ip_address, :config, :provider,
35
36
  :comment
36
37
  MAX_HOST_LENGTH = 255
@@ -65,7 +65,8 @@ module EmailAddress
65
65
  # [CFWS]
66
66
  ############################################################################
67
67
  class Local
68
- attr_accessor :mailbox, :comment, :tag, :local, :config, :original
68
+ attr_reader :local
69
+ attr_accessor :mailbox, :comment, :tag, :config, :original
69
70
  attr_accessor :syntax
70
71
 
71
72
  # RFC-2142: MAILBOX NAMES FOR COMMON SERVICES, ROLES AND FUNCTIONS
@@ -79,19 +80,20 @@ module EmailAddress
79
80
  STANDARD_MAX_SIZE = 64
80
81
 
81
82
  # Conventional : word([.-+'_]word)*
82
- CONVENTIONAL_MAILBOX_REGEX = /\A [\p{L}\p{N}]+ ( [\.\-\+\'_] [\p{L}\p{N}]+ )* \z/x
83
- CONVENTIONAL_MAILBOX_WITHIN = /[\p{L}\p{N}]+ ( [\.\-\+\'_] [\p{L}\p{N}]+ )*/x
83
+ CONVENTIONAL_MAILBOX_REGEX = /\A [\p{L}\p{N}]+ (?: [\.\-\+\'_] [\p{L}\p{N}]+ )* \z/x
84
+ CONVENTIONAL_MAILBOX_WITHIN = /[\p{L}\p{N}]+ (?: [\.\-\+\'_] [\p{L}\p{N}]+ )*/x
84
85
 
85
86
  # Relaxed: same characters, relaxed order
86
- RELAXED_MAILBOX_REGEX = /\A [\p{L}\p{N}]+ ( [\.\-\+\'_]+ [\p{L}\p{N}]+ )* \z/x
87
+ RELAXED_MAILBOX_WITHIN = /[\p{L}\p{N}]+ (?: [\.\-\+\'_]+ [\p{L}\p{N}]+ )*/x
88
+ RELAXED_MAILBOX_REGEX = /\A [\p{L}\p{N}]+ (?: [\.\-\+\'_]+ [\p{L}\p{N}]+ )* \z/x
87
89
 
88
90
  # RFC5322 Token: token."token".token (dot-separated tokens)
89
91
  # Quoted Token can also have: SPACE \" \\ ( ) , : ; < > @ [ \ ] .
90
92
  STANDARD_LOCAL_WITHIN = /
91
- ( [\p{L}\p{N}\!\#\$\%\&\'\*\+\-\/\=\?\^\_\`\{\|\}\~\(\)]+
92
- | \" ( \\[\" \\] | [\x20 \! \x23-\x5B \x5D-\x7E \p{L} \p{N}] )+ \" )
93
- ( \. ( [\p{L}\p{N}\!\#\$\%\&\'\*\+\-\/\=\?\^\_\`\{\|\}\~\(\)]+
94
- | \" ( \\[\" \\] | [\x20 \! \x23-\x5B \x5D-\x7E \p{L} \p{N}] )+ \" ) )* /x
93
+ (?: [\p{L}\p{N}\!\#\$\%\&\'\*\+\-\/\=\?\^\_\`\{\|\}\~\(\)]+
94
+ | \" (?: \\[\" \\] | [\x20 \! \x23-\x5B \x5D-\x7E \p{L} \p{N}] )+ \" )
95
+ (?: \. (?: [\p{L}\p{N}\!\#\$\%\&\'\*\+\-\/\=\?\^\_\`\{\|\}\~\(\)]+
96
+ | \" (?: \\[\" \\] | [\x20 \! \x23-\x5B \x5D-\x7E \p{L} \p{N}] )+ \" ) )* /x
95
97
  STANDARD_LOCAL_REGEX = /\A #{STANDARD_LOCAL_WITHIN} \z/x
96
98
 
97
99
  REDACTED_REGEX = /\A \{ [0-9a-f]{40} \} \z/x # {sha1}
@@ -1,3 +1,3 @@
1
1
  module EmailAddress
2
- VERSION = "0.1.1"
2
+ VERSION = "0.1.2"
3
3
  end
@@ -7,6 +7,7 @@ class TestAR < MiniTest::Test
7
7
  def test_validation
8
8
  user = User.new(email:"Pat.Jones+ASDF#GMAIL.com")
9
9
  assert_equal false, user.valid?
10
+ assert user.errors.messages[:email].first
10
11
  user = User.new(email:"Pat.Jones+ASDF@GMAIL.com")
11
12
  assert_equal true, user.valid?
12
13
  end
@@ -31,6 +31,7 @@ class TestAddress < Minitest::Test
31
31
  assert_equal "user+tag@example.com", a.to_s
32
32
  assert_equal "user@example.com", a.canonical
33
33
  assert_equal "{63a710569261a24b3766275b7000ce8d7b32e2f7}@example.com", a.redact
34
+ assert_equal "{b58996c504c5638798eb6b511e6f49af}@example.com", a.redact(:md5)
34
35
  assert_equal "b58996c504c5638798eb6b511e6f49af", a.reference
35
36
  end
36
37
 
@@ -55,6 +56,14 @@ class TestAddress < Minitest::Test
55
56
  assert_equal 'user*@gmail*', a.matches?('user*@gmail*')
56
57
  end
57
58
 
59
+ def test_empty_address
60
+ a = EmailAddress.new("")
61
+ assert_equal "{da39a3ee5e6b4b0d3255bfef95601890afd80709}", a.redact
62
+ assert_equal "", a.to_s
63
+ assert_equal "", a.canonical
64
+ assert_equal "d41d8cd98f00b204e9800998ecf8427e", a.reference
65
+ end
66
+
58
67
  # VALIDATION
59
68
  def test_valid
60
69
  assert EmailAddress.valid?("User+tag@example.com", dns_lookup: :a), "valid 1"
@@ -73,6 +82,7 @@ class TestAddress < Minitest::Test
73
82
  assert "First.Last+TAG@example.com".match(EmailAddress::Address::STANDARD_REGEX)
74
83
  assert_equal nil, "First.Last+TAGexample.com".match(EmailAddress::Address::STANDARD_REGEX)
75
84
  assert_equal nil, "First#Last+TAGexample.com".match(EmailAddress::Address::CONVENTIONAL_REGEX)
85
+ assert "aasdf-34-.z@example.com".match(EmailAddress::Address::RELAXED_REGEX)
76
86
  end
77
87
 
78
88
  end
data/test/test_helper.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
2
 
3
- require 'codeclimate-test-reporter'
4
- CodeClimate::TestReporter.start
3
+ require 'simplecov'
4
+ SimpleCov.start
5
5
 
6
6
  require 'active_record'
7
7
  require 'rubygems'
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.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Allen Fair
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-09-19 00:00:00.000000000 Z
11
+ date: 2017-02-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -58,14 +58,14 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: 5.0.0.beta1
61
+ version: 5.0.1
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.0.0.beta1
68
+ version: 5.0.1
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: sqlite3
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -175,7 +175,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
175
175
  version: '0'
176
176
  requirements: []
177
177
  rubyforge_project:
178
- rubygems_version: 2.5.1
178
+ rubygems_version: 2.6.8
179
179
  signing_key:
180
180
  specification_version: 4
181
181
  summary: This gem provides a ruby language library for working with and validating