email_address 0.0.1 → 0.0.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.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -0
  3. data/README.md +99 -32
  4. data/email_address.gemspec +2 -1
  5. data/lib/email_address.rb +14 -142
  6. data/lib/email_address/address.rb +70 -0
  7. data/lib/email_address/config.rb +75 -0
  8. data/lib/email_address/domain_matcher.rb +90 -0
  9. data/lib/email_address/domain_parser.rb +71 -0
  10. data/lib/email_address/exchanger.rb +67 -0
  11. data/lib/email_address/host.rb +71 -1
  12. data/lib/email_address/local.rb +97 -0
  13. data/lib/email_address/validator.rb +135 -0
  14. data/lib/email_address/version.rb +1 -1
  15. data/test/email_address/test_address.rb +30 -0
  16. data/test/email_address/test_config.rb +13 -0
  17. data/test/email_address/test_domain_matcher.rb +15 -0
  18. data/test/email_address/test_domain_parser.rb +29 -0
  19. data/test/email_address/test_exchanger.rb +19 -0
  20. data/test/email_address/test_host.rb +43 -0
  21. data/test/email_address/test_local.rb +27 -0
  22. data/test/email_address/test_validator.rb +16 -0
  23. data/test/test_email_address.rb +12 -0
  24. metadata +40 -27
  25. data/lib/email_address/esp.rb +0 -4
  26. data/lib/email_address/providers/default.rb +0 -8
  27. data/lib/email_address/providers/google.rb +0 -8
  28. data/lib/email_providers/address.rb +0 -102
  29. data/lib/email_providers/config.rb +0 -36
  30. data/lib/email_providers/factory.rb +0 -17
  31. data/lib/email_providers/host.rb +0 -87
  32. data/lib/email_providers/mail_exchanger.rb +0 -60
  33. data/lib/email_providers/mailbox.rb +0 -44
  34. data/lib/email_providers/providers/default.rb +0 -55
  35. data/lib/email_providers/providers/google.rb +0 -27
  36. data/lib/email_providers/version.rb +0 -3
  37. data/test/email_address.rb +0 -52
  38. data/test/email_address/address.rb +0 -16
  39. data/test/email_address/config.rb +0 -13
  40. data/test/email_address/host.rb +0 -29
  41. data/test/email_address/mail_exchanger.rb +0 -9
