[Awesome Ruby Gem] Use valid_email2 gem to validate email address

valid_email2

Validate emails with the help of the mail gem instead of some clunky regexp. Aditionally validate that the domain has a MX record. Optionally validate against a static list of disposable email services - https://github.com/micke/valid_email2/blob/master/config/disposable_email_domains.txt. Optionally validate that the email is not subaddressed ([RFC5233 - https://tools.ietf.org/html/rfc5233]{https://tools.ietf.org/html/rfc5233}).

Installation

You can install it as a gem:

1
$ gem install valid_email2

or add it into a Gemfile (Bundler):

1
2
3
4
5
# Gemfile

# GitHub - micke/valid_email2: ActiveModel validation for email. Including MX lookup and disposable email blacklist
# https://github.com/micke/valid_email2
gem 'valid_email2', '4.0.0'

Then, run bundle install.

1
$ bundle install

Usages

Use with ActiveModel

If you just want to validate that it is a valid email address:

1
2
3
class User < ActiveRecord::Base
validates :email, presence: true, 'valid_email_2/email': true
end

To validate that the domain has an MX record or A record:

1
validates :email, 'valid_email_2/email': { mx: true }

To validate strictly that the domain has an MX record:

1
validates :email, 'valid_email_2/email': { strict_mx: true }

strict_mx and mx both default to a 5 second timeout for DNS lookups. To override this timeout, specify a dns_timeout option:

1
validates :email, 'valid_email_2/email': { strict_mx: true, dns_timeout: 10 }

To validate that the domain is not a disposable email (checks domain and MX server):

1
validates :email, 'valid_email_2/email': { disposable: true }

To validate that the domain is not a disposable email (checks domain only, does not check MX server):

1
validates :email, 'valid_email_2/email': { disposable_domain: true }

To validate that the domain is not a disposable email or a disposable email (checks domain and MX server) but whitelisted (under config/whitelisted_email_domains.yml):

1
validates :email, 'valid_email_2/email': { disposable_with_whitelist: true }

To validate that the domain is not a disposable email or a disposable email (checks domain only, does not check MX server) but whitelisted (under config/whitelisted_email_domains.yml):

1
validates :email, 'valid_email_2/email': { disposable_domain_with_whitelist: true }

To validate that the domain is not blacklisted (under config/blacklisted_email_domains.yml):

1
validates :email, 'valid_email_2/email': { blacklist: true }

To validate that email is not subaddressed:

1
validates :email, 'valid_email_2/email': { disallow_subaddressing: true }

To validate that email does not contain a dot before the @:

1
validates :email, 'valid_email_2/email': { disallow_dotted: true }

To validate create your own custom message:

1
validates :email, 'valid_email_2/email': { message: "is not a valid email" }

To allow multiple addresses separated by comma:

1
validates :email, 'valid_email_2/email': { multiple: true }

All together:

1
validates :email, 'valid_email_2/email': { mx: true, disposable: true, disallow_subaddressing: true}

Note that this gem will let an empty email pass through so you will need to add presence: true if you require an email

Use without ActiveModel

1
2
3
4
5
6
address = ValidEmail2::Address.new("[email protected]")
address.valid? => true
address.disposable? => false
address.valid_mx? => true
address.valid_strict_mx? => true
address.subaddressed? => false

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.
Do so by adding this in your spec_helper:

1
2
3
4
config.before(:each) do
allow_any_instance_of(ValidEmail2::Address).to receive(:valid_mx?).and_return(true)
allow_any_instance_of(ValidEmail2::Address).to receive(:valid_strict_mx?).and_return(true)
end

Validating disposable e-mails triggers a mx validation alongside checking if the domain is disposable. The above stub does not apply to the disposable validation and should therefore be individually stubbed with:

1
2
3
config.before(:each) do
allow_any_instance_of(ValidEmail2::Address).to receive(:mx_server_is_in?).and_return(false)
end

References

[1] GitHub - micke/valid_email2: ActiveModel validation for email. Including MX lookup and disposable email blacklist - https://github.com/micke/valid_email2

[2] valid_email2 | RubyGems.org | your community gem host - https://rubygems.org/gems/valid_email2/