gman 0.0.7 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. data/README.md +20 -0
  2. data/gman.gemspec +3 -1
  3. data/lib/gman.rb +35 -13
  4. data/test/test_gman.rb +52 -4
  5. metadata +34 -2
data/README.md CHANGED
@@ -28,6 +28,15 @@ Or add this to your `Gemfile` before doing a `bundle install`:
28
28
  Gman.valid? "foo@bar.gov" #true
29
29
  Gman.valid? "foo@bar.com" #false
30
30
  ```
31
+
32
+ ### Really verify an email address
33
+
34
+ (also verifies that the server returns a valid MX record)
35
+
36
+ ```ruby
37
+ Gman.valid? "foo@whitehouse.gov", true #true
38
+ Gman.valid? "foo@bar.gov", true #false
39
+ ```
31
40
  ### Verify domain
32
41
 
33
42
  ```ruby
@@ -37,6 +46,17 @@ Gman.valid? "foo.gov" #true
37
46
  Gman.valid? "foo.biz" #false
38
47
  ```
39
48
 
49
+ ### Get a domain name from an arbitrary domainy string
50
+
51
+ ```ruby
52
+ Gman.get_domain "http://foo.bar.gov" # foo.bar.gov
53
+ Gman.get_domain "foo@bar.gov" # bar.gov
54
+ Gman.get_domain "foo.bar.gov" # foo.bar.gov
55
+ Gman.get_domain "asdf@asdf" # nil (no domain within the string)
56
+ Gman.get_domain "foo@bar.gov", true #false (no MX record)
57
+ Gman.get_domain "foo@whitehouse.gov", true # true (valid MX record)
58
+ ```
59
+
40
60
  ## Contributing
41
61
 
42
62
  Contributions welcome! Please see [the contribution guidelines](CONTRIBUTING.md) for code contributions or for details on how to add, update, or delete government domains.
data/gman.gemspec CHANGED
@@ -2,7 +2,7 @@ Gem::Specification.new do |s|
2
2
  s.name = "gman"
3
3
  s.summary = "Check if a given domain or email address belong to a governemnt entity"
4
4
  s.description = "A ruby gem to check if the owner of a given email address is working for THE MAN."
5
- s.version = "0.0.7"
5
+ s.version = "0.1.0"
6
6
  s.authors = ["Ben Balter"]
7
7
  s.email = "ben.balter@github.com"
8
8
  s.homepage = "https://github.com/benbalter/gman"
@@ -26,6 +26,8 @@ Gem::Specification.new do |s|
26
26
  s.require_paths = ["lib"]
27
27
  s.add_dependency( "public_suffix" )
28
28
  s.add_dependency( "swot" )
29
+ s.add_dependency( "email_veracity" )
30
+ s.add_dependency( "addressable" )
29
31
 
30
32
  s.add_development_dependency( "rake" )
31
33
  s.add_development_dependency( "shoulda" )
data/lib/gman.rb CHANGED
@@ -1,6 +1,8 @@
1
1
  require 'public_suffix'
2
2
  require 'yaml'
3
3
  require 'swot'
4
+ require "addressable/uri"
5
+ require "email_veracity"
4
6
 
5
7
  module Gman
6
8
 
@@ -14,10 +16,19 @@ module Gman
14
16
  # "foo.gov.uk"
15
17
  # "http://foo.bar.gov"
16
18
  #
19
+ # check_mx - if an email is passed, check the domain for an mx record
20
+ #
17
21
  # Returns boolean true if a government domain
18
- def valid?(text)
19
- return false if text.nil?
22
+ def valid?(text, check_mx=false)
23
+
20
24
  domain = get_domain text
25
+ return false unless PublicSuffix.valid?(domain)
26
+
27
+ # validate mx record
28
+ if check_mx && email?(text)
29
+ EmailVeracity::Config[:skip_lookup] = false
30
+ return false unless EmailVeracity::Address.new(text).valid?
31
+ end
21
32
 
22
33
  # Ensure non-edu
23
34
  return false if Swot::is_academic?(domain)
@@ -27,8 +38,6 @@ module Gman
27
38
  return true if !rule.nil? && rule.allow?(domain)
28
39
 
29
40
  # also allow for explicit matches to domain list
30
- # but still make sure it's at least a valid domain
31
- return false unless PublicSuffix.valid? domain
32
41
  list.rules.any? { |rule| rule.value == domain }
33
42
  end
34
43
 
@@ -41,18 +50,31 @@ module Gman
41
50
  # Get the FQDN name from a URL or email address.
42
51
  #
43
52
  # Returns a string with the FQDN; nil if there's an error.
44
- # Source: https://github.com/leereilly/swot/blob/master/lib/swot.rb#L190
45
53
  def get_domain(text)
46
- text.strip.downcase.match(domain_regex).captures.first
47
- rescue
48
- return nil
49
- end
50
54
 
51
- private
55
+ return nil if text.to_s.empty?
52
56
 
53
- # Source: https://github.com/leereilly/swot/blob/master/lib/swot.rb#L202
54
- def domain_regex
55
- /([^@\/:]+)[:\d]*$/
57
+ text = text.downcase
58
+ uri = Addressable::URI.parse(text)
59
+
60
+ if uri.host # valid https?://* URI
61
+ uri.host
62
+ elsif email?(text)
63
+ EmailVeracity::Address.new(text).domain.to_s
64
+ else # url sans http://
65
+ uri = Addressable::URI.parse("http://#{text}")
66
+ # properly parse http://foo edge cases
67
+ # see https://github.com/sporkmonger/addressable/issues/145
68
+ uri.host if uri.host =~ /\./
69
+ end
70
+ end
71
+
72
+ # Is the given string in the form of a valid email address?
73
+ #
74
+ # Returns true if email, otherwise false
75
+ def email?(text)
76
+ EmailVeracity::Config[:skip_lookup] = true
77
+ EmailVeracity::Address.new(text).valid?
56
78
  end
57
79
  end
58
80
  end
data/test/test_gman.rb CHANGED
@@ -1,14 +1,15 @@
1
1
  require 'helper'
2
- require 'swot'
3
2
 
4
3
  VALID = [ "foo.gov",
5
4
  "http://foo.mil",
6
5
  "foo@bar.gc.ca",
7
6
  "foo.gov.au",
8
- "http://www.foo.gouv.fr",
7
+ "https://www.foo.gouv.fr",
9
8
  "foo@ci.champaign.il.us",
10
9
  "foo.bar.baz.gov.au",
11
- "foo@bar.gov.uk"
10
+ "foo@bar.gov.uk",
11
+ ".gov",
12
+ "foo.fed.us",
12
13
  ]
13
14
 
14
15
  INVALID = [ "foo.bar.com",
@@ -17,7 +18,10 @@ INVALID = [ "foo.bar.com",
17
18
  "foo.uk",
18
19
  "gov",
19
20
  "foo@k12.champaign.il.us",
20
- "foo@kii.gov.by"
21
+ "foo@kii.gov.by",
22
+ "foo",
23
+ "",
24
+ nil,
21
25
  ]
22
26
 
23
27
  class TestGman < Test::Unit::TestCase
@@ -39,4 +43,48 @@ class TestGman < Test::Unit::TestCase
39
43
  assert_equal false, Swot::is_academic?(entry.name), "#{entry.name} is an academic domain"
40
44
  end
41
45
  end
46
+
47
+ should "not contain any invalid domains" do
48
+ Gman.list.each do |entry|
49
+ assert_equal true, PublicSuffix.valid?("foo.#{entry.name}"), "#{entry.name} is not a valid domain"
50
+ end
51
+ end
52
+
53
+ should "not allow educational domains" do
54
+ assert_equal false, Gman::valid?("foo@gwu.edu")
55
+ end
56
+
57
+ should "properly parse domains from strings" do
58
+ assert_equal "github.gov", Gman::get_domain("foo@github.gov")
59
+ assert_equal "foo.github.gov", Gman::get_domain("foo.github.gov")
60
+ assert_equal "github.gov", Gman::get_domain("http://github.gov")
61
+ assert_equal "github.gov", Gman::get_domain("https://github.gov")
62
+ assert_equal ".gov", Gman::get_domain(".gov")
63
+ assert_equal nil, Gman.get_domain("foo")
64
+ end
65
+
66
+ should "validate mx records when asked" do
67
+ assert_equal true, Gman.valid?("foo@nasa.gov", true)
68
+ assert_equal false, Gman.valid?("foo@github.gov", true)
69
+ assert_equal true, Gman.valid?("foo@github.gov", false)
70
+ end
71
+
72
+ should "pass any url on the list" do
73
+ Gman.list.each do |entry|
74
+ assert_equal true, Gman.valid?("http://foo.#{entry.name}/bar"), "http://foo.#{entry.name}/bar is not a valid"
75
+ end
76
+ end
77
+
78
+ should "pass any email on the list" do
79
+ Gman.list.each do |entry|
80
+ assert_equal true, Gman.valid?("foo@bar.#{entry.name}"), "foo@bar.#{entry.name} is not a valid"
81
+ end
82
+ end
83
+
84
+ should "pass any domain on the list" do
85
+ Gman.list.each do |entry|
86
+ assert_equal true, Gman.valid?("foo.#{entry.name}"), "foo.#{entry.name} is not a valid domain"
87
+ end
88
+ end
89
+
42
90
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gman
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-11-25 00:00:00.000000000 Z
12
+ date: 2013-11-27 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: public_suffix
@@ -43,6 +43,38 @@ dependencies:
43
43
  - - ! '>='
44
44
  - !ruby/object:Gem::Version
45
45
  version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: email_veracity
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: addressable
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
46
78
  - !ruby/object:Gem::Dependency
47
79
  name: rake
48
80
  requirement: !ruby/object:Gem::Requirement