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.
- checksums.yaml +4 -4
- data/Gemfile +1 -0
- data/README.md +99 -32
- data/email_address.gemspec +2 -1
- data/lib/email_address.rb +14 -142
- data/lib/email_address/address.rb +70 -0
- data/lib/email_address/config.rb +75 -0
- data/lib/email_address/domain_matcher.rb +90 -0
- data/lib/email_address/domain_parser.rb +71 -0
- data/lib/email_address/exchanger.rb +67 -0
- data/lib/email_address/host.rb +71 -1
- data/lib/email_address/local.rb +97 -0
- data/lib/email_address/validator.rb +135 -0
- data/lib/email_address/version.rb +1 -1
- data/test/email_address/test_address.rb +30 -0
- data/test/email_address/test_config.rb +13 -0
- data/test/email_address/test_domain_matcher.rb +15 -0
- data/test/email_address/test_domain_parser.rb +29 -0
- data/test/email_address/test_exchanger.rb +19 -0
- data/test/email_address/test_host.rb +43 -0
- data/test/email_address/test_local.rb +27 -0
- data/test/email_address/test_validator.rb +16 -0
- data/test/test_email_address.rb +12 -0
- metadata +40 -27
- data/lib/email_address/esp.rb +0 -4
- data/lib/email_address/providers/default.rb +0 -8
- data/lib/email_address/providers/google.rb +0 -8
- data/lib/email_providers/address.rb +0 -102
- data/lib/email_providers/config.rb +0 -36
- data/lib/email_providers/factory.rb +0 -17
- data/lib/email_providers/host.rb +0 -87
- data/lib/email_providers/mail_exchanger.rb +0 -60
- data/lib/email_providers/mailbox.rb +0 -44
- data/lib/email_providers/providers/default.rb +0 -55
- data/lib/email_providers/providers/google.rb +0 -27
- data/lib/email_providers/version.rb +0 -3
- data/test/email_address.rb +0 -52
- data/test/email_address/address.rb +0 -16
- data/test/email_address/config.rb +0 -13
- data/test/email_address/host.rb +0 -29
- 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
|
data/lib/email_providers/host.rb
DELETED
@@ -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
|
data/test/email_address.rb
DELETED
@@ -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
|
data/test/email_address/host.rb
DELETED
@@ -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
|