email_address 0.0.3 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,3 @@
1
1
  module EmailAddress
2
- VERSION = "0.0.3"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -0,0 +1,22 @@
1
+ # encoding: UTF-8
2
+ require_relative '../test_helper'
3
+
4
+ class TestAR < MiniTest::Test
5
+ require_relative 'user.rb'
6
+
7
+ def test_validation
8
+ user = User.new(email:"Pat.Jones+ASDF#GMAIL.com")
9
+ assert_equal false, user.valid?
10
+ user = User.new(email:"Pat.Jones+ASDF@GMAIL.com")
11
+ assert_equal true, user.valid?
12
+ end
13
+
14
+ def test_datatype
15
+ if defined?(ActiveRecord) && ::ActiveRecord::VERSION::MAJOR >= 5
16
+ user = User.new(email:"Pat.Jones+ASDF@GMAIL.com")
17
+ assert_equal 'pat.jones+asdf@gmail.com', user.email
18
+ assert_equal 'patjones@gmail.com', user.canonical_email
19
+ end
20
+ end
21
+
22
+ end
@@ -0,0 +1,71 @@
1
+ ################################################################################
2
+ # ActiveRecord Test Setup ...
3
+ ################################################################################
4
+
5
+ class ApplicationRecord < ActiveRecord::Base
6
+ self.abstract_class = true
7
+ end
8
+
9
+ dbfile = ENV['EMAIL_ADDRESS_TEST_DB'] || "/tmp/email_address.gem.db"
10
+ File.unlink(dbfile) if File.exist?(dbfile)
11
+
12
+ # Connection: JRuby vs. MRI
13
+ if RUBY_PLATFORM == 'java' # jruby
14
+ require 'jdbc/sqlite3'
15
+ require 'java'
16
+ require 'activerecord-jdbcsqlite3-adapter'
17
+ Jdbc::SQLite3.load_driver
18
+ ActiveRecord::Base.establish_connection(
19
+ :adapter => 'jdbc',
20
+ :driver => "org.sqlite.JDBC",
21
+ :url => "jdbc:sqlite:" + dbfile
22
+ )
23
+ else
24
+ require 'sqlite3'
25
+ ActiveRecord::Base.establish_connection(
26
+ :adapter => 'sqlite3',
27
+ :database => dbfile
28
+ )
29
+ end
30
+
31
+ ApplicationRecord.connection.execute(
32
+ "create table users ( email varchar, canonical_email varchar)")
33
+
34
+ if defined?(ActiveRecord) && ::ActiveRecord::VERSION::MAJOR >= 5
35
+ ActiveRecord::Type.register(:email_address, EmailAddress::EmailAddressType)
36
+ ActiveRecord::Type.register(:canonical_email_address,
37
+ EmailAddress::CanonicalEmailAddressType)
38
+ end
39
+
40
+ ################################################################################
41
+ # User Model
42
+ ################################################################################
43
+
44
+ class User < ApplicationRecord
45
+
46
+ if defined?(ActiveRecord) && ::ActiveRecord::VERSION::MAJOR >= 5
47
+ attribute :email, :email_address
48
+ attribute :canonical_email, :canonical_email_address
49
+ end
50
+
51
+ validates_with EmailAddress::ActiveRecordValidator,
52
+ fields: %i(email canonical_email)
53
+
54
+ def email=(email_address)
55
+ self[:canonical_email] = email_address
56
+ self[:email] = email_address
57
+ end
58
+
59
+ def self.find_by_email(email)
60
+ user = self.find_by(email: EmailAddress.normal(email))
61
+ user ||= self.find_by(canonical_email: EmailAddress.canonical(email))
62
+ user ||= self.find_by(canonical_email: EmailAddress.redacted(email))
63
+ user
64
+ end
65
+
66
+ def redact!
67
+ self[:canonical_email] = EmailAddress.redact(self.canonical_email)
68
+ self[:email] = self[:canonical_email]
69
+ end
70
+
71
+ end
@@ -6,47 +6,73 @@ class TestAddress < Minitest::Test
6
6
  a = EmailAddress.new("User+tag@example.com")
