philiprehberger-email_validator

Tests Gem Version Last updated

RFC-compliant email validation with MX record verification, disposable domain detection, normalization, and typo suggestions

Requirements

  • Ruby >= 3.1

Installation

Add to your Gemfile:

gem "philiprehberger-email_validator"

Or install directly:

gem install philiprehberger-email_validator

Usage

require "philiprehberger/email_validator"

Philiprehberger::EmailValidator.valid?("[email protected]")
# => true

Philiprehberger::EmailValidator.valid?("not-an-email")
# => false

Full Validation

result = Philiprehberger::EmailValidator.validate("[email protected]")
result.valid?    # => true
result.errors    # => []
result.warnings  # => []

result = Philiprehberger::EmailValidator.validate("[email protected]")
result.valid?    # => true
result.warnings  # => ["address appears to be role-based"]

MX Record Verification

result = Philiprehberger::EmailValidator.validate("[email protected]", check_mx: true)
result.valid?  # => true (if domain has MX/A records)

Philiprehberger::EmailValidator.mx_valid?("example.com")
# => true

Disposable Domain Detection

Philiprehberger::EmailValidator.disposable?("[email protected]")
# => true

result = Philiprehberger::EmailValidator.validate("[email protected]", allow_disposable: false)
result.valid?  # => false
result.errors  # => ["disposable email domains are not allowed"]

Role-Based Address Detection

Philiprehberger::EmailValidator.role_based?("[email protected]")
# => true

Philiprehberger::EmailValidator.role_based?("[email protected]")
# => false

Bulk Validation

emails = ["[email protected]", "invalid", "[email protected]"]

results = Philiprehberger::EmailValidator.validate_all(emails, allow_disposable: false)
results[0].valid?  # => true
results[1].valid?  # => false

Philiprehberger::EmailValidator.valid_all?(["[email protected]", "[email protected]"])
# => true

Batch Validation (Hash)

emails = ["[email protected]", "invalid", "[email protected]"]

results = Philiprehberger::EmailValidator.batch_validate(emails)
results["[email protected]"].valid?  # => true
results["invalid"].valid?           # => false
results["[email protected]"].valid? # => true

Custom Disposable Domain List

Philiprehberger::EmailValidator.configure do |config|
  config.add_disposable_domains(["custom-temp.com", "temp.org"])
  config.remove_disposable_domains(["mailinator.com"])
end

Philiprehberger::EmailValidator.disposable?("[email protected]")
# => true

Philiprehberger::EmailValidator.reset_configuration!

Email Normalization

Philiprehberger::EmailValidator.normalize("[email protected]")
# => "[email protected]"

Philiprehberger::EmailValidator.normalize("  [email protected]  ")
# => "[email protected]"

Sub-address Tags

Philiprehberger::EmailValidator.extract_tag("[email protected]")
# => "promo"

Philiprehberger::EmailValidator.extract_tag("[email protected]")
# => nil

Philiprehberger::EmailValidator.strip_tag("[email protected]")
# => "[email protected]"

Philiprehberger::EmailValidator.strip_tag("[email protected]")
# => "[email protected]"

Splitting an Address

Get the local, domain, and tag in one call:

Philiprehberger::EmailValidator.split("[email protected]")
# => { local: "user", domain: "example.com", tag: "work" }

Philiprehberger::EmailValidator.split("[email protected]")
# => { local: "user", domain: "example.com", tag: nil }

Philiprehberger::EmailValidator.split("not-an-email")
# => nil

Canonical Equality

require "philiprehberger/email_validator"

Philiprehberger::EmailValidator.canonical_equal?("[email protected]", "[email protected]")
# => true

Philiprehberger::EmailValidator.canonical_equal?("[email protected]", "[email protected]")
# => false

Philiprehberger::EmailValidator.canonical_equal?(nil, "[email protected]")
# => false

Typo Suggestion

Philiprehberger::EmailValidator.suggest("[email protected]")
# => { original: "[email protected]", suggested: "[email protected]" }

Philiprehberger::EmailValidator.suggest("[email protected]")
# => nil

Domain Info

Philiprehberger::EmailValidator.domain_info("[email protected]")
# => { domain: "mail.example.co.uk", tld: "uk" }

Philiprehberger::EmailValidator.domain_info("[email protected]", check_mx: true)
# => { domain: "example.com", tld: "com", mx_records: ["mail.example.com"] }

API

Method Description
EmailValidator.valid?(email) Quick syntax check, returns boolean
EmailValidator.validate(email, check_mx: false, allow_disposable: true) Full validation returning Result
EmailValidator.validate_all(emails, **opts) Bulk validation returning array of Results
EmailValidator.batch_validate(emails, **opts) Bulk validation returning hash of { email => Result }
EmailValidator.valid_all?(emails) Returns true only if all emails are valid
EmailValidator.mx_valid?(domain) Check if domain has MX or A records
EmailValidator.disposable?(email) Check if email uses a disposable domain
EmailValidator.role_based?(email) Detect role-based addresses (info@, admin@, etc.)
`EmailValidator.configure { \ config\ ... }` Configure custom disposable domain list
EmailValidator.reset_configuration! Reset configuration to defaults
EmailValidator.normalize(email) Normalize email (lowercase, remove aliases, Gmail dots)
EmailValidator.canonical_equal?(a, b) Compare two emails after normalization; false on invalid input
EmailValidator.same_domain?(a, b) Return true when both addresses share the same domain (case-insensitive); false for invalid input
EmailValidator.extract_tag(email) Extract the sub-address tag after + in the local part; nil if none or invalid
EmailValidator.strip_tag(email) Remove any +tag from the local part; returns the original value on invalid input
EmailValidator.split(email) Return { local:, domain:, tag: }; nil for invalid input
EmailValidator.suggest(email) Suggest corrected domain for typos
EmailValidator.domain_info(email, check_mx: false) Extract domain metadata

Result

Method Description
#valid? True if no validation errors
#errors Array of error message strings
#warnings Array of warning message strings

Development

bundle install
bundle exec rspec
bundle exec rubocop

Support

If you find this project useful:

Star the repo

🐛 Report issues

💡 Suggest features

❤️ Sponsor development

🌐 All Open Source Projects

💻 GitHub Profile

🔗 LinkedIn Profile

License

MIT