Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/FGRibreau/mailchecker int…
Browse files Browse the repository at this point in the history
…o rubygems-travis
  • Loading branch information
buren committed Oct 1, 2015
2 parents 27561f6 + 93aa607 commit 665c136
Show file tree
Hide file tree
Showing 10 changed files with 200 additions and 4 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
node_modules
npm-*.log
compare.js
*.pyc
*.gem
Gemfile.lock
42 changes: 40 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# MailChecker
# MailChecker
[![Build Status](https://drone.io/github.com/FGRibreau/mailchecker/status.png)](https://drone.io/github.com/FGRibreau/mailchecker/latest) [![Deps](https://david-dm.org/FGRibreau/mailchecker.png)](https://david-dm.org/FGRibreau/mailchecker) [![Version](http://badge.fury.io/js/mailchecker.png)](http://badge.fury.io/js/mailchecker) [![Downloads](http://img.shields.io/npm/dm/mailchecker.svg)](https://www.npmjs.com/package/mailchecker)

Cross-language email validation. Backed by a [database](./list.json) of **1979 throwable email providers**.
Expand All @@ -10,10 +10,22 @@ This will be very helpful when you have to contact your users and you want to av

-------------------------

> Looking for a free **Redis administration & monitoring** service?
>
> [**Create your free account on Redsmin**](https://redsmin.com?gh)

<p align="center"><a href="https://redsmin.com?gh"><img src="https://redsmin.com/logo/[email protected]"/></a></p>

-------------------------

MailChecker currently supports:
* [NodeJS](https://github.com/FGRibreau/mailchecker/tree/master/platform/node) (CommonJS)
* [JavaScript](https://github.com/FGRibreau/mailchecker/tree/master/platform/javascript) (Client-Side)
* [PHP](https://github.com/FGRibreau/mailchecker/tree/master/platform/php)
* [Python](https://github.com/FGRibreau/mailchecker/tree/master/platform/python)
* [Ruby](https://github.com/FGRibreau/mailchecker/tree/master/platform/ruby)
* [Elixir](https://github.com/FGRibreau/mailchecker/tree/master/platform/elixir)
* **Easily add support for your own language with MailChecker template system and [send us a pull-request!](https://github.com/FGRibreau/mailchecker/fork_select)**

-------------------------
Expand Down Expand Up @@ -50,6 +62,7 @@ if(!MailChecker('myemail.com')){
```

### PHP

```php
include __DIR__."/MailChecker/platform/php/MailChecker.php";

Expand All @@ -62,6 +75,31 @@ if(!MailChecker('myemail.com')){
}
```

### Elixir

```elixir
Code.require_file("mail_checker.ex", "mailchecker/platform/elixir/")

unless MailChecker.valid?("[email protected]") do
raise "O RLY !"
end

unless MailChecker.valid?("myemail.com") do
raise "O RLY !"
end
```

### Python

```python
# no package yet; just drop in MailChecker.py where you want to use it.
import MailChecker
m = MailChecker.MailChecker()

if not m.is_valid('[email protected]'):
print "O RLY !"
```

### Ruby [![Build Status](https://travis-ci.org/FGRibreau/mailchecker.svg)](https://travis-ci.org/FGRibreau/mailchecker)

```ruby
Expand All @@ -88,7 +126,7 @@ npm install mailchecker

Ruby
```bash
gem install mail_checker
gem install ruby-mailchecker
```

__We accept pull-requests for other package manager__.
Expand Down
28 changes: 28 additions & 0 deletions platform/elixir/mail_checker.ex

Large diffs are not rendered by default.

28 changes: 28 additions & 0 deletions platform/elixir/mail_checker.tmpl.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
defmodule MailChecker do
def valid?(email) do
valid_address?(email) && !in_blacklist?(email)
end

def in_blacklist?(email) do
set = Enum.into(blacklist, HashSet.new)

member = HashSet.member?(set, extract_top_domain(email))
member
end

def blacklist do
[{{& listSTR }}]
end

def extract_top_domain(email) do
domain = String.split(email, "@") |> List.last
domain_parts = String.split(domain, ".")
top_domain_part = Enum.slice(domain_parts, -2..2)
Enum.join(top_domain_part, ".")
end

def valid_address?(email) do
Regex.match?(~r/^(?!(?:(?:\x22?\x5C[\x00-\x7E]\x22?)|(?:\x22?[^\x5C\x22]\x22?)){255,})(?!(?:(?:\x22?\x5C[\x00-\x7E]\x22?)|(?:\x22?[^\x5C\x22]\x22?)){65,}@)(?:(?:[\x21\x23-\x27\x2A\x2B\x2D\x2F-\x39\x3D\x3F\x5E-\x7E]+)|(?:\x22(?:[\x01-\x08\x0B\x0C\x0E-\x1F\x21\x23-\x5B\x5D-\x7F]|(?:\x5C[\x00-\x7F]))*\x22))(?:\.(?:(?:[\x21\x23-\x27\x2A\x2B\x2D\x2F-\x39\x3D\x3F\x5E-\x7E]+)|(?:\x22(?:[\x01-\x08\x0B\x0C\x0E-\x1F\x21\x23-\x5B\x5D-\x7F]|(?:\x5C[\x00-\x7F]))*\x22)))*@(?:(?:(?!.*[^.]{64,})(?:(?:(?:xn--)?[a-z0-9]+(?:-[a-z0-9]+)*\.){1,126}){1,}(?:(?:[a-z][a-z0-9]*)|(?:(?:xn--)[a-z0-9]+))(?:-[a-z0-9]+)*)|(?:\[(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){7})|(?:(?!(?:.*[a-f0-9][:\]]){7,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?)))|(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){5}:)|(?:(?!(?:.*[a-f0-9]:){5,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3}:)?)))?(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9]))(?:\.(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9]))){3}))\]))$/i, email)
end

