Skip to content

Instantly share code, notes, and snippets.

@scottserok
Last active January 23, 2019 16:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save scottserok/6d28844655348a511bde8cc2c85b4659 to your computer and use it in GitHub Desktop.
Save scottserok/6d28844655348a511bde8cc2c85b4659 to your computer and use it in GitHub Desktop.
Add a custom MX validator to your rails app in app/validators/email_mx_validator.rb
# frozen_string_literal: true
require 'mail' unless defined? Mail
require 'resolv' unless defined? Resolv
# == Summary
# This validator checks for a valid DNS MX resource
# for the given email address. The domain of the email
# address is extracted and used to perform a DNS lookup
# for an MX resource. A valid DNS MX resource does not
# gaurantee that the email address is valid, only that
# the *domain* of the email address is valid for email.
#
# == Usage
# Use the +EmailMxValidator+ on a +User+ model.
#
# class User < ApplicationRecord
# validates :email, email_mx: true
# end
#
# user = User.new email: 'scott@serok.us'
# user.valid?
# #=> true
# user.email = 'scott@wizards.unicorn89'
# user.valid?
# #=> false
# user.errors.full_messages
# #=> ["Email MX record missing for the domain \"wizards.unicorn89\""]
class EmailMxValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
domain = email_domain(record, attribute, value)
return false if record.errors[attribute].any?
mx_record_for_domain(record, attribute, domain)
return false if record.errors[attribute].any?
true
end
private
def email_domain(record, attribute, email)
address = Mail::Address.new(email)
return address.domain if address.domain
record.errors[attribute] << %("#{email}" does not have a domain)
end
def mx_record_for_domain(record, attribute, domain)
dns = Resolv::DNS.new
dns.getresource(domain, Resolv::DNS::Resource::IN::MX)
rescue Resolv::ResolvError
record.errors[attribute] << %(MX record missing for the domain "#{domain}")
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment