mailcheck 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in mailcheck.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Scott Becker
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,48 @@
1
+ # Mailcheck
2
+
3
+ A ruby translation of the [Kicksend mailcheck](https://github.com/Kicksend/mailcheck) javascript library which suggests a right domain when your users misspell it in an email address.
4
+
5
+ When your user types in "user@hotnail.con", Mailcheck will suggest "user@hotmail.com".
6
+
7
+ Mailcheck will offer up suggestions for top level domains too, and suggest ".com" when a user types in "user@hotmail.cmo".
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ gem 'mailcheck'
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install mailcheck
22
+
23
+ ## Usage
24
+
25
+ ```ruby
26
+ > require 'mailcheck'
27
+
28
+ > mailcheck = Mailcheck.new
29
+ > mailcheck.suggest("user@hotma.com")
30
+ # => {
31
+ # :address =>"user",
32
+ # :domain =>"hotmail.com",
33
+ # :full =>"user@hotmail.com"
34
+ # }
35
+ ```
36
+
37
+ ## Contributing
38
+
39
+ 1. Fork it
40
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
41
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
42
+ 4. Push to the branch (`git push origin my-new-feature`)
43
+ 5. Create new Pull Request
44
+
45
+ ## Credits
46
+
47
+ * [Mailcheck.js](https://github.com/Kicksend/mailcheck): the original idea
48
+ * [This gist](https://gist.github.com/mmmaia/3715790), by [mmmaia](https://github.com/mmmaia) - an initial port to Ruby
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new('spec')
6
+
7
+ task :default => :spec
data/lib/mailcheck.rb ADDED
@@ -0,0 +1,136 @@
1
+ require "mailcheck/version"
2
+
3
+ class Mailcheck
4
+
5
+ THRESHOLD = 3
6
+
7
+ DOMAINS = ['yahoo.com', 'google.com', 'hotmail.com', 'gmail.com', 'me.com', 'aol.com', 'mac.com', 'live.com', 'comcast.net', 'googlemail.com', 'msn.com', 'hotmail.co.uk', 'yahoo.co.uk', 'facebook.com', 'verizon.net', 'sbcglobal.net', 'att.net', 'gmx.com', 'mail.com']
8
+
9
+ TOP_LEVEL_DOMAINS = ['co.uk', 'com', 'net', 'org', 'info', 'edu', 'gov', 'mil']
10
+
11
+ def initialize(opts={})
12
+ @domains = opts[:domains] || DOMAINS
13
+ @top_level_domains = opts[:top_level_domains] || TOP_LEVEL_DOMAINS
14
+ end
15
+
16
+ def suggest(email)
17
+ email_parts = split_email(email.downcase)
18
+
19
+ return false if email_parts == false
20
+
21
+ closest_domain = find_closest_domain(email_parts[:domain], @domains)
22
+
23
+ if closest_domain
24
+ if closest_domain != email_parts[:domain]
25
+ # The email address closely matches one of the supplied domains return a suggestion
26
+ return { :address => email_parts[:address], :domain => closest_domain, :full => "#{email_parts[:address]}@#{closest_domain}" }
27
+ end
28
+ else
29
+ # The email address does not closely match one of the supplied domains
30
+ closest_top_level_domain = find_closest_domain(email_parts[:top_level_domain], @top_level_domains)
31
+ if email_parts[:domain] && closest_top_level_domain && closest_top_level_domain != email_parts[:top_level_domain]
32
+ # The email address may have a mispelled top-level domain return a suggestion
33
+ domain = email_parts[:domain]
34
+ closest_domain = domain[0, domain.rindex(email_parts[:top_level_domain])] + closest_top_level_domain
35
+ return { :address => email_parts[:address], :domain => closest_domain, :full => "#{email_parts[:address]}@#{closest_domain}" }
36
+ end
37
+ end
38
+ # The email address exactly matches one of the supplied domains, does not closely
39
+ # match any domain and does not appear to simply have a mispelled top-level domain,
40
+ # or is an invalid email address do not return a suggestion.
41
+ false
42
+ end
43
+
44
+ def find_closest_domain(domain, domains)
45
+ min_dist = 99
46
+
47
+ for i in 0...domains.length do
48
+ if domain === domains[i]
49
+ return domain
50
+ end
51
+ dist = sift_3distance(domain, domains[i])
52
+ if dist < min_dist
53
+ min_dist = dist
54
+ closest_domain = domains[i]
55
+ end
56
+ end
57
+
58
+ if min_dist <= THRESHOLD && closest_domain
59
+ closest_domain
60
+ else
61
+ false
62
+ end
63
+ end
64
+
65
+ def sift_3distance(s1, s2)
66
+ # sift3: http:#siderite.blogspot.com/2007/04/super-fast-and-accurate-string-distance.html
67
+
68
+ c = 0
69
+ offset1 = 0
70
+ offset2 = 0
71
+ lcs = 0
72
+ max_offset = 5
73
+
74
+ while (c + offset1 < s1.length) && (c + offset2 < s2.length) do
75
+ if s1[c + offset1] == s2[c + offset2]
76
+ lcs += 1
77
+ else
78
+ offset1 = 0
79
+ offset2 = 0
80
+ for i in 0...max_offset do
81
+ if c + i < s1.length && s1[c + i] == s2[c]
82
+ offset1 = i
83
+ break
84
+ end
85
+ if c + i < s2.length && s1[c] == s2[c + i]
86
+ offset2 = i
87
+ break
88
+ end
89
+ end
90
+ end
91
+ c += 1
92
+ end
93
+ return (s1.length + s2.length) / 2 - lcs
94
+ end
95
+
96
+ def split_email(email)
97
+
98
+ parts = email.split('@')
99
+
100
+ if parts.length < 2
101
+ return false
102
+ end
103
+
104
+ for i in 0...parts.length do
105
+ if parts[i] === ''
106
+ return false
107
+ end
108
+ end
109
+
110
+ domain = parts.pop
111
+ domain_parts = domain.split('.')
112
+ tld = ''
113
+
114
+ if domain_parts.length == 0
115
+ # The address does not have a top-level domain
116
+ return false
117
+ elsif domain_parts.length == 1
118
+ # The address has only a top-level domain (valid under RFC)
119
+ tld = domain_parts[0]
120
+ else
121
+ # The address has a domain and a top-level domain
122
+ for i in 1...domain_parts.length do
123
+ tld << "#{domain_parts[i]}."
124
+ end
125
+ if domain_parts.length >= 2
126
+ tld = tld[0, tld.length - 1]
127
+ end
128
+ end
129
+
130
+ {
131
+ :top_level_domain => tld,
132
+ :domain => domain,
133
+ :address => parts.join('@')
134
+ }
135
+ end
136
+ end
@@ -0,0 +1,3 @@
1
+ class Mailcheck
2
+ VERSION = "0.0.1"
3
+ end
data/mailcheck.gemspec ADDED
@@ -0,0 +1,18 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/mailcheck/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Scott Becker"]
6
+ gem.email = ["becker.scott@gmail.com"]
7
+ gem.description = %q{A ruby translation of the Kicksend mailcheck javascript library (https://github.com/Kicksend/mailcheck) which suggests a right domain when your users misspell it in an email address.}
8
+ gem.summary = %q{When your user types in "user@hotnail.con", Mailcheck will suggest "user@hotmail.com". Mailcheck will offer up suggestions for top level domains too, and suggest ".com" when a user types in "user@hotmail.cmo".}
9
+ gem.homepage = ""
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "mailcheck"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Mailcheck::VERSION
17
+ gem.add_development_dependency 'rspec', '~> 2.12'
18
+ end
@@ -0,0 +1,57 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mailcheck do
4
+
5
+ before do
6
+ @domains = ['yahoo.com', 'yahoo.com.tw', 'google.com','hotmail.com', 'gmail.com', 'emaildomain.com', 'comcast.net', 'facebook.com', 'msn.com', 'gmx.com']
7
+ @top_level_domains = ['co.uk', 'com', 'org', 'info']
8
+ @mailcheck = Mailcheck.new
9
+ end
10
+
11
+ describe "#suggest" do
12
+ it "returns a hash of the address, domain, and full email address when there's a suggestion" do
13
+ suggestion = @mailcheck.suggest("user@hotma.com")
14
+
15
+ suggestion[:address].should == 'user'
16
+ suggestion[:domain].should == 'hotmail.com'
17
+ suggestion[:full].should == 'user@hotmail.com'
18
+ end
19
+
20
+ it "is false when there's no suggestion" do
21
+ @mailcheck.suggest("user@hotmail.com").should be_false
22
+ end
23
+
24
+ it "is false when an imcomplete email is provided" do
25
+ @mailcheck.suggest("contact").should be_false
26
+ end
27
+ end
28
+
29
+ describe "cases" do
30
+ it "passes" do
31
+ mailcheck = Mailcheck.new :domains => @domains, :top_level_domains => @top_level_domains
32
+
33
+ mailcheck.suggest('test@emaildomain.co')[:domain].should == 'emaildomain.com'
34
+ mailcheck.suggest('test@gmail.con')[:domain].should == 'gmail.com'
35
+ mailcheck.suggest('test@gnail.con')[:domain].should == 'gmail.com'
36
+ mailcheck.suggest('test@GNAIL.con')[:domain].should == 'gmail.com'
37
+ mailcheck.suggest('test@#gmail.com')[:domain].should == 'gmail.com'
38
+ mailcheck.suggest('test@comcast.com')[:domain].should == 'comcast.net'
39
+ mailcheck.suggest('test@homail.con')[:domain].should == 'hotmail.com'
40
+ mailcheck.suggest('test@hotmail.co')[:domain].should == 'hotmail.com'
41
+ mailcheck.suggest('test@fabecook.com')[:domain].should == 'facebook.com'
42
+ mailcheck.suggest('test@yajoo.com')[:domain].should == 'yahoo.com'
43
+ mailcheck.suggest('test@randomsmallcompany.cmo')[:domain].should == 'randomsmallcompany.com'
44
+ mailcheck.suggest('test@yahoo.com.tw').should be_false
45
+ mailcheck.suggest('').should be_false
46
+ mailcheck.suggest('test@').should be_false
47
+ mailcheck.suggest('test').should be_false
48
+
49
+ # This test is for illustrative purposes as the splitEmail function should return a better
50
+ # representation of the true top-level domain in the case of an email address with subdomains.
51
+ # mailcheck will be unable to return a suggestion in the case of this email address.
52
+ #
53
+ mailcheck.suggest('test@mail.randomsmallcompany.cmo').should be_false
54
+ end
55
+ end
56
+
57
+ end
@@ -0,0 +1,7 @@
1
+ require 'rspec'
2
+ require 'mailcheck'
3
+
4
+ RSpec.configure do |config|
5
+ config.color_enabled = true
6
+ config.formatter = 'documentation'
7
+ end
metadata ADDED
@@ -0,0 +1,76 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mailcheck
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Scott Becker
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-02-19 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '2.12'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '2.12'
30
+ description: A ruby translation of the Kicksend mailcheck javascript library (https://github.com/Kicksend/mailcheck)
31
+ which suggests a right domain when your users misspell it in an email address.
32
+ email:
33
+ - becker.scott@gmail.com
34
+ executables: []
35
+ extensions: []
36
+ extra_rdoc_files: []
37
+ files:
38
+ - .gitignore
39
+ - Gemfile
40
+ - LICENSE
41
+ - README.md
42
+ - Rakefile
43
+ - lib/mailcheck.rb
44
+ - lib/mailcheck/version.rb
45
+ - mailcheck.gemspec
46
+ - spec/mailcheck_spec.rb
47
+ - spec/spec_helper.rb
48
+ homepage: ''
49
+ licenses: []
50
+ post_install_message:
51
+ rdoc_options: []
52
+ require_paths:
53
+ - lib
54
+ required_ruby_version: !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ! '>='
58
+ - !ruby/object:Gem::Version
59
+ version: '0'
60
+ required_rubygems_version: !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ requirements: []
67
+ rubyforge_project:
68
+ rubygems_version: 1.8.25
69
+ signing_key:
70
+ specification_version: 3
71
+ summary: When your user types in "user@hotnail.con", Mailcheck will suggest "user@hotmail.com".
72
+ Mailcheck will offer up suggestions for top level domains too, and suggest ".com"
73
+ when a user types in "user@hotmail.cmo".
74
+ test_files:
75
+ - spec/mailcheck_spec.rb
76
+ - spec/spec_helper.rb