@@ -1,36 +0,0 @@
1
- module EmailAddress
2
- class Config
3
-
4
- # EmailAddress::Config.add_provider(:google, domain_names:["gmail.com", "googlemail.com", "google.com"])
5
- def self.add_provider(provider, matches={})
6
- @pmatch ||= []
7
- @pmatch << matches
8
- end
9
-
10
- # EmailAddress::Config.config do .... end
11
- def self.setup(&block)
12
- @config = Config::DSL.new(&block)
13
- @config.instance_eval(&block)
14
- end
15
-
16
- def self.get
17
- @config
18
- end
19
-
20
- class DSL
21
- attr_accessor :provider_matching_rules
22
- def add_provider(provider, matches={})
23
- puts provider, matches
24
- @provider_matching_rules ||= []
25
- @provider_matching_rules << {provider:provider, matches:matches}
26
- end
27
- end
28
- end
29
- end
30
-
31
-
32
- #EmailAddress::Config.setup do
33
- # add_provider :google, domain_names:["gmail.com", "googlemail.com", "google.com"]
34
- #end
35
-
36
- #puts EmailAddress::Config.provider_matching_rules
@@ -1,17 +0,0 @@
1
- module EmailAddress
2
-
3
- # EmailAddress::Address - Inspects a Email Address.
4
- #
5
- # Format: mailbox@hostname
6
- #
7
- class Factory
8
- attr_reader :mailbox, :host
9
-
10
- def address(address)
11
- (@mailbox, host) = address.strip.split(/\@/)
12
- return unless host
13
- @host = EmailAddress::Host.new(host)
14
- @mailbox = @host.provider_address(@mailbox)
15
- end
16
- end
17
- end
@@ -1,87 +0,0 @@
1
- # EmailAddress::Address
2
- # EmailAddress::Host
3
- # EmailAddress::MailExchanger
4
- # EmailAddress::Config
5
- # EmailAddress::EspMapping
6
- # EmailAddress::Esp::Base, Yahoo, Msn, ...
7
-
8
- require 'simpleidn'
9
-
10
- module EmailAddress
11
-
12
- # EmailAddress::Host handles mail host properties of an email address
13
- # The host is typically the data to the right of the @ in the address
14
- # and consists of:
15
- #
16
- # * hostname - full name of DNS host with the MX record.
17
- # * domain_name - generally, the name and TLD without subdomain
18
- # * base_domain - the identity name of the domain name, without the tld
19
- # * tld (top-level-domain), like .com, .co.jp, .com.xx, etc.
20
- # * subdomain - optional name of server/service under the domain
21
- # * esp (email service provider) a name of the provider: yahoo, msn, etc.
22
- # * dns_hostname - Converted hostname Unicode to Punycode
23
-
24
- class Host
25
- attr_reader :host, :domain_name, :tld, :base_domain, :subdomains, :dns_hostname
26
-
27
- def initialize(host)
28
- host.gsub!(/\A.*@/, '')
29
- host.downcase!
30
- self.host = host
31
- end
32
-
33
- def address(mailbox)
34
- # Determine EmailAddress::Provider::Xxxx
35
- EmailAddress::Address.new(mailbox, self)
36
- end
37
-
38
- def host=(host)
39
- @host = host
40
- # Patterns: *.com, *.xx.cc, *.cc
41
- if @host =~ /(.+)\.(\w{3,10})\z/ || @host =~ /(.+)\.(\w{1,3}\.\w\w)\z/ || @host =~ /(.+)\.(\w\w)\z/
42
- @tld = $2;
43
- sld = $1 # Second level domain
44
- if @sld =~ /(.+)\.(.+)$/ # is subdomain?
45
- @subdomains = $1
46
- @base_domain = $2
47
- else
48
- @subdomains = ""
49
- @base_domain = sld
50
- end
51
- @domain_name = @base_domain + '.' + @tld
52
- @dns_hostname = SimpleIDN.to_ascii(@host)
53
- @host
54
- end
55
- end
56
-
57
- # Resets the host to the domain name, dropping any subdomain
58
- def drop_subdomain!
59
- self.hostname = domain_name
60
- end
61
-
62
- def valid?
63
- return false unless valid_format?
64
- return false unless valid_mx?
65
- true
66
- end
67
-
68
- def valid_format?
69
- Host.valid_format?(@host)
70
- end
71
-
72
- def self.valid_format?(host)
73
- return false unless host.match(/\A([0-9a-z\-]{1,63}\.)+[a-z0-9\-]{2,15}\z/)
74
- return false unless host.length <= 253
75
- true
76
- end
77
-
78
- def valid_mx?
79
- Host.valid_mx?(@host)
80
- end
81
-
82
- def self.valid_mx?(host)
83
- true
84
- end
85
-
86
- end
87
- end
@@ -1,60 +0,0 @@
1
- require 'resolv'
2
- require 'netaddr'
3
- require 'socket'
4
-
5
- class MailExchanger
6
- cattr_accessor :domains, :lookups
7
-
8
- def self.valid_mx?(domain)
9
- dns_a_record_exists?(domain) || mxers(domain).size > 0
10
- end
11
-
12
- def self.dns_a_record_exists?(domain)
13
- @dns_a_record ||= {}
14
- @dns_a_record[domain] = false
15
- if Socket.gethostbyname(domain)
16
- return @dns_a_record[domain] = true
17
- end
18
- rescue SocketError # not found
19
- @dns_a_record[domain] = false
20
- end
21
-
22
- # Returns DNS A record results for the domain as: [[domain, ip, 0],...]
23
- def self.domain_hosts(domain)
24
- @domain_hosts ||= {}
25
- @domain_hosts[domain] = []
26
- res = TCPSocket.gethostbyname(domain)
27
- res = res.slice(3, res.size)
28
- res.each { |r| @domain_hosts[domain] << [domain, r, 0] }
29
- @domain_hosts[domain]
30
-
31
- rescue SocketError
32
- return []
33
- end
34
-
35
- # 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]]
36
- # If not found, returns []
37
- def self.mxers(domain)
38
- @domains ||= {}
39
- return @domains[domain] if @domains.key?(domain)
40
- @lookups = @lookups ? @lookups + 1 : 1
41
- mx = nil
42
- mxs = Resolv::DNS.open do |dns|
43
- ress = dns.getresources domain, Resolv::DNS::Resource::IN::MX
44
- ress.map { |r| [r.exchange.to_s, IPSocket::getaddress(r.exchange.to_s), r.preference] }
45
- end
46
- @domains[domain] = mxs
47
- end
48
-
49
- # Returns an array of MX IP address (String) for the given email domain
50
- def self.mx_ips(domain)
51
- mxers(domain).map {|m| m[1] }
52
- end
53
-
54
- # Given a cidr (ip/bits) and ip address, returns true on match. Caches cidr object.
55
- def self.in_cidr?(cidr, ip)
56
- @cidrs ||= {}
57
- @cidrs[cidr] ||= NetAddr::CIDR.create(cidr)
58
- @cidrs[cidr].matches?(ip)
59
- end
60
- end
@@ -1,44 +0,0 @@
1
- module EmailAddress
2
-
3
- # EmailAddress::Mailbox - Left side of the @
4
- #
5
- # * mailbox - Everything to the left of the @
6
- # * account - part of the mailbox typically sent to a user
7
- # * tags - Address tags appended to the account for tracking
8
- #
9
- class Mailbox
10
- attr_reader :mailbox, :account, :tags, :provider
11
-
12
- def initialize(mailbox, mail_provider=nil)
13
- @provider = mail_provider
14
- @mailbox = mailbox
15
- end
16
-
17
- def to_s
18
- @mailbox
19
- end
20
-
21
- def mailbox=(mailbox)
22
- @mailbox = mailbox.strip.downcase
23
- (@account, @tags) = @mailbox.split(@provider.tag_separator)
24
- @mailbox
25
- end
26
-
27
- def valid?
28
- return false unless provider.valid?(mailbox)
29
- true
30
- end
31
-
32
- def valid_format?
33
- return false unless provider.valid_format?(mailbox)
34
- #return false unless @mailbox =~ /\A\w[\w\.\-\+\']*\z/
35
- true
36
- end
37
-
38
- # Returns true if the email account is a standard reserved address
39
- def reserved?
40
- %Q(postmaster abuse).include?(account)
41
- end
42
-
43
- end
44
- end
@@ -1,55 +0,0 @@
1
- module EmailAddress
2
- module Providers
3
- class Default
4
- def initialize(address)
5
- @mailbox = mailbox
6
- end
7
-
8
- def account(mailbox)
9
- mailbox
10
- end
11
-
12
- def provider
13
- 'default'
14
- end
15
-
16
- def tag_separator
17
- '+'
18
- end
19
-
20
- def case_sensitive_mailbox
21
- false
22
- end
23
-
24
- def max_domain_length
25
- 253
26
- end
27
-
28
- def max_email_length
29
- 254
30
- end
31
-
32
- # Letters, numbers, period (no start) 6-30chars
33
- def max_mailbox_length
34
- 64
35
- end
36
-
37
- # Letters, numbers, period (no start) 6-30chars
38
- def user_pattern
39
- /\A[a-z0-9][\.\'a-z0-9]{5,29}\z/i
40
- end
41
-
42
- def valid?
43
- return false unless valid_format?
44
- end
45
-
46
- def valid_format?
47
- return false if mailbox.length > max_mailbox_length
48
- return false if address.length > max_email_length
49
- return false unless mailbox.to_s.match(user_pattern)
50
- true
51
- end
52
-
53
- end
54
- end
55
- end
@@ -1,27 +0,0 @@
1
- module EmailAddress
2
- module Providers
3
- class Google < Default
4
- def account
5
- account.gsub(/\./. '')
6
- end
7
-
8
- def provider
9
- 'google'
10
- end
11
-
12
- def tag_separator
13
- '+'
14
- end
15
-
16
- def case_sensitive_mailbox
17
- false
18
- end
19
-
20
- # Letters, numbers, period (no start) 6-30chars
21
- def user_pattern
22
- /\A[a-z0-9][\.a-z0-9]{5,29}\z/i
23
- end
24
-
25
- end
26
- end
27
- end
@@ -1,3 +0,0 @@
1
- module EmailAddress
2
- VERSION = "0.0.1"
3
- end
@@ -1,52 +0,0 @@
1
- # encoding: UTF-8
2
- require_relative 'test_helper'
3
-
4
- class TestEmailAddress < MiniTest::Unit::TestCase
5
- def test_address
6
- a = EmailAddress.new('user@example.com')
7
- assert_equal a.local, 'user'
8
- assert_equal a.tag, ''
9
- assert_equal a.comment, ''
10
- assert_equal a.domain, 'example.com'
11
- assert_equal a.subdomains, ''
12
- assert_equal a.base_domain, 'example'
13
- assert_equal a.dns_hostname, 'example.com'
14
- assert_equal a.top_level_domain, 'com'
15
- assert_equal a.to_s, 'user@example.com'
16
- end
17
-
18
- def test_foreign_address
19
- a = EmailAddress.new("user@sub.example.co.jp")
20
- assert_equal a.domain, "sub.example.co.jp"
21
- assert_equal a.subdomains, "sub"
22
- assert_equal a.domain_name, "example.co.jp"
23
- assert_equal a.base_domain, "example"
24
- assert_equal a.top_level_domain, "co.jp"
25
- end
26
-
27
- def test_address_tag
28
- a = EmailAddress.new('user+etc@example.com')
29
- assert_equal a.account, 'user'
30
- assert_equal a.tag, 'etc'
31
- assert_equal a.unique_address, 'user@example.com'
32
- end
33
-
34
- def test_address_comment
35
- a = EmailAddress.new('(comment)user@example.com')
36
- assert_equal a.comment, 'comment'
37
- assert_equal a.account, 'user'
38
- assert_equal a.unique_address, 'user@example.com'
39
- end
40
-
41
- def test_user_validation
42
- a = EmailAddress.new("user@example.co.jp")
43
- assert a.valid? == true
44
- end
45
-
46
- def test_unicode_domain
47
- a = EmailAddress.new("User@København.eu")
48
- assert_equal a.dns_hostname, 'xn--kbenhavn-54a.eu'
49
- assert_equal a.unique_address, 'user@xn--kbenhavn-54a.eu'
50
- end
51
-
52
- end
@@ -1,16 +0,0 @@
1
- #encoding: utf-8
2
- require_relative '../test_helper'
3
-
4
- class TestAddress < MiniTest::Unit::TestCase
5
- def test_address
6
- a = EmailAddress.new("User+tag@example.com")
7
- assert_equal "user", a.account
8
- assert_equal "user+tag", a.local
9
- assert_equal "user@example.com", a.unique_address
10
- end
11
-
12
- def test_unicode_user
13
- a = EmailAddress.new("å@example.com")
14
- assert_equal false, a.valid_format?
15
- end
16
- end
@@ -1,13 +0,0 @@
1
- #encoding: utf-8
2
- require_relative '../test_helper'
3
- #require 'minitest/autorun'
4
-
5
- class TestConfig < MiniTest::Unit::TestCase
6
- def test_config
7
- EmailAddress::Config.setup do
8
- add_provider :google, domain_names: %w(gmail.com googlemail.com google.com)
9
- end
10
- assert_equal EmailAddress::Config.get.provider_matching_rules.first[:provider], :google
11
- end
12
-
13
- end
@@ -1,29 +0,0 @@
1
- # encoding: UTF-8
2
- require_relative '../test_helper'
3
-
4
-
5
- class TestHost < MiniTest::Unit::TestCase
6
- def test_host
7
- a = EmailAddress::Host.new("example.com")
8
- assert_equal "example.com", a.host
9
- assert_equal "example.com", a.domain_name
10
- assert_equal "example", a.base_domain
11
- assert_equal ".com", a.tld
12
- assert_equal "", a.subdomains
13
- end
14
-
15
- def test_foreign_host
16
- a = EmailAddress::Host.new("yahoo.co.jp")
17
- assert_equal "yahoo.co.jp", a.host
18
- assert_equal "yahoo.co.jp", a.domain_name
19
- assert_equal "yahoo", a.base_domain
20
- assert_equal "co.jp", a.tld
21
- assert_equal "", a.subdomains
22
- end
23
-
24
- def test_unicode_host
25
- a = EmailAddress::Host.new("å.com")
26
- assert_equal "xn--5ca.com", a.dns_hostname
27
- end
28
-
29
- end