dnsaur 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f66e48837e8ecf6f1054428ec24ded5bb6dac963
4
+ data.tar.gz: 60c6ead262c3ec8520a55c178fb4113978a1482a
5
+ SHA512:
6
+ metadata.gz: aff9730e949bc99f3ce852f46a5b2183bb7cccc41def6e738da726734f3d9103fdcdf66e8c54a059d315cd3043bd5ef4ca60ade445710e87a13b590319aed295
7
+ data.tar.gz: 067d14eb95347c9eff2bae485b7cf3e8beddca05964cf614a493b2b613706067b51fd136aca82ca670082010885ea6367d0f44c3af03f5c6ad9ca632947be072
data/.coveralls.yml ADDED
@@ -0,0 +1 @@
1
+ repo_token: 8NC95fsJvtAh0zfZgqPvvDAjJqs4ZGXs9
data/.gitignore ADDED
@@ -0,0 +1,37 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /test/tmp/
9
+ /test/version_tmp/
10
+ /tmp/
11
+
12
+ ## Specific to RubyMotion:
13
+ .dat*
14
+ .repl_history
15
+ build/
16
+
17
+ ## Documentation cache and generated files:
18
+ /.yardoc/
19
+ /_yardoc/
20
+ /doc/
21
+ /rdoc/
22
+
23
+ ## Environment normalisation:
24
+ /.bundle/
25
+ /lib/bundler/man/
26
+
27
+ # for a library or gem, you might want to ignore these files since the code is
28
+ # intended to run in multiple environments; otherwise, check them in:
29
+ # Gemfile.lock
30
+ # .ruby-version
31
+ # .ruby-gemset
32
+
33
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
34
+ .rvmrc
35
+
36
+ # OSX Operating files
37
+ .DS_Store
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.1.3
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source 'https://rubygems.org'
2
+
3
+ group :development, :test do
4
+ gem "codeclimate-test-reporter", group: :test, require: nil
5
+ gem 'coveralls', require: false
6
+ gem 'guard-rspec', require: false
7
+ gem 'pry'
8
+ gem 'rake'
9
+ gem 'rspec', '~> 3.1.0'
10
+ gem 'terminal-notifier-guard'
11
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,85 @@
1
+ GEM
2
+ remote: https://rubygems.org/
3
+ specs:
4
+ celluloid (0.16.0)
5
+ timers (~> 4.0.0)
6
+ codeclimate-test-reporter (0.4.1)
7
+ simplecov (>= 0.7.1, < 1.0.0)
8
+ coderay (1.1.0)
9
+ coveralls (0.7.1)
10
+ multi_json (~> 1.3)
11
+ rest-client
12
+ simplecov (>= 0.7)
13
+ term-ansicolor
14
+ thor
15
+ diff-lcs (1.2.5)
16
+ docile (1.1.5)
17
+ ffi (1.9.6)
18
+ formatador (0.2.5)
19
+ guard (2.7.0)
20
+ formatador (>= 0.2.4)
21
+ listen (~> 2.7)
22
+ lumberjack (~> 1.0)
23
+ pry (>= 0.9.12)
24
+ thor (>= 0.18.1)
25
+ guard-rspec (4.3.1)
26
+ guard (~> 2.1)
27
+ rspec (>= 2.14, < 4.0)
28
+ hitimes (1.2.2)
29
+ listen (2.7.11)
30
+ celluloid (>= 0.15.2)
31
+ rb-fsevent (>= 0.9.3)
32
+ rb-inotify (>= 0.9)
33
+ lumberjack (1.0.9)
34
+ method_source (0.8.2)
35
+ mime-types (2.4.3)
36
+ multi_json (1.10.1)
37
+ netrc (0.8.0)
38
+ pry (0.10.1)
39
+ coderay (~> 1.1.0)
40
+ method_source (~> 0.8.1)
41
+ slop (~> 3.4)
42
+ rake (10.1.0)
43
+ rb-fsevent (0.9.4)
44
+ rb-inotify (0.9.5)
45
+ ffi (>= 0.5.0)
46
+ rest-client (1.7.2)
47
+ mime-types (>= 1.16, < 3.0)
48
+ netrc (~> 0.7)
49
+ rspec (3.1.0)
50
+ rspec-core (~> 3.1.0)
51
+ rspec-expectations (~> 3.1.0)
52
+ rspec-mocks (~> 3.1.0)
53
+ rspec-core (3.1.7)
54
+ rspec-support (~> 3.1.0)
55
+ rspec-expectations (3.1.2)
56
+ diff-lcs (>= 1.2.0, < 2.0)
57
+ rspec-support (~> 3.1.0)
58
+ rspec-mocks (3.1.3)
59
+ rspec-support (~> 3.1.0)
60
+ rspec-support (3.1.2)
61
+ simplecov (0.9.1)
62
+ docile (~> 1.1.0)
63
+ multi_json (~> 1.0)
64
+ simplecov-html (~> 0.8.0)
65
+ simplecov-html (0.8.0)
66
+ slop (3.6.0)
67
+ term-ansicolor (1.3.0)
68
+ tins (~> 1.0)
69
+ terminal-notifier-guard (1.6.1)
70
+ thor (0.19.1)
71
+ timers (4.0.1)
72
+ hitimes
73
+ tins (1.3.3)
74
+
75
+ PLATFORMS
76
+ ruby
77
+
78
+ DEPENDENCIES
79
+ codeclimate-test-reporter
80
+ coveralls
81
+ guard-rspec
82
+ pry
83
+ rake
84
+ rspec (~> 3.1.0)
85
+ terminal-notifier-guard
data/Guardfile ADDED
@@ -0,0 +1,7 @@
1
+ guard :rspec, cmd: "bundle exec rspec" do
2
+ watch(%r{^spec/.+_spec\.rb$})
3
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
4
+ watch('spec/spec_helper.rb') { "spec" }
5
+
6
+ notification :terminal_notifier
7
+ end
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Patrick Vice
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
data/README.md ADDED
@@ -0,0 +1,140 @@
1
+ #Dnsaur
2
+ [![Code Climate](https://codeclimate.com/github/patvice/dnsaur/badges/gpa.svg)](https://codeclimate.com/github/patvice/dnsaur) [![Coverage Status](https://coveralls.io/repos/patvice/dnsaur/badge.png?branch=master)](https://coveralls.io/r/patvice/dnsaur?branch=master) [![Circle CI](https://circleci.com/gh/patvice/dnsaur.png?style=badge)](https://circleci.com/gh/patvice/dnsaur)
3
+
4
+
5
+ Dnsaur is a simple DNS checker / email corrector for ruby. This gem does three things; when a user misspells a domain, it suggests the right spelling, it provide simple reverse DNS helper methods to help verifiy these emails, and splits emails into three parts(top level domain, domain, address).
6
+
7
+ The email suggestion part of the gem is based off a small javascript library called
8
+ [mailcheck.js](https://github.com/mailcheck/mailcheck). If you are looking for a more front end
9
+ solution for correcting email input, I suggest checking this out.
10
+
11
+ ## How the suggest works
12
+
13
+ When your user types in "user@hotnail.con", Dnsaur will suggest "user@hotmail.com". It can also
14
+ suggest top level domains, where a user types "user@hotmail.cmo" and would suggest ".com"
15
+
16
+ It does this by comparing a list of popular default domains and defualt top level domains suplied to
17
+ the gem.
18
+
19
+ ## Usage
20
+ Dnsaur can be used ether as an instance or as class methods. When creating an instance you need to
21
+ supply it with email,
22
+ ```ruby
23
+ email = "test@example.com"
24
+ dns = Dnsaur.new email
25
+ => #<Dnsaur:0x007fb8ea17d590 @original_email="test@example.com", ...
26
+ ```
27
+ custom domains and/or custom top level domains are optional.
28
+ For more information on custom domain, see the `Domains`section below.
29
+
30
+ ### Email Suggestion/Correction
31
+
32
+ In the suggest method, you can pass an email and it will return a suggested email in a hash
33
+ example:
34
+ ```ruby
35
+ # Class Methods
36
+ email = "test@hotnail.con"
37
+ Dnsaur.suggest email
38
+ =>
39
+ {
40
+ address: 'test', // the address; part before the @ sign
41
+ domain: 'hotmail.com', // the suggested domain
42
+ top_level_domain: 'com', // the suggested top level domain
43
+ full: 'test@hotmail.com' // the full suggested email
44
+ }
45
+ ```
46
+ If there is no match, or it is an exact match to a defualt domain, it will return false.
47
+
48
+ ### Reverse DNS lookup Helpers
49
+ The DNS lookup for this gem uses `Resolv` from the ruby stdlib, but I supplied class/instanced helper methods
50
+ for ease of use. If you have an instances of the class, it
51
+
52
+ ```ruby
53
+ #Class Methods
54
+ email = "test@example.com"
55
+ Dnsaur.valid_dns? email
56
+ => true || false
57
+
58
+ #Instant Methods
59
+ email = "test@hotnail.com"
60
+ dns = Dnsaur.new email
61
+ dns.valid_original_dns?
62
+ => true || false
63
+
64
+ dns.valid_suggested_email?
65
+ => true || false
66
+ ```
67
+
68
+ ### Spliting and Vaildating Emails
69
+
70
+ The split_email method is used to split the email into three parts
71
+ ```ruby
72
+ email = "test@exmaple.com"
73
+ Dnsaur.split_email email
74
+ {
75
+ top_level_domain: 'com', // the top level domain
76
+ domain: 'example.com', // the domain
77
+ address: 'test' // the address; part before the @ sign
78
+ }
79
+ ```
80
+
81
+ ## Domains
82
+ Just like [mailcheck.js](https://github.com/mailcheck/mailcheck), you can and should give Dnsaur
83
+ a custom list of domains/top level domains that your user will most likely use to sign up.
84
+
85
+ This can be done in two different way, ether by giving a completly new list and passing it
86
+ into and instance:
87
+ ```ruby
88
+ email = "test@example.com"
89
+ domains = ['customdomain.com', 'anotherdomain.net']
90
+ top_level_domains = ['com.au', 'ru']
91
+
92
+ Dnsaur.default_domains = domains
93
+ Dnsaur.default_top_level_domains = top_level_domains
94
+
95
+ Dnsaur.default_domains
96
+ => ["customdomain.com", "anotherdomain.net"]
97
+ Dnsaur.default_top_level_domains
98
+ => ["com.au", "ru"]
99
+ ```
100
+
101
+ Or if you want to just add values to the default domains provided,
102
+ you can pushing new values into the class constants:
103
+ ```ruby
104
+ Dnsaur.default_domains.push('customdomain.com', 'anotherdomain.net')
105
+ Dnsaur.default_top_level_domains.push('com.au', 'ru')
106
+ ```
107
+
108
+ `default_domains` and `default_top_level_domains` are class members, with one change, all other instances of your class will have your custom list of domains
109
+
110
+ ## Installation
111
+
112
+ Add this line to your application's Gemfile:
113
+
114
+ gem 'dnsaur'
115
+
116
+ And then execute:
117
+
118
+ $ bundle
119
+
120
+ Or install it yourself as:
121
+
122
+ $ gem install dnsaur
123
+
124
+ ## Still left Todo
125
+
126
+ There is still alot of polish that I would like to do to the code in this gem, and I would
127
+ also like to add some more functionality for validating emails:
128
+
129
+ - More test, and better test for all specs
130
+ - RFC822 regexp-based to be able to validate emails. [link](http://ex-parrot.com/~pdw/Mail-RFC822-Address.html)
131
+ - Using STMP VRFY command as well as RCTP TO: for better DNS validation
132
+ - Improve suggest methods readlity, and usablity
133
+
134
+ ## Contributing
135
+
136
+ 1. Fork it ( https://github.com/[my-github-username]/dnsaur/fork )
137
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
138
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
139
+ 4. Push to the branch (`git push origin my-new-feature`)
140
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ Dir.glob('tasks/**/*.rake').each(&method(:import))
data/dnsaur.gemspec ADDED
@@ -0,0 +1,22 @@
1
+ $:.push File.expand_path('../lib', __FILE__)
2
+ require 'dnsaur'
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = 'dnsaur'
6
+ s.version = Dnsaur::VERSION
7
+ s.date = '2014-10-25'
8
+ s.authors = ['Patrick Vice']
9
+ s.email = ['patrickgvice@gmail.com']
10
+ s.summary = 'A simple dns checker/ mistyped email suggester'
11
+ s.description = <<-EOF
12
+ Dnsaur is a simple DNS checker / email corrector for ruby. This gem does three
13
+ things; when a user misspells a domain, it suggests the right spelling, it
14
+ provide simple reverse DNS helper methods to help verifiy these emails, and
15
+ splits emails into three parts(top level domain, domain, address).
16
+ EOF
17
+ s.homepage = 'https://github.com/pavice/dnsaur'
18
+ s.license = 'MIT'
19
+
20
+ s.files = `git ls-files`.split("\n")
21
+ s.require_paths = ["lib"]
22
+ end
@@ -0,0 +1,61 @@
1
+ require "dnsaur/version"
2
+ require "dnsaur/sift_3_distance"
3
+ require "dnsaur/email_manipulation"
4
+
5
+ class Dnsaur
6
+ include EmailManipulation
7
+
8
+ ARG_ERROR = "An email can not be empty or invalid"
9
+ attr_reader :original_email
10
+
11
+ def initialize email
12
+ if Dnsaur.valid_email? email
13
+ @original_email = email
14
+ else
15
+ raise ArgumentError, ARG_ERROR
16
+ end
17
+ @suggested_email = suggest @original_email
18
+ end
19
+
20
+ def self.open(*args)
21
+ dnsaur = new(*args)
22
+ return dnsaur unless block_given?
23
+ begin
24
+ yield dnsaur
25
+ end
26
+ end
27
+
28
+ def original_email
29
+ @original_email
30
+ end
31
+
32
+ def original_email= email
33
+ raise ArgumentError, ARG_ERROR unless Dnsaur.valid_email? email
34
+ @original_email = email
35
+ @suggested_email = suggest email
36
+ end
37
+
38
+ def suggested_email
39
+ return false unless @suggested_email
40
+ @suggested_email[:full] if @suggested_email
41
+ end
42
+
43
+ def valid_original_dns?
44
+ Dnsaur.valid_dns? @original_email
45
+ end
46
+
47
+ def valid_suggested_dns?
48
+ return false unless @suggested_email
49
+ Dnsaur.valid_dns? @suggested_email[:full]
50
+ end
51
+
52
+ def self.valid_dns? email
53
+ email_parts = Dnsaur.split_email email
54
+ mx = Resolv::DNS.open.getresources(email_parts[:domain], Resolv::DNS::Resource::IN::MX)
55
+ mx.size > 0 ? true : false
56
+ end
57
+
58
+ def self.valid_email? email
59
+ !!(Dnsaur.split_email email)
60
+ end
61
+ end
@@ -0,0 +1,97 @@
1
+ require 'pry'
2
+
3
+ module EmailManipulation
4
+ include Sift3Distance
5
+
6
+ DOMAIN_THRESHOLD = 4
7
+ TOP_LEVEL_THRESHOLD = 3
8
+ DEFAULT_ERROR = "default domains list can't be nil or empty"
9
+ TOP_LEVEL_ERROR = "default top level domains can't be nil or empty"
10
+
11
+
12
+ @@default_domains = ["yahoo.com", "google.com", "hotmail.com", "gmail.com", "me.com", "aol.com", "mac.com",
13
+ "live.com", "comcast.net", "googlemail.com", "msn.com", "hotmail.co.uk", "yahoo.co.uk",
14
+ "facebook.com", "verizon.net", "sbcglobal.net", "att.net", "gmx.com", "mail.com",
15
+ "outlook.com", "icloud.com"]
16
+
17
+ @@default_top_level_domains = ["co.jp", "co.uk", "com", "net", "org", "info", "edu", "gov", "mil", "ca"]
18
+
19
+ def default_domains
20
+ @@default_domains
21
+ end
22
+
23
+ def default_domains= domains
24
+ raise ArgumentError, DEFAULT_ERROR if domains.nil? || domains.empty?
25
+ @@default_domains = domains
26
+ end
27
+
28
+ def default_top_level_domains
29
+ @@default_top_level_domains
30
+ end
31
+
32
+ def default_top_level_domains= top_level_domains
33
+ raise ArgumentError, TOP_LEVEL_ERROR if top_level_domains.nil? || top_level_domains.empty?
34
+ @@default_top_level_domains = top_level_domains
35
+ end
36
+
37
+ def suggest email
38
+ email_parts = self.split_email(email)
39
+ closest_domain = self.find_closest_domain(email_parts[:domain], @@default_domains, DOMAIN_THRESHOLD)
40
+
41
+ if closest_domain
42
+ if closest_domain != email_parts[:domain]
43
+ return { address: email_parts[:address], domain: closest_domain, full: email_parts[:address] + "@" + closest_domain }
44
+ end
45
+ else
46
+ closest_top_level_domain = self.find_closest_domain(email_parts[:top_level_domain], @@default_top_level_domains, TOP_LEVEL_THRESHOLD)
47
+
48
+ if closest_top_level_domain && closest_top_level_domain != email_parts[:top_level_domain]
49
+ closest_domain = email_parts[:domain].split('.', 2).first + '.' + closest_top_level_domain
50
+
51
+ return { address: email_parts[:address], domain: closest_domain, full: email_parts[:address] + "@" + closest_domain }
52
+ end
53
+ end
54
+
55
+ return false
56
+ end
57
+
58
+ def split_email email
59
+ parts = email.downcase.split('@')
60
+
61
+ return false if parts.length < 2 || parts.include?('')
62
+
63
+ address = parts.first
64
+ domain = parts.last
65
+ top_level_domain = domain.split('.', 2).last
66
+
67
+ return {top_level_domain: top_level_domain, domain: domain, address: address}
68
+ end
69
+
70
+ def find_closest_domain domain, domains, threshold
71
+ min_distance = 99
72
+ closest_domain = nil
73
+
74
+ return false if !domain || !domains
75
+
76
+ domains.each do |d|
77
+ if domain == d
78
+ return
79
+ end
80
+ dist = self.sift_3_distance(domain, d)
81
+ if (dist < min_distance)
82
+ min_distance = dist
83
+ closest_domain = d
84
+ end
85
+ end
86
+
87
+ if min_distance <= threshold && !closest_domain.nil?
88
+ return closest_domain
89
+ else
90
+ return false
91
+ end
92
+ end
93
+
94
+ def self.included(base)
95
+ base.extend(EmailManipulation)
96
+ end
97
+ end
@@ -0,0 +1,48 @@
1
+ module Sift3Distance
2
+
3
+ def sift_3_distance s1, s2
4
+ #My version of the the sift3 algorithm re-written in ruby
5
+ # sift3: http://siderite.blogspot.com/2007/04/super-fast-and-accurate-string-distance.html
6
+ if s1.nil? || s1.length == 0
7
+ if s2.nil? || s2.length == 0
8
+ return 0;
9
+ else
10
+ return s2.length
11
+ end
12
+ end
13
+
14
+ return s1.length if s2.nil? || s2.length == 0
15
+
16
+ c = 0
17
+ offset1 = 0
18
+ offset2 = 0
19
+ lcs = 0
20
+ max_offset = 5
21
+
22
+ begin
23
+ if s1[c + offset1] == s2[c + offset2]
24
+ lcs+= 1
25
+ else
26
+ offset1 = 0
27
+ offset2 = 0
28
+ max_offset.times do |i|
29
+ if (c+i < s1.length) && (s1[c+i] == s2[c])
30
+ offset1 = i
31
+ break
32
+ end
33
+ if (c+i < s2.length) && (s1[c] == s2[c+i])
34
+ offset2 = i
35
+ break
36
+ end
37
+ end
38
+ end
39
+ c+= 1
40
+ end while c+offset1 < s1.length && c+offset2 < s2.length
41
+
42
+ (s1.length + s2.length)/2 - lcs
43
+ end
44
+
45
+ def self.included(base)
46
+ base.extend(Sift3Distance)
47
+ end
48
+ end
@@ -0,0 +1,3 @@
1
+ class Dnsaur
2
+ VERSION = '0.1.0'
3
+ end
data/lib/dnsaur.rb ADDED
@@ -0,0 +1 @@
1
+ require "dnsaur/dnsaur"
@@ -0,0 +1,105 @@
1
+ require 'spec_helper'
2
+
3
+ describe Dnsaur do
4
+
5
+ describe "::initialize" do
6
+ it "when the email is invalid it raises an error" do
7
+ email = ""
8
+ expect{ Dnsaur.new email }.to raise_error(ArgumentError)
9
+ end
10
+ it "suggests an email when it being initialized" do
11
+ email = "test@hotnail.con"
12
+ dns = Dnsaur.new email
13
+ expect(dns.suggested_email).to be_truthy
14
+ end
15
+ end
16
+
17
+ context "class methods" do
18
+
19
+ describe "::valid_dns?" do
20
+ it "returns true when there reverse DNS lookup returns MX" do
21
+ email = "test@example.com"
22
+ Resolv::DNS.stub_chain(:open, :getresources).and_return ['true', 'true']
23
+ expect(Dnsaur.valid_dns? email).to be true
24
+ end
25
+ it "returns false when there is no MX for that domain" do
26
+ email = "test@example.com"
27
+ Resolv::DNS.stub_chain(:open, :getresources).and_return []
28
+ expect(Dnsaur.valid_dns? email).to be false
29
+ end
30
+ end
31
+
32
+ describe "::valid_email?" do
33
+ it "returns true when the email format is valid" do
34
+ email = "test@example.com"
35
+ expect(Dnsaur.valid_email? email).to be true
36
+ end
37
+ it "returns false when the email format is not valid" do
38
+ email = "test@"
39
+ expect(Dnsaur.valid_email? email).to be false
40
+ end
41
+ end
42
+ end
43
+
44
+ context 'instance methods' do
45
+ before do
46
+ @dnsaur = Dnsaur.new "test@hotnail.com"
47
+ end
48
+
49
+ describe "#original_email" do
50
+ it "returns an email given when a new instance is created" do
51
+ expect(@dnsaur.original_email).to eq("test@hotnail.com")
52
+ end
53
+ end
54
+
55
+ describe "#original_email=" do
56
+ it "sets a new email for that object" do
57
+ email = "test@example.com"
58
+ @dnsaur.original_email = email
59
+ expect(@dnsaur.original_email).to eq(email)
60
+ end
61
+ it "sets a new suggestion when an email is changed" do
62
+ email = "test@example.com"
63
+ @dnsaur.original_email = email
64
+ expect(@dnsaur.suggested_email).to be_falsey
65
+ end
66
+ it "raises an error when trying to change to an invalid email" do
67
+ email = "test@"
68
+ expect{@dnsaur.original_email= email}.to raise_error(ArgumentError)
69
+ end
70
+ end
71
+
72
+ describe "#suggested_email" do
73
+ it "returns a suggested email" do
74
+ expect(@dnsaur.suggested_email).to eq('test@hotmail.com')
75
+ end
76
+ it "it returns false if there is not suggest" do
77
+ email = "test@example.com"
78
+ @dnsaur.original_email = email
79
+ expect(@dnsaur.suggested_email).to be_falsey
80
+ end
81
+ end
82
+
83
+ describe "#valid_original_dns?" do
84
+ it "returns true when reverse DNS lookup returns MX" do
85
+ Resolv::DNS.stub_chain(:open, :getresources).and_return ['true', 'true']
86
+ expect(@dnsaur.valid_original_dns?).to be true
87
+ end
88
+ it "returns fail when there is no MX for that domain" do
89
+ Resolv::DNS.stub_chain(:open, :getresources).and_return []
90
+ expect(@dnsaur.valid_original_dns?).to be false
91
+ end
92
+ end
93
+
94
+ describe "#valid_suggested_dns?" do
95
+ it "returns true when there reverse DNS lookup returns MX" do
96
+ Resolv::DNS.stub_chain(:open, :getresources).and_return ['true', 'true']
97
+ expect(@dnsaur.valid_suggested_dns?).to be true
98
+ end
99
+ it "returns false when there is no MX for that domain" do
100
+ Resolv::DNS.stub_chain(:open, :getresources).and_return []
101
+ expect(@dnsaur.valid_suggested_dns?).to be false
102
+ end
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,123 @@
1
+ require 'spec_helper'
2
+
3
+ describe EmailManipulation do
4
+ let(:domains) {["yahoo.com", "google.com", "hotmail.com", "gmail.com", "me.com", "aol.com", "mac.com",
5
+ "live.com", "comcast.net", "googlemail.com", "msn.com", "hotmail.co.uk", "yahoo.co.uk",
6
+ "facebook.com", "verizon.net", "sbcglobal.net", "att.net", "gmx.com", "mail.com",
7
+ "outlook.com", "icloud.com"] }
8
+
9
+ let(:top_level_domains){ ["co.jp", "co.uk", "com", "net", "org", "info", "edu", "gov", "mil", "ca"] }
10
+
11
+ class DummyEmailManipulation
12
+ end
13
+
14
+ before(:each) do
15
+ @email_manipulation = DummyEmailManipulation.new
16
+ @email_manipulation.extend(EmailManipulation)
17
+ end
18
+ after(:each) do
19
+ @email_manipulation.default_domains = domains
20
+ @email_manipulation.default_top_level_domains = top_level_domains
21
+ end
22
+
23
+ describe "#default_domains" do
24
+ it "returns a list of domains" do
25
+ expect(@email_manipulation.default_domains).to be_truthy
26
+ end
27
+ end
28
+
29
+ describe "#default_domains=" do
30
+ it "assigns a new set of domains" do
31
+ domain_list = ['example.com', 'fake.org']
32
+ @email_manipulation.default_domains= domain_list
33
+ expect(@email_manipulation.default_domains).to eq(domain_list)
34
+ end
35
+ it "raise an error when passed an empty array" do
36
+ domain_list = []
37
+ expect{@email_manipulation.default_domains= domain_list}.to raise_error
38
+ end
39
+ it "raises an error when passed nil" do
40
+ domain_list = nil
41
+ expect{@email_manipulation.default_domains= domain_list}.to raise_error
42
+ end
43
+ end
44
+
45
+ describe "#default_top_level_domains" do
46
+ it "returns a list of top_level_domains" do
47
+ expect(@email_manipulation.default_top_level_domains).to be_truthy
48
+ end
49
+ end
50
+
51
+ describe "#default_top_level_domains=" do
52
+ it "assigns a new set of domains" do
53
+ tldomain_list = ['example.com', 'fake.org']
54
+ @email_manipulation.default_top_level_domains= tldomain_list
55
+ expect(@email_manipulation.default_top_level_domains).to eq(tldomain_list)
56
+ end
57
+ it "raise an error when passed an empty array" do
58
+ tldomain_list = []
59
+ expect{@email_manipulation.default_top_level_domains= tldomain_list}.to raise_error
60
+ end
61
+ it "raises an error when passed nil" do
62
+ tldomain_list = nil
63
+ expect{@email_manipulation.default_top_level_domains= tldomain_list}.to raise_error
64
+ end
65
+ end
66
+
67
+ describe "#suggest" do
68
+ it "returns a corrected top level domain" do
69
+ email = "test@example.con"
70
+ suggest_return = {address: "test", domain: "example.com", full: "test@example.com"}
71
+ expect(@email_manipulation.suggest email).to eq(suggest_return)
72
+ end
73
+ it "returns a corrected domain" do
74
+ email = "test@hotnail.con"
75
+ suggest_return = {address: "test", domain: "hotmail.com", full: "test@hotmail.com"}
76
+ expect(@email_manipulation.suggest email).to eq(suggest_return)
77
+ end
78
+ it "returns false when a email doesn't match default domains" do
79
+ email = "test@example.com"
80
+ expect(@email_manipulation.suggest email).to be false
81
+ end
82
+ end
83
+
84
+ describe "#split_email" do
85
+ it "splits an email into three parts" do
86
+ email = 'test@example.com'
87
+ split_return = {top_level_domain: 'com',domain: 'example.com', address: 'test'}
88
+ expect(@email_manipulation.split_email email).to eq(split_return)
89
+ end
90
+ it "returns the same top level domain/domain when givin an domain without a top level domain" do
91
+ #this is actually a valid email, according
92
+ email = 'test@example'
93
+ split_return = {:top_level_domain=>"example", :domain=>"example", :address=>"test"}
94
+ expect(@email_manipulation.split_email email).to eq(split_return)
95
+ end
96
+ it "returns false if the email doesn't have a domain" do
97
+ email = 'test@'
98
+ expect(@email_manipulation.split_email email).to be false
99
+ end
100
+ it "returns false if there is no @ symbol in the string" do
101
+ email = 'test'
102
+ expect(@email_manipulation.split_email email).to be false
103
+ end
104
+ end
105
+
106
+ describe "#find_closest_domain" do
107
+ it "returns false when passed nil attributes" do
108
+ expect(@email_manipulation.find_closest_domain nil, nil, 4).to be false
109
+ end
110
+ it "returns false when there is no match" do
111
+ domain = "example.com"
112
+ expect(@email_manipulation.find_closest_domain domain, domains, 4).to be false
113
+ end
114
+ it "returns nil when there is an exact match" do
115
+ domain = "hotmail.com"
116
+ expect(@email_manipulation.find_closest_domain domain, domains, 4).to be nil
117
+ end
118
+ it "passes a suggestion when there is a differece less then the threshold" do
119
+ domain = "hotmail.c"
120
+ expect(@email_manipulation.find_closest_domain domain, domains, 4).to eq('hotmail.com')
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ describe Sift3Distance do
4
+ class DummySift3Distance
5
+ end
6
+
7
+ before(:each) do
8
+ @sift_3_distance = DummySift3Distance.new
9
+ @sift_3_distance.extend(Sift3Distance)
10
+ end
11
+
12
+ describe "#sift_3_distance" do
13
+ it "returns the different of two strings" do
14
+ s1 = "example"
15
+ s2 = "eample"
16
+ expect(@sift_3_distance.sift_3_distance s1, s2).to eq 1
17
+ end
18
+ it "returns zero when both arguments is nil or empty" do
19
+ s1 = nil
20
+ s2 = ""
21
+ expect(@sift_3_distance.sift_3_distance s1, s2).to eq 0
22
+ end
23
+ it "returns the length of the first string if the second sring is nil or empty" do
24
+ s1 = "example"
25
+ s2 = nil
26
+ expect(@sift_3_distance.sift_3_distance s1, s2).to eq s1.length
27
+ end
28
+ it "returns the length of the second string if the first string is nil or empty" do
29
+ s1 = nil
30
+ s2 = "example"
31
+ expect(@sift_3_distance.sift_3_distance s1, s2).to eq s2.length
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,22 @@
1
+ require "codeclimate-test-reporter"
2
+ CodeClimate::TestReporter.start
3
+
4
+ require 'coveralls'
5
+ Coveralls.wear!
6
+
7
+ require 'bundler/setup'
8
+ Bundler.setup
9
+
10
+ require 'dnsaur'
11
+
12
+ Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each {|f| require f}
13
+
14
+ RSpec.configure do |config|
15
+ config.expect_with :rspec do |expectations|
16
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
17
+ end
18
+
19
+ config.mock_with :rspec do |mocks|
20
+ mocks.verify_partial_doubles = true
21
+ end
22
+ end
data/tasks/debug.rake ADDED
@@ -0,0 +1,4 @@
1
+ desc 'Open an irb session preloaded with this library'
2
+ task :console do
3
+ sh 'irb -rubygems -I lib -r dnsaur.rb'
4
+ end
data/tasks/rspec.rake ADDED
@@ -0,0 +1,4 @@
1
+ require 'rspec/core/rake_task'
2
+
3
+ RSpec::Core::RakeTask.new(:spec)
4
+ task :default => :spec
metadata ADDED
@@ -0,0 +1,70 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dnsaur
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Patrick Vice
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-10-25 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: |2
14
+ Dnsaur is a simple DNS checker / email corrector for ruby. This gem does three
15
+ things; when a user misspells a domain, it suggests the right spelling, it
16
+ provide simple reverse DNS helper methods to help verifiy these emails, and
17
+ splits emails into three parts(top level domain, domain, address).
18
+ email:
19
+ - patrickgvice@gmail.com
20
+ executables: []
21
+ extensions: []
22
+ extra_rdoc_files: []
23
+ files:
24
+ - ".coveralls.yml"
25
+ - ".gitignore"
26
+ - ".rspec"
27
+ - ".ruby-version"
28
+ - Gemfile
29
+ - Gemfile.lock
30
+ - Guardfile
31
+ - LICENSE
32
+ - README.md
33
+ - Rakefile
34
+ - dnsaur.gemspec
35
+ - lib/dnsaur.rb
36
+ - lib/dnsaur/dnsaur.rb
37
+ - lib/dnsaur/email_manipulation.rb
38
+ - lib/dnsaur/sift_3_distance.rb
39
+ - lib/dnsaur/version.rb
40
+ - spec/lib/dnsaur/dnsaur_spec.rb
41
+ - spec/lib/dnsaur/email_manipulation_spec.rb
42
+ - spec/lib/dnsaur/sift_3_distance_spec.rb
43
+ - spec/spec_helper.rb
44
+ - tasks/debug.rake
45
+ - tasks/rspec.rake
46
+ homepage: https://github.com/pavice/dnsaur
47
+ licenses:
48
+ - MIT
49
+ metadata: {}
50
+ post_install_message:
51
+ rdoc_options: []
52
+ require_paths:
53
+ - lib
54
+ required_ruby_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: '0'
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ requirements: []
65
+ rubyforge_project:
66
+ rubygems_version: 2.2.2
67
+ signing_key:
68
+ specification_version: 4
69
+ summary: A simple dns checker/ mistyped email suggester
70
+ test_files: []