Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,5 @@ Style/StringLiterals:
EnforcedStyle: double_quotes
Gemspec/OrderedDependencies:
Enabled: no
Metrics/BlockLength:
Enabled: no
21 changes: 15 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,13 @@ To validate strictly that the domain has an MX record:
```ruby
validates :email, 'valid_email_2/email': { strict_mx: true }
```
`strict_mx` and `mx` both default to a 5 second timeout for DNS lookups.
`strict_mx` and `mx` both default to a 5 second timeout for DNS lookups.
To override this timeout, specify a `dns_timeout` option:
```ruby
validates :email, 'valid_email_2/email': { strict_mx: true, dns_timeout: 10 }
```

Any checks that require DNS resolution will use the default `Resolv::DNS` nameservers for DNS lookups.
Any checks that require DNS resolution will use the default `Resolv::DNS` nameservers for DNS lookups.
To override these, specify a `dns_nameserver` option:
```ruby
validates :email, 'valid_email_2/email': { mx: true, dns_nameserver: ['8.8.8.8', '8.8.4.4'] }
Expand Down Expand Up @@ -145,10 +145,19 @@ If you want to allow multibyte characters, set it explicitly.
ValidEmail2::Address.permitted_multibyte_characters_regex = /[ÆæØøÅåÄäÖöÞþÐð]/
```

If you want to load any of the lists dynamically:

```ruby
# make sure to use a Set for speedy access and cache the result
ValidEmail2.disposable_proc = -> { Set.new(['your.com']) }
ValidEmail2.deny_proc = -> { Set.new(['data.com']) }
ValidEmail2.allow_proc = -> { Set.new(['provided.com']) }
```

### Test environment

If you are validating `mx` then your specs will fail without an internet connection.
It is a good idea to stub out that validation in your test environment.
It is a good idea to stub out that validation in your test environment.
Do so by adding this in your `spec_helper`:
```ruby
config.before(:each) do
Expand All @@ -168,7 +177,7 @@ This gem is tested against currently supported Ruby and Rails versions. For an u

In version v5.3.0 the config directory files were renamed as follows:

`config/blacklisted_email_domains.yml` -> `config/deny_listed_email_domains.yml`
`config/blacklisted_email_domains.yml` -> `config/deny_listed_email_domains.yml`
`config/whitelisted_email_domains.yml` -> `config/allow_listed_email_domains.yml`

You won't need to make any changes yourself if you're installing this version for the first time. For individuals updating from earlier versions, make sure to update the file namings as per the above. In future versions this will be a breaking change.
Expand All @@ -178,7 +187,7 @@ You won't need to make any changes yourself if you're installing this version fo
In version v3.0.0 I decided to move __and__ rename the config files from the
vendor directory to the config directory. That means:

`vendor/blacklist.yml` -> `config/blacklisted_email_domains.yml`
`vendor/blacklist.yml` -> `config/blacklisted_email_domains.yml`
`vendor/whitelist.yml` -> `config/whitelisted_email_domains.yml`

The `disposable` validation has been improved with a `mx` check. Apply the
Expand All @@ -187,7 +196,7 @@ down or if they do not work without an internet connection.

## Upgrading to v2.0.0

In version 1.0 of valid_email2 we only defined the `email` validator.
In version 1.0 of valid_email2 we only defined the `email` validator.
But since other gems also define a `email` validator this can cause some unintended
behaviours and emails that shouldn't be valid are regarded valid because the
wrong validator is used by rails.
Expand Down
19 changes: 14 additions & 5 deletions lib/valid_email2.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,27 @@ module ValidEmail2
ALLOW_LIST_FILE = "config/allow_listed_email_domains.yml"
DISPOSABLE_FILE = File.expand_path('../config/disposable_email_domains.txt', __dir__)

cattr_accessor :disposable_proc do
-> { @disposable_emails ||= load_file(DISPOSABLE_FILE) }
end
cattr_accessor :deny_proc do
-> { @deny_list ||= load_if_exists(DENY_LIST_FILE) || Set.new }
end
cattr_accessor :allow_proc do
-> { @allow_list ||= load_if_exists(ALLOW_LIST_FILE) || Set.new }
end

class << self
def disposable_emails
@disposable_emails ||= load_file(DISPOSABLE_FILE)
disposable_proc&.call
end

def deny_list
@deny_list ||= load_if_exists(DENY_LIST_FILE) || Set.new
deny_proc&.call
end

def allow_list
@allow_list ||= load_if_exists(ALLOW_LIST_FILE) || Set.new
allow_proc&.call
end

private
Expand All @@ -27,8 +37,7 @@ def load_if_exists(path)
end

def load_file(path)
# This method MUST return a Set, otherwise the
# performance will suffer!
# This method MUST return a Set, otherwise the performance will suffer!
if path.end_with?(".yml")
Set.new(YAML.load_file(path))
else
Expand Down
16 changes: 16 additions & 0 deletions spec/valid_email2_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,22 @@ def set_allow_list
end
end

describe "with deny list validation" do
before do
@old_proc = ValidEmail2.deny_proc
end

after do
ValidEmail2.deny_proc = @old_proc
end

it "is invalid if the domain is deny-listed from a proc" do
ValidEmail2.deny_proc = -> { @deny_list ||= Set.new(['dubbi.com']) }
user = TestUserDisallowDenyListed.new(email: "foo@dubbi.com")
expect(user.valid?).to be_falsey
end
end

describe "with mx validation" do
it "is valid if mx records are found" do
user = TestUserMX.new(email: "foo@gmail.com")
Expand Down