7
7
  assert_equal "user+tag", a.local.to_s
8
8
  assert_equal "example.com", a.host.to_s
9
- assert_equal :unknown, a.provider
9
+ assert_equal "us*****@ex*****", a.munge
10
+ assert_equal :default, a.provider
10
11
  end
11
12
 
12
- def test_noramlize
13
- a = EmailAddress.new("User+tag@Example.com")
14
- assert_equal "user+tag@example.com", a.normalize
13
+ # LOCAL
14
+ def test_local
15
+ a = EmailAddress.new("User+tag@example.com")
16
+ assert_equal "user", a.mailbox
17
+ assert_equal "user+tag", a.left
18
+ assert_equal "tag", a.tag
19
+ end
20
+
21
+ # HOST
22
+ def test_host
23
+ a = EmailAddress.new("User+tag@example.com")
24
+ assert_equal "example.com", a.hostname
25
+ #assert_equal :default, a.provider
15
26
  end
16
27
 
17
- def test_canonical
18
- a = EmailAddress.new("User+tag@Example.com")
28
+ # ADDRESS
29
+ def test_forms
30
+ a = EmailAddress.new("User+tag@example.com")
31
+ assert_equal "user+tag@example.com", a.to_s
19
32
  assert_equal "user@example.com", a.canonical
20
- a = EmailAddress.new("first.last+tag@gmail.com")
21
- assert_equal "firstlast@gmail.com", a.canonical
33
+ assert_equal "{63a710569261a24b3766275b7000ce8d7b32e2f7}@example.com", a.redact
34
+ assert_equal "b58996c504c5638798eb6b511e6f49af", a.reference
35
+ end
36
+
37
+ # COMPARISON & MATCHING
38
+ def test_compare
39
+ a = ("User+tag@example.com")
40
+ #e = EmailAddress.new("user@example.com")
41
+ n = EmailAddress.new(a)
42
+ c = EmailAddress.new_canonical(a)
43
+ #r = EmailAddress.new_redacted(a)
44
+ assert_equal true, n == "user+tag@example.com"
45
+ assert_equal true, n > "b@example.com"
46
+ assert_equal true, n.same_as?(c)
47
+ assert_equal true, n.same_as?(a)
22
48
  end
23
49
 
24
- def test_digest
25
- a = EmailAddress.new("User+tag@Example.com")
26
- assert_equal "b58996c504c5638798eb6b511e6f49af", a.md5
27
- assert_equal "63a710569261a24b3766275b7000ce8d7b32e2f7", a.sha1
28
- assert_equal "63a710569261a24b3766275b7000ce8d7b32e2f7@example.com", a.redact
50
+ def test_matches
51
+ a = EmailAddress.new("User+tag@gmail.com")
52
+ assert_equal false, a.matches?('mail.com')
53
+ assert_equal 'google', a.matches?('google')
54
+ assert_equal 'user+tag@', a.matches?('user+tag@')
55
+ assert_equal 'user*@gmail*', a.matches?('user*@gmail*')
29
56
  end
30
57
 
31
- def test_idn
32
- a = EmailAddress.new("User+tag@ɹᴉɐℲuǝll∀.ws")
33
- assert_equal "user@xn--ull-6eb78cvh231oq7gdzb.ws", a.canonical
34
- assert_equal "9c06226d81149f59b4df32bb426c64a0cbafcea5@xn--ull-6eb78cvh231oq7gdzb.ws", a.redact
58
+ # VALIDATION
59
+ def test_valid
60
+ assert EmailAddress.valid?("User+tag@example.com", dns_lookup: :a), "valid 1"
61
+ assert ! EmailAddress.valid?("User%tag@example.com", dns_lookup: :a), "valid 2"
62
+ assert EmailAddress.new("ɹᴉɐℲuǝll∀@ɹᴉɐℲuǝll∀.ws", local_encoding: :uncode, dns_lookup: :off ), "valid unicode"
35
63
  end