end
23 changes: 23 additions & 0 deletions platform/python/MailChecker.py

Large diffs are not rendered by default.

23 changes: 23 additions & 0 deletions platform/python/MailChecker.tmpl.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import re

class MailChecker(object):

def __init__(self):
self.list_string = """{{list}}"""

# valid email format regex source: https://gist.github.com/dideler/5219706
self.email_regex = """([a-z0-9!#$%&'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+\/=?^_`"
"{|}~-]+)*(@|\sat\s)(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?(\.|"
"\sdot\s))+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)"""
self.fake_matcher = re.compile('|'.join(map(lambda x: '\\b' + x.lower() + '$', self.list_string.split(","))))
self.valid_matcher = re.compile(self.email_regex)

def is_valid(self, email):
email = email.lower()
return self.is_valid_email_format(email) and self.fake_matcher.search(email) == None

def is_valid_email_format(self, email):
if email and email != '':
return self.valid_matcher.search(email) != None
else:
return False
1 change: 1 addition & 0 deletions platform/ruby/ruby-mailchecker.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
require 'mail_checker'
4 changes: 2 additions & 2 deletions mail_checker.gemspec → ruby-mailchecker.gemspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# coding: utf-8
Gem::Specification.new do |spec|
spec.name = 'mail_checker'
spec.name = 'ruby-mailchecker'
spec.version = '0.1.0'
spec.authors = ['Francois-Guillaume Ribreau', 'Jacob Burenstam']
spec.email = ['[email protected]']
Expand All @@ -10,6 +10,6 @@ Gem::Specification.new do |spec|
spec.homepage = 'https://github.com/FGRibreau/mailchecker'
spec.license = 'MIT'

spec.files = ['platform/ruby/mail_checker.rb']
spec.files = ['platform/ruby/mail_checker.rb', 'platform/ruby/ruby-mailchecker.rb']
spec.require_paths = ['platform/ruby']
end
36 changes: 36 additions & 0 deletions test/platform.elixir.test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Run tests from the repository root directory:
# $ elixir test/platform.elixir.test.exs
ExUnit.start

try do
Code.require_file("mail_checker.ex", "platform/elixir/")
rescue
_ -> raise ArgumentError, message: "You must be in the repository root directory in order to run the tests."
end

defmodule MailCheckerTest do
use ExUnit.Case

test "should return true if the email is valid" do
assert MailChecker.valid?("[email protected]")
assert MailChecker.valid?("[email protected]")
assert MailChecker.valid?("[email protected]")
assert MailChecker.valid?("[email protected]")
assert MailChecker.valid?("[email protected]")
assert MailChecker.valid?("[email protected]")
end

test "should return false if the email is invalid" do
assert MailChecker.valid?("plopplop.com") == false
assert MailChecker.valid?("my+ok@ok°plop.com") == false
assert MailChecker.valid?("my+ok@ok=plop.com") == false
assert MailChecker.valid?("my,[email protected]") == false
assert MailChecker.valid?("[email protected]") == false
end

test "should return false if the email come from a throwable domain" do
assert MailChecker.valid?("[email protected]") == false
assert MailChecker.valid?("[email protected]") == false
end

end
18 changes: 18 additions & 0 deletions test/platform.python.test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# compatibility with both Python 2.x and 3.x
from __future__ import print_function

# for testing only; add the python MailChecker to the system path
import os, sys
sys.path.insert(0, '../platform/python/')

# import MailChecker, create instance, check emails
import MailChecker

m = MailChecker.MailChecker()

print( m.is_valid('[email protected]'))
print( m.is_valid('[email protected]'))
print( m.is_valid('[email protected]'))
print( m.is_valid('[email protected]'))
print( m.is_valid('[email protected]'))
print( m.is_valid(''))

0 comments on commit 665c136

Please sign in to comment.