email_address 0.1.1 → 0.1.2

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
  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