36
64
 
37
65
  def test_no_domain
38
66
  e = EmailAddress.new("User+tag.gmail.ws")
39
- assert_equal false, e.valid?
67
+ assert_equal '', e.hostname
68
+ assert_equal false, e.valid? # localhost not allowed by default
40
69
  end
41
70
 
42
- def test_equality
43
- a = EmailAddress.new("User+tag@Example.com")
44
- b = EmailAddress.new("user@Example.com")
45
- c = EmailAddress.new( EmailAddress.new("USER@Example.com").redact)
46
- assert a != b
47
- assert a < b
48
- assert b > a
49
- assert a.same_as?(b)
50
- assert a.same_as?(c)
71
+ def test_regexen
72
+ assert "First.Last+TAG@example.com".match(EmailAddress::Address::CONVENTIONAL_REGEX)
73
+ assert "First.Last+TAG@example.com".match(EmailAddress::Address::STANDARD_REGEX)
74
+ assert_equal nil, "First.Last+TAGexample.com".match(EmailAddress::Address::STANDARD_REGEX)
75
+ assert_equal nil, "First#Last+TAGexample.com".match(EmailAddress::Address::CONVENTIONAL_REGEX)
51
76
  end
77
+
52
78
  end
@@ -1,13 +1,28 @@
1
1
  require_relative '../test_helper'
2
2
 
3
3
  class TestConfig < MiniTest::Test
4
- def test_setup
5
- EmailAddress::Config.setup do
6
- provider :disposable, domains:%w(mailenator)
7
- option :downcase_mailboxes, true
8
- end
9
- assert_equal true, EmailAddress::Config.providers.has_key?(:disposable)
10
- assert_equal true, EmailAddress::Config.options[:downcase_mailboxes]
4
+ def test_setting
5
+ assert_equal :mx, EmailAddress::Config.setting(:dns_lookup)
6
+ assert_equal :off, EmailAddress::Config.setting(:dns_lookup, :off)
7
+ assert_equal :off, EmailAddress::Config.setting(:dns_lookup)
8
+ EmailAddress::Config.setting(:dns_lookup, :mx)
9
+ end
10
+
11
+ def test_configure
12
+ assert_equal :mx, EmailAddress::Config.setting(:dns_lookup)
13
+ assert_equal true, EmailAddress::Config.setting(:local_downcase)
14
+ EmailAddress::Config.configure(local_downcase:false, dns_lookup: :off)
15
+ assert_equal :off, EmailAddress::Config.setting(:dns_lookup)
16
+ assert_equal false, EmailAddress::Config.setting(:local_downcase)
17
+ EmailAddress::Config.configure(local_downcase:true, dns_lookup: :mx)
18
+ end
19
+
20
+ def test_provider
21
+ assert_equal nil, EmailAddress::Config.provider(:github)
22
+ EmailAddress::Config.provider(:github, host_match: %w(github.com), local_format: :standard)
23
+ assert_equal :standard, EmailAddress::Config.provider(:github)[:local_format]
24
+ assert_equal :github, EmailAddress::Host.new("github.com").provider
25
+ EmailAddress::Config.providers.delete(:github)
26
+ assert_equal nil, EmailAddress::Config.provider(:github)
11
27
  end
12
-
13
28
  end
@@ -3,17 +3,29 @@ require_relative '../test_helper'
3
3
 
4
4
  class TestExchanger < MiniTest::Test
5
5
  def test_exchanger
