Add email validation plugin from:

git://github.com/dancroak/validates_email_format_of.git
This commit is contained in:
Tom Hughes 2010-02-25 19:14:50 +00:00
parent b547145865
commit aefc5f5112
14 changed files with 398 additions and 0 deletions

View file

@ -0,0 +1,3 @@
pkg
test/debug.log
*.swp

View file

@ -0,0 +1,22 @@
= CHANGELOG
== Version 1.0
* initial version
== Version 1.1 (the Francis Hwang edition)
* moved Regexp out of class methods into the ValidatesEmailFormatOf module
== Version 1.2 (the Ismael Santos Kafeltz and Michael MacDonald edition)
* added support for un-escaped and escaped special characters in the local part, per RFC 3696
* added :allow_nil option
== Version 1.2.1 (the RTFM edition)
* added support for quoted local parts
* added length checks for domain and local parts
* corrected escaped character support for RFC 3696 Errata
* added :allow_blank option
* added :unless option
== Unreleased
* Now available as a gem on GitHub
* added should_validate_email_format_of

View file

@ -0,0 +1,20 @@
Copyright (c) 2006 Alex Dunae
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View file

@ -0,0 +1,58 @@
Validates email format
======================
Validate various formats of email address against RFC 2822.
Usage
-----
class PersonTest < ActiveSupport::TestCase
should_validate_email_format_of :email
end
class Person < ActiveRecord::Base
validates_email_format_of :email
end
Options
-------
:message =>
String. A custom error message (default is: " does not appear to be a valid e-mail address")
:on =>
Symbol. Specifies when this validation is active (default is :save, other options :create, :update)
:allow_nil =>
Boolean. Allow nil values (default is false)
:allow_blank =>
Boolean. Allow blank values (default is false)
:if =>
Specifies a method, proc or string to call to determine if the validation should occur
(e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }). The method,
proc or string should return or evaluate to a true or false value.
:unless =>
See :if option.
Testing
-------
To execute the unit tests run <tt>rake test</tt>.
The unit tests for this plugin use an in-memory sqlite3 database.
Installing the gem
------------------
* gem sources -a http://gems.github.com (only needed once)
* sudo gem install dancroak-validates\_email\_format\_of
Credits
-------
Written by Alex Dunae (dunae.ca), 2006-07.
Thanks to Francis Hwang (http://fhwang.net/) at Diversion Media for creating the 1.1 update.

View file

@ -0,0 +1,12 @@
require 'rake'
require 'rake/testtask'
test_files_pattern = 'test/*_test.rb'
Rake::TestTask.new do |t|
t.libs << 'lib'
t.pattern = test_files_pattern
t.verbose = false
end
desc "Run the test suite"
task :default => :test

View file

@ -0,0 +1 @@
require File.join(File.dirname(__FILE__), 'rails', 'init')

View file

@ -0,0 +1,56 @@
# encoding: utf-8
module ValidatesEmailFormatOf
LocalPartSpecialChars = Regexp.escape('!#$%&\'*-/=?+-^_`{|}~')
LocalPartUnquoted = '(([[:alnum:]' + LocalPartSpecialChars + ']+[\.\+]+))*[[:alnum:]' + LocalPartSpecialChars + '+]+'
LocalPartQuoted = '\"(([[:alnum:]' + LocalPartSpecialChars + '\.\+]*|(\\\\[\u0001-\uFFFF]))*)\"'
Regex = Regexp.new('^((' + LocalPartUnquoted + ')|(' + LocalPartQuoted + ')+)@(((\w+\-+)|(\w+\.))*\w{1,63}\.[a-z]{2,6}$)', Regexp::EXTENDED | Regexp::IGNORECASE)
end
module ActiveRecord
module Validations
module ClassMethods
# Validates whether the value of the specified attribute is a valid email address
#
# class User < ActiveRecord::Base
# validates_email_format_of :email, :on => :create
# end
#
# Configuration options:
# * <tt>message</tt> - A custom error message (default is: " does not appear to be a valid e-mail address")
# * <tt>on</tt> - Specifies when this validation is active (default is :save, other options :create, :update)
# * <tt>allow_nil</tt> - Allow nil values (default is false)
# * <tt>allow_blank</tt> - Allow blank values (default is false)
# * <tt>if</tt> - Specifies a method, proc or string to call to determine if the validation should
# occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }). The
# method, proc or string should return or evaluate to a true or false value.
# * <tt>unless</tt> - See <tt>:if</tt>
def validates_email_format_of(*attr_names)
options = { :message => ' does not appear to be a valid e-mail address',
:on => :save,
:allow_nil => false,
:allow_blank => false,
:with => ValidatesEmailFormatOf::Regex }
options.update(attr_names.pop) if attr_names.last.is_a?(Hash)
validates_each(attr_names, options) do |record, attr_name, value|
v = value.to_s
# local part max is 64 chars, domain part max is 255 chars
# TODO: should this decode escaped entities before counting?
begin
domain, local = v.reverse.split('@', 2)
rescue
record.errors.add(attr_name, options[:message])
next
end
unless v =~ options[:with] and not v =~ /\.\./ and domain.length <= 255 and local.length <= 64
record.errors.add(attr_name, options[:message])
end
end
end
end
end
end

View file

@ -0,0 +1 @@
require 'validates_email_format_of'

View file

@ -0,0 +1,12 @@
require 'rake'
require 'rake/testtask'
test_files_pattern = 'test/*_test.rb'
Rake::TestTask.new do |t|
t.libs << 'lib'
t.pattern = test_files_pattern
t.verbose = false
end
desc "Run the test suite"
task :default => :test

View file

@ -0,0 +1,97 @@
module ValidatesEmailFormatOf
module Shoulda
def should_validate_email_format_of(field)
metaclass = (class << self; self; end)
metaclass.send(:define_method,:should_allow_values) do |klass,*values|
should_allow_values_for(field, *values)
end
metaclass.send(:define_method,:should_not_allow_values) do |klass, *values|
should_not_allow_values_for(field, values, :message => /valid e-mail/)
end
should_validate_email_format_of_klass(model_class, field)
end
def should_validate_email_format_of_klass(klass, field)
context 'Typical valid email' do
should_allow_values(klass,
'valid@example.com',
'Valid@test.example.com',
'valid+valid123@test.example.com',
'valid_valid123@test.example.com',
'valid-valid+123@test.example.co.uk',
'valid-valid+1.23@test.example.com.au',
'valid@example.co.uk',
'v@example.com',
'valid@example.ca',
'valid_@example.com',
'valid123.456@example.org',
'valid123.456@example.travel',
'valid123.456@example.museum',
'valid@example.mobi',
'valid@example.info',
'valid-@example.com')
end
context 'valid email from RFC 3696, page 6' do
should_allow_values(klass,
'customer/department=shipping@example.com',
'$A12345@example.com',
'!def!xyz%abc@example.com',
'_somename@example.com')
end
context 'valid email with apostrophe' do
should_allow_values(klass, "test'test@example.com")
end
context 'valid email from http://www.rfc-editor.org/errata_search.php?rfc=3696' do
should_allow_values(klass,
'"Abc\@def"@example.com',
'"Fred\ Bloggs"@example.com',
'"Joe.\\Blow"@example.com')
end
context 'Typical invalid email' do
should_not_allow_values(klass,
'invalid@example-com',
'invalid@example.com.',
'invalid@example.com_',
'invalid@example.com-',
'invalid-example.com',
'invalid@example.b#r.com',
'invalid@example.c',
'invali d@example.com',
'invalidexample.com',
'invalid@example.')
end
context 'invalid email with period starting local part' do
should_not_allow_values(klass,'.invalid@example.com')
end
context 'invalid email with period ending local part' do
should_not_allow_values(klass, 'invalid.@example.com')
end
context 'invalid email with consecutive periods' do
should_not_allow_values(klass, 'invali..d@example.com')
end
# corrected in http://www.rfc-editor.org/errata_search.php?rfc=3696
context 'invalid email from http://tools.ietf.org/html/rfc3696, page 5' do
should_not_allow_values(klass,
'Fred\ Bloggs_@example.com',
'Abc\@def+@example.com',
'Joe.\\Blow@example.com')
end
context 'invalid email exceeding length limits' do
should_not_allow_values(klass,
"#{'a' * 65}@example.com",
"test@#{'a'*252}.com")
end
end
end
end
Test::Unit::TestCase.extend(ValidatesEmailFormatOf::Shoulda)

View file

@ -0,0 +1,47 @@
$:.unshift(File.dirname(__FILE__) + '/../lib')
require 'rubygems'
require 'active_record'
require 'active_record/base'
require 'validates_email_format_of'
ActiveRecord::Base.establish_connection(
:adapter => 'sqlite3',
:database => ':memory:')
ActiveRecord::Schema.define(:version => 0) do
create_table :users, :force => true do |t|
t.column 'email', :string
end
end
class Person < ActiveRecord::Base
validates_email_format_of :email, :on => :create, :message => 'fails with custom message', :allow_nil => true
end
require 'test/unit'
require 'shoulda'
require "#{File.dirname(__FILE__)}/../init"
class Test::Unit::TestCase #:nodoc:
def self.should_allow_values(klass,*good_values)
good_values.each do |v|
should "allow email to be set to #{v.inspect}" do
user = klass.new(:email => v)
user.save
assert_nil user.errors.on(:email)
end
end
end
def self.should_not_allow_values(klass,*bad_values)
bad_values.each do |v|
should "not allow email to be set to #{v.inspect}" do
user = klass.new(:email => v)
assert !user.save, "Saved user with email set to \"#{v}\""
assert user.errors.on(:email), "There are no errors set on email after being set to \"#{v}\""
end
end
end
end

View file

@ -0,0 +1,37 @@
require File.dirname(__FILE__) + '/test_helper'
require File.dirname(__FILE__) + '/../shoulda_macros/validates_email_format_of'
class User < ActiveRecord::Base
validates_email_format_of :email,
:on => :create,
:message => 'fails with custom message',
:allow_nil => true
end
class ValidatesEmailFormatOfTest < Test::Unit::TestCase
should_validate_email_format_of_klass(User, :email)
context 'An invalid user on update' do
setup do
@user = User.new(:email => 'dcroak@thoughtbot.com')
assert @user.save
assert @user.update_attribute(:email, '..dcroak@thoughtbot.com')
end
should 'pass validation' do
assert @user.valid?
assert @user.save
assert_nil @user.errors.on(:email)
end
end
context 'A user with a nil email' do
setup { @user = User.new(:email => nil) }
should 'pass validation' do
assert @user.valid?
assert @user.save
assert_nil @user.errors.on(:email)
end
end
end

View file

@ -0,0 +1,32 @@
Gem::Specification.new do |s|
s.name = "validates_email_format_of"
s.version = "1.3.0"
s.date = "2009-06-08"
s.summary = "Validate e-mail addreses against RFC 2822 and RFC 3696."
s.email = "dcroak@thoughtbot.com"
s.description = "Validate e-mail addreses against RFC 2822 and RFC 3696."
s.authors = ["Alex Dunae", "Dan Croak", "Mike Burns"]
s.extra_rdoc_files = ["CHANGELOG",
"lib/validates_email_format_of.rb",
"README.markdown"]
s.files = ["CHANGELOG",
"init.rb",
"lib/validates_email_format_of.rb",
"MIT-LICENSE",
"rails/init.rb",
"Rakefile",
"README",
"test/database.yml",
"test/fixtures/people.yml",
"test/fixtures/person.rb",
"test/schema.rb",
"test/test_helper.rb",
"test/validates_email_format_of_test.rb",
"Rakefile",
"validates_email_format_of.gemspec"]
s.has_rdoc = true
s.homepage = %q{http://code.dunae.ca/validates_email_format_of.html}
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Validates_email_format_of"]
s.require_paths = ["lib"]
end