Last active
January 23, 2019 16:37
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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