6
- a = EmailAddress::Exchanger.new("example.com")
7
- assert_equal true, a.has_dns_a_record? # example.com has no MX'ers
6
+ e = EmailAddress::Exchanger.new("gmail.com")
7
+ assert_equal true, e.mxers.size > 1
8
+ assert_equal :google, e.provider
9
+ assert_equal 'google.com', e.domains.first
10
+ assert_equal 'google.com', e.matches?("google.com")
11
+ assert_equal false, e.matches?("fa00:1450:4013:c01::1a/16")
12
+ assert_equal false, e.matches?("127.0.0.1/24")
13
+ assert_equal true, e.mx_ips.size > 1
8
14
  end
9
15
 
10
- def test_dns
11
- good = EmailAddress::Exchanger.new("gmail.com")
12
- bad = EmailAddress::Exchanger.new("exampldkeie4iufe.com")
13
- assert_equal true, good.has_dns_a_record?
14
- assert_equal false, bad.has_dns_a_record?
15
- assert_equal "gmail.com", good.dns_a_record.first
16
- assert(/google.com\z/, good.mxers.first.first)
17
- assert_equal 'google.com', good.domains.first
16
+ def test_not_found
17
+ e = EmailAddress::Exchanger.new("oops.gmail.com")
18
+ assert_equal 0, e.mxers.size
18
19
  end
20
+
21
+ #assert_equal true, a.has_dns_a_record? # example.com has no MX'ers
22
+ #def test_dns
23
+ # good = EmailAddress::Exchanger.new("gmail.com")
24
+ # bad = EmailAddress::Exchanger.new("exampldkeie4iufe.com")
25
+ # assert_equal true, good.has_dns_a_record?
26
+ # assert_equal false, bad.has_dns_a_record?
27
+ # assert_equal "gmail.com", good.dns_a_record.first
28
+ # assert(/google.com\z/, good.mxers.first.first)
29
+ # #assert_equal 'google.com', good.domains.first
30
+ #end
19
31
  end
@@ -9,7 +9,8 @@ class TestHost < MiniTest::Test
9
9
  assert_equal "example.com", a.domain_name
10
10
  assert_equal "example", a.registration_name
11
11
  assert_equal "com", a.tld
12
- assert_equal "", a.subdomains
12
+ assert_equal "ex*****", a.munge
13
+ assert_equal nil, a.subdomains
13
14
  end
14
15
 
15
16
  def test_foreign_host
@@ -17,27 +18,28 @@ class TestHost < MiniTest::Test
17
18
  assert_equal "my.yahoo.co.jp", a.host_name
18
19
  assert_equal "yahoo.co.jp", a.domain_name
19
20
  assert_equal "yahoo", a.registration_name
20
- assert_equal "co.jp", a.tld
21
+ assert_equal "co.jp", a.tld2
21
22
  assert_equal "my", a.subdomains
22
23
  end
23
24
 
24
25
  def test_ip_host
25
26
  a = EmailAddress::Host.new("[127.0.0.1]")
26
- assert_equal "[127.0.0.1]", a.host_name
27
+ assert_equal "[127.0.0.1]", a.name
27
28
  assert_equal "127.0.0.1", a.ip_address
28
-
29
29
  end
30
30
 
31
31
  def test_unicode_host
32
32
  a = EmailAddress::Host.new("å.com")
33
- assert_equal "xn--5ca.com", a.dns_host_name
33
+ assert_equal "xn--5ca.com", a.dns_name
34
+ a = EmailAddress::Host.new("xn--5ca.com", host_encoding: :unicode)
35
+ assert_equal "å.com", a.to_s
34
36
  end
35
37
 
36
38
  def test_provider
37
39
  a = EmailAddress::Host.new("my.yahoo.co.jp")
38
40
  assert_equal :yahoo, a.provider
39
41
  a = EmailAddress::Host.new("example.com")
40
- assert_equal :unknown, a.provider
42
+ assert_equal :default, a.provider
41
43
  end
42
44
 
43
45
  def test_dmarc
@@ -46,4 +48,43 @@ class TestHost < MiniTest::Test
46
48
  d = EmailAddress::Host.new("example.com").dmarc
47
49
  assert_equal true, d.empty?
48
50
  end
51
+
52
+ def test_ipv4
53
+ h = EmailAddress::Host.new("[127.0.0.1]", host_allow_ip:true)
54
+ assert_equal "127.0.0.1", h.ip_address
55
+ assert_equal true, h.valid?
56
+ end
57
+
58
+ def test_ipv6
59
+ h = EmailAddress::Host.new("[IPv6:::1]", host_allow_ip:true)
60
+ assert_equal "::1", h.ip_address
61
+ assert_equal true, h.valid?
62
+ end
63
+
64
+ def test_comment
65
+ h = EmailAddress::Host.new("(oops)gmail.com")
66
+ assert_equal 'gmail.com', h.to_s
67
+ assert_equal 'oops', h.comment
68
+ h = EmailAddress::Host.new("gmail.com(oops)")
69
+ assert_equal 'gmail.com', h.to_s
70
+ assert_equal 'oops', h.comment
71
+ end
72
+
73
+ def test_matches
74
+ h = EmailAddress::Host.new("yahoo.co.jp")
75
+ assert_equal false, h.matches?("gmail.com")
76
+ assert_equal 'yahoo.co.jp', h.matches?("yahoo.co.jp")
77
+ assert_equal '.co.jp', h.matches?(".co.jp")
78
+ assert_equal '.jp', h.matches?(".jp")
79
+ assert_equal 'yahoo.', h.matches?("yahoo.")
80
+ assert_equal 'yah*.jp', h.matches?("yah*.jp")
81
+ end
82
+
83
+ def test_regexen
84
+ assert "asdf.com".match EmailAddress::Host::CANONICAL_HOST_REGEX
85
+ assert "xn--5ca.com".match EmailAddress::Host::CANONICAL_HOST_REGEX
86
+ assert "[127.0.0.1]".match EmailAddress::Host::STANDARD_HOST_REGEX
87
+ assert "[IPv6:2001:dead::1]".match EmailAddress::Host::STANDARD_HOST_REGEX
88
+ assert_equal nil, "[256.0.0.1]".match(EmailAddress::Host::STANDARD_HOST_REGEX)
89
+ end
49
90
  end
@@ -2,30 +2,94 @@
2
2
  require_relative '../test_helper'
3
3
 
4
4
  class TestLocal < MiniTest::Test
