Time and time again in our Rails projects we find ourselves validating email addresses for well-formedness, often in User models like this:
validates_format_of :email, :with => /\A([^@\s]+)@((?:[-a-z0-9]+.)+[a-z]{2,})\Z/i
This is fine for checking the form of an email address, but we can do more to make sure that users enter correct addresses. Anyone who's run a production site has witnessed mistyped addresses like heycarsten@gmaol.com, and with the above scheme this would be accepted. Here's where the validates_email_veracity_of plugin comes in.
validates_email_veracity_of :email
Now in addition to checking the format, the email domain is checked for MX records. (It's remarkable how many errors this catches on our production site Languify.)
To speed things up, the plugin includes a list of popular domains which are skipped.
Just want to check the format?
validates_email_veracity_of :email, :domain_check => false
Require a custom error message?
validates_email_veracity_of :email, :message => 'is not correct at all.'
By default the plugin waits for two seconds before quietly skipping the domain lookup, if you want to change this timeout interval simply:
validates_email_veracity_of :email, :timeout => 1 # => Time in seconds.
There are many other options, all documented in the README.
Install the plugin into your Rails project the standard way:
> script/plugin install http://svn.savvica.com/public/plugins/validates_email_veracity_of
Let us know if validates_email_veracity_of has helped you, or of any improvements that come to mind. As always, patches and enhancements are encouraged.


Paul, I appreciate your interest! I have tested many different patterns to include RFC 2822 validation but none of them will pass the tests. You are more than welcome to submit an enhancement.
Index: lib/validates_email_veracity_of.rb =================================================================== --- lib/validates_email_veracity_of.rb (revision 12) +++ lib/validates_email_veracity_of.rb (working copy) @@ -16,6 +16,7 @@ require 'resolv' require 'timeout' + require 'socket' attr_accessor :name @@ -34,6 +35,17 @@ rescue Timeout::Error nil end + + # Returns the array value returned by gethostbyname, if the domain does + # not exist, it will return an empty array. If it times out, nil is + # returned + def gethostbyname(options = {}) + st = Timeout::timeout(options.fetch(:timeout, 2)) do + Socket.gethostbyname(name) rescue [] + end + rescue Timeout::Error + nil + end end @@ -66,15 +78,16 @@ # specified. def domain_has_mail_servers?(options = {}) return true if EmailAddress.known_domains.include?(domain.name.downcase) - mail_servers = domain.mail_servers(options) - if mail_servers.nil? + list = domain.mail_servers(options) + list = domain.gethostbyname(options) if list.blank? + if list.nil? options.fetch(:fail_on_timeout, true) ? nil : true else - !mail_servers.empty? + !list.empty? end end end -end \ No newline at end of file +end Index: lib/extensions.rb =================================================================== --- lib/extensions.rb (revision 12) +++ lib/extensions.rb (working copy) @@ -52,4 +52,4 @@ end end -end \ No newline at end of file +endPetyo, I’ve updated the plugin, as part of the update I renamed the file so hopefully this does not happen to you or anyone else anymore.
Shanti, The plugin does validate addresses with plus signs in them. It uses the pattern from the
validates_format_ofexample in the Rails documentation.Excellent plugin! I just downloaded and installed this baby, and it works like a champ. Well done!
Nice plugin, and thanks for your work.
If you are interested, having the knowndomains be something we can add to would be great. I have modified the plugin to support it. The patch is at http://pastie.caboo.se/123138 In my spechelper.rb, I do this:
ValidatesEmailVeracityOf::EmailAddress.known_domains << “nomail.net”
aiwilliams, that’s a great suggestion, I’ll be adding that functionality in the next release for sure. Thanks for the support and thanks for the contribution!
When I put ‘sth@’ as email I got an error [“You have a nil object when you didn’t expect it! The error occured while evaluating nil.strip”]
dirtyPeter, thanks for the find. I have fixed the issue.
Thanks - this plugin will solve the exact problem I am facing :)
right now you end up with servers == [nil, nil] for invalid domains
Hi, thanks for this plugin, it really helps me out.
You could add some french providers domains to your whitelist : %w[ free.fr wanadoo.fr orange.fr laposte.net yahoo.fr voila.fr club-internet.fr neuf.fr noos.fr tiscali.fr tele2.fr ]
Found a small bug. It’s validating this email address ( “.@netinlet.com”). Great plugin - Thanks.