gman 0.0.7 → 0.1.0

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