5
- def test_local
6
- a = EmailAddress::Local.new("TestMonkey")
7
- assert_equal "testmonkey", a.to_s
5
+
6
+ def test_valid_standard
7
+ [ # Via https://en.wikipedia.org/wiki/Email_address
8
+ %Q{prettyandsimple},
9
+ %Q{very.common},
10
+ %Q{disposable.style.email.with+symbol},
11
+ %Q{other.email-with-dash},
12
+ %Q{"much.more unusual"},
13
+ %Q{"(comment)very.unusual.@.unusual.com"},
14
+ %Q{#!$%&'*+-/=?^_`{}|~},
15
+ %Q{" "},
16
+ %Q{"very.(),:;<>[]\\".VERY.\\"very@\\ \\"very\\".unusual"},
17
+ %Q{"()<>[]:,;@\\\"!#$%&'*+-/=?^_`{}| ~.a"},
18
+ %Q{token." ".token},
19
+ %Q{abc."defghi".xyz},
20
+ ].each do |local|
21
+ assert EmailAddress::Local.new(local, local_fix: false).standard?, local
22
+ end
23
+ end
24
+
25
+ def test_invalid_standard
26
+ [ # Via https://en.wikipedia.org/wiki/Email_address
27
+ %Q{A@b@c},
28
+ %Q{a"b(c)d,e:f;g<h>i[j\k]l},
29
+ %Q{just"not"right},
30
+ %Q{this is"not\allowed},
31
+ %Q{this\ still\"not\\allowed},
32
+ %Q{john..doe},
33
+ %Q{ invalid},
34
+ %Q{invalid },
35
+ %Q{abc"defghi"xyz},
36
+ ].each do |local|
37
+ assert_equal false, EmailAddress::Local.new(local, local_fix: false).standard?, local
38
+ end
39
+ end
40
+
41
+ def test_relaxed
42
+ assert EmailAddress::Local.new("first..last", local_format: :relaxed).valid?, "relax.."
43
+ assert EmailAddress::Local.new("first.-last", local_format: :relaxed).valid?, "relax.-"
44
+ assert EmailAddress::Local.new("a", local_format: :relaxed).valid?, "relax single"
45
+ assert ! EmailAddress::Local.new("firstlast_", local_format: :relaxed).valid?, "last_"
46
+ end
47
+
48
+ def test_unicode
49
+ assert ! EmailAddress::Local.new("üñîçøðé1", local_encoding: :ascii).standard?, "not üñîçøðé1"
50
+ assert EmailAddress::Local.new("üñîçøðé2", local_encoding: :unicode).standard?, "üñîçøðé2"
51
+ assert ! EmailAddress::Local.new("üñîçøðé3").valid?, "üñîçøðé3 valid"
8
52
  end
9
53
 
10
- def test_tag_comment
11
- a = EmailAddress::Local.new("User+tag(comment!)")
12
- assert_equal "user", a.mailbox
13
- assert_equal "comment!", a.comment
14
- assert_equal "tag", a.tag
54
+
55
+ def test_valid_conventional
56
+ %w( first.last first First+Tag o'brien).each do |local|
57
+ assert EmailAddress::Local.new(local).conventional?, local
58
+ end
59
+ end
60
+
61
+ def test_invalid_conventional
62
+ (%w( first;.last +leading trailing+ o%brien) + ["first space"]).each do |local|
63
+ assert ! EmailAddress::Local.new(local, local_fix:false).conventional?, local
64
+ end
65
+ end
66
+
67
+ def test_valid
68
+ assert_equal false, EmailAddress::Local.new("first(comment)", local_format: :conventional).valid?
69
+ assert_equal true, EmailAddress::Local.new("first(comment)", local_format: :standard).valid?
15
70
  end
16
71
 
17
72
  def test_format
18
- a = EmailAddress::Local.new("(Comment!)First Last+tag")
19
- assert_equal 'firstlast+tag', a.normalize
73
+ assert_equal :conventional, EmailAddress::Local.new("can1").format?
74
+ assert_equal :standard, EmailAddress::Local.new(%Q{"can1"}).format?
75
+ assert_equal "can1", EmailAddress::Local.new(%Q{"can1(commment)"}).format(:conventional)
20
76
  end
21
77
 
22
- def test_gmail
23
- a = EmailAddress::Local.new("first.last", EmailAddress::Host.new('gmail.com'))
24
- assert_equal "firstlast", a.canonical
78
+ def test_redacted
79
+ l = "{bea3f3560a757f8142d38d212a931237b218eb5e}"
80
+ assert EmailAddress::Local.redacted?(l), "redacted? #{l}"
81
+ assert_equal :redacted, EmailAddress::Local.new(l).format?
25
82
  end
26
83
 
27
- def test_root_name
28
- a = EmailAddress::Local.new("superman123", EmailAddress::Host.new('gmail.com'))
29
- assert_equal "superman", a.root_name
84
+ def test_matches
85
+ a = EmailAddress.new("User+tag@gmail.com")
86
+ assert_equal false, a.matches?('user')
87
+ assert_equal false, a.matches?('user@')
88
+ assert_equal 'user*@', a.matches?('user*@')
30
89
  end
90
+
91
+ def test_munge
92
+ assert_equal "us*****", EmailAddress::Local.new("User+tag").munge
93
+ end
94
+
31
95
  end