A quick note on validating email addresses in Rails.
Rails gives you a couple of clean options here — a built-in regex approach that covers most cases, and a gem if you need deeper validation (MX record checks, disposable email detection, etc.).
-
1
Built-in format validation (usually enough)
Rails 7.1+ ships a
URI::MailTo::EMAIL_REGEXPconstant you can reference directly:
app/models/user.rb
Ruby
class User < ApplicationRecord
validates :email,
presence: true,
uniqueness: { case_sensitive: false },
format: { with: URI::MailTo::EMAIL_REGEXP, message: "must be a valid email address" }
end
On older Rails, use a simple regex:
app/models/user.rb
Ruby
VALID_EMAIL_REGEX = /\A[^@\s]+@[^@\s]+\.[^@\s]+\z/
validates :email,
presence: true,
format: { with: VALID_EMAIL_REGEX }
-
2
Normalise the email before saving
It’s good practice to downcase and strip whitespace so
User@Example.comanduser@example.comare treated as the same address:
app/models/user.rb
Ruby
before_validation :normalise_email
private
def normalise_email
self.email = email.to_s.downcase.strip
end
-
3
Deep validation with the truemail gem
If you need to verify the domain actually has MX records (catches typos like
@gamil.com), add the gem:
Gemfile
Ruby
gem "truemail"
config/initializers/truemail.rb
Ruby
Truemail.configure do |config|
config.verifier_email = "hello@yourdomain.com"
config.validation_type_for = { "gmail.com" => :regex }
end
Then validate on demand:
email.rb
Ruby
result = Truemail.validate("user@example.com")
result.result.valid? # => true / false
For most apps, Option 1 + 2 is plenty. Reach for truemail when you need to cut down on bounces on a transactional email flow.