Ensuring email addresses are valid in a Rails application is key to maintaining data integrity and a smooth user experience. We'll explore five ways to implement this validation, providing working code snippets for each. We will also examine the pitfalls of these traditional methods and show how Abstract API addresses them.
How to Implement Email Validation in Rails
Here are four common methods to validate email formats directly within a Rails application. Each approach uses different tools, from built-in constants to specialized gems for more advanced checks.
Inline Regular Expression
This method uses pure ActiveModel format validation. It defines a regular expression, or regex, as a constant named "EMAIL_REGEX" inside the User model to check the email's structure. The code validates that the email attribute is present and matches this pattern.
This approach keeps the application's dependency graph small because it does not require an external gem, a DNS call, or extra memory allocations. The regex pattern itself can be adjusted to fit specific domain requirements, such as to allow or disallow sub-domains.
class User < ApplicationRecord
EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true, format: { with: EMAIL_REGEX }
end
Built-in URI::MailTo::EMAIL_REGEXP
Ruby's standard library includes a predefined constant, "URI::MailTo::EMAIL_REGEXP", for email validation. Since Rails automatically picks up this constant, you can use it directly in your model validations without any setup.
This expression mirrors the one used by browsers for fields with "type=email", which ensures server-side and client-side validations share the same logic. The code simply applies this built-in regex to the email attribute.
class User < ApplicationRecord
validates :email, format: { with: URI::MailTo::EMAIL_REGEXP }
end
The activemodel-email_address_validator Gem
This gem provides a plug-and-play validator for ActiveModel. After you add the gem to your Gemfile, you can use the "email_address: true" validator in your model. The gem supports internationalization and rejects local-only addresses.
It can also perform a DNS lookup for a domain's Mail Exchange (MX) record, which indicates if the domain can receive email. You can extend its functionality with custom patterns to enforce specific policies. The code shows basic validation, a DNS MX lookup, and a custom rule.
# Gemfile
gem 'activemodel-email_address_validator'
# Model
class User < ApplicationRecord
validates :email, email_address: true # basic
validates :email, email_address: { mx: true } # DNS MX lookup
validates :email, email_address: { with: /…/ } # custom rule
end
The email_address Gem
The "email_address" gem is a full parser that tokenizes and normalizes email addresses. It can provide a canonical form for uniqueness checks, a redacted form for privacy, and even offers ActiveRecord type casting.
The gem supports multiple validation modes, autocorrects capitalization, and strips tags from addresses like "user+tag@example.com". It also integrates with I18n for custom error messages. The code shows how to add the validator to the model.
# Gemfile
gem 'email_address'
# Model
class User < ApplicationRecord
validates_with EmailAddress::ActiveRecordValidator, field: :email
end
Challenges of Email Validation in Rails
While these methods offer some control, they introduce significant challenges. Simplified regex patterns, limited scope, and maintenance overhead often lead to both false positives and rejected valid emails.
- Simplified patterns, like inline regex or the built-in URI::MailTo::EMAIL_REGEXP, willfully violate the RFC-5322 spec. They fail to account for edge cases like apostrophes or quoted local parts, which results in the rejection of valid addresses.
- Most Rails patterns, especially custom regex, lack support for internationalized mailboxes. They fail to match Unicode characters or punycoded domains, so the system incorrectly rejects valid global email addresses and confuses international users.
- Syntax validation alone does not confirm an email's reachability. Methods like inline regex check format but cannot detect if a mailbox exists or if the domain accepts mail. This means syntactically correct addresses can still bounce.
- The email landscape constantly evolves with new TLDs and disposable domains. Hard-coded patterns, common in inline regex validations, quickly become outdated. Without frequent manual updates, they block legitimate users and accept throwaway addresses.
Validate Emails with Abstract API
Ensure every email is valid in your Rails project for clean data and deliverability.
Get started for free
How Abstract API Handles Email Validation in Rails
Abstract API addresses the core weaknesses of traditional validation methods through advanced typo detection, real-time SMTP checks, and comprehensive domain analysis.
- It moves past simple syntactic checks that miss common typos. Instead, it employs machine learning to detect typos and offer autocorrect suggestions, which lets you prompt the user before a record saves.
- It replaces slow, thread-blocking DNS and MX checks run from your server. The API performs fast MX and real-time SMTP handshakes to determine if an address is DELIVERABLE, UNDELIVERABLE, or UNKNOWN.
- It eliminates the need to maintain blocklists for disposable or role-based domains. The API continuously refreshes its database of disposable domains, flags role-based addresses, and provides a quality score for fine-tuned acceptance rules.
How to Set Up Abstract API in Your Project
Once you possess familiarity with Abstract’s capabilities, the addition of its email validation API to your project is simple. The setup requires just a few steps.
- Add an HTTP client like Faraday to your Gemfile, then run bundle install.
- Sign up at Abstract, create an Email Validation key, and copy it.
- Store the key in Rails credentials or an environment variable like "ABSTRACT_EMAIL_API_KEY".
- Create a file at app/services/abstract_email_validator.rb and insert this code:
class AbstractEmailValidator
ENDPOINT = 'https://emailvalidation.abstractapi.com/v1/'.freeze
def self.validate(email)
res = Faraday.get(ENDPOINT, { api_key: ENV.fetch('ABSTRACT_EMAIL_API_KEY'), email: email }, { 'Accept' => 'application/json' })
JSON.parse(res.body, symbolize_names: true)
end
end
Sample Email Validation Implementation with Abstract API
With the validator in place, you can use it in a model. This code defines a custom validation method, `email_must_be_deliverable`. This method calls the validator we just created. It checks the API response to confirm the email's deliverability status is "DELIVERABLE" and that it is not a disposable address. If the email fails these checks, the method adds an error to the record.
validate :email_must_be_deliverable
def email_must_be_deliverable
r = AbstractEmailValidator.validate(email)
unless r[:deliverability] == 'DELIVERABLE' && !r[:is_disposable_email][:value]
errors.add(:email, 'cannot be delivered')
end
end
The API returns a JSON object with detailed information. The `deliverability` key summarizes all checks, while the `quality_score` allows you to weigh borderline results. Other boolean flags, like `is_disposable_email`, expose specific risks. You can combine these flags to create your own validation policy.
Here is a sample response:
{
"email": "eric@abstractapi.com",
"deliverability": "DELIVERABLE",
"quality_score": "0.80",
"is_valid_format": { "value": true },
"is_free_email": { "value": false },
"is_disposable_email": { "value": false },
"is_role_email": { "value": false },
"is_catchall_email": { "value": true },
"is_mx_found": { "value": true },
"is_smtp_valid": { "value": true }
}
Final Thoughts
Traditional validation in Rails often fails to catch simple typos or perform real-time checks without performance penalties. You also have the constant task to maintain blocklists. Abstract API solves these issues with typo detection, fast SMTP handshakes, and a managed database of disposable domains. To reliably validate user emails, consider the creation of an account on Abstract API for your free API key.
Validate Emails with Abstract API
Start validating emails in your Rails application to protect your data and boost email deliverability.
Get started for free