validates_email_format_of 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/CHANGELOG.rdoc ADDED
@@ -0,0 +1,33 @@
1
+ = CHANGELOG
2
+
3
+ == Version 1.4.1 (the George Anderson and 'history' edition)
4
+ * don't allow domains with underscores
5
+ * removed extra spaces in validation messages
6
+ * updated tests for Rails 2.3+
7
+
8
+ == Version 1.4 (the Denis Ahearn edition)
9
+ * added ability to run validation tests without touching ActiveRecord or a database
10
+
11
+ == Version 1.3.1 (the Github edition)
12
+ * updated for github
13
+
14
+ == Version 1.3 (the Travis Sinnott edition)
15
+ * added optional MX record check
16
+ * now available as a gem
17
+
18
+ == Version 1.2.1 (the RTFM edition)
19
+ * added support for quoted local parts
20
+ * added length checks for domain and local parts
21
+ * corrected escaped character support for RFC 3696 Errata
22
+ * added :allow_blank option
23
+ * added :unless option
24
+
25
+ == Version 1.2 (the Ismael Santos Kafeltz and Michael MacDonald edition)
26
+ * added support for un-escaped and escaped special characters in the local part, per RFC 3696
27
+ * added :allow_nil option
28
+
29
+ == Version 1.1 (the Francis Hwang edition)
30
+ * moved Regexp out of class methods into the ValidatesEmailFormatOf module
31
+
32
+ == Version 1.0
33
+ * initial version
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2006-09 Alex Dunae
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,77 @@
1
+ = validates_email_format_of Gem and Rails Plugin
2
+
3
+ Validate e-mail addresses against RFC 2822 and RFC 3696.
4
+
5
+ == Installation
6
+
7
+ Installing as a gem:
8
+
9
+ gem sources -a http://gems.github.com
10
+ gem install alexdunae-validates_email_format_of
11
+
12
+ Installing as a Ruby on Rails plugin:
13
+
14
+ ./script/plugin install http://github.com/alexdunae/validates_email_format_of.git
15
+
16
+
17
+ == Usage
18
+
19
+ class Person < ActiveRecord::Base
20
+ validates_email_format_of :email
21
+ end
22
+
23
+ As of version 1.4, it's possible to run e-mail validation tests (including MX
24
+ checks) without using ActiveRecord or even touching a database. The
25
+ <tt>validate_email_format</tt> method will return <tt>nil</tt> on a valid
26
+ e-mail address or an array of error messages for invalid addresses.
27
+
28
+ results = ValidatesEmailFormatOf::validate_email_format(email, options)
29
+
30
+ if results.nil?
31
+ # success!
32
+ else
33
+ puts results.join(', ')
34
+ end
35
+
36
+
37
+ === Options
38
+
39
+ :message
40
+ String. A custom error message (default is: " does not appear to be a valid e-mail address")
41
+ :on
42
+ Symbol. Specifies when this validation is active (default is :save, other options :create, :update)
43
+ :allow_nil
44
+ Boolean. Allow nil values (default is false)
45
+ :allow_blank
46
+ Boolean. Allow blank values (default is false)
47
+ :check_mx
48
+ Boolean. Check domain for a valid MX record (default is false)
49
+ :if
50
+ Specifies a method, proc or string to call to determine if the validation should occur
51
+ (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }). The method,
52
+ proc or string should return or evaluate to a true or false value.
53
+ :unless
54
+ See :if option.
55
+
56
+ == Testing
57
+
58
+ To execute the unit tests run <tt>rake test</tt>.
59
+
60
+ The unit tests for this plugin use an in-memory sqlite3 database.
61
+
62
+ == Resources
63
+
64
+ * http://github.com/alexdunae/validates_email_format_of
65
+ * http://code.dunae.ca/validates_email_format_of.html
66
+
67
+ == Credits
68
+
69
+ Written by Alex Dunae (dunae.ca), 2006-09.
70
+
71
+ Thanks to Francis Hwang (http://fhwang.net/) at Diversion Media for creating the 1.1 update.
72
+
73
+ Thanks to Travis Sinnott for creating the 1.3 update.
74
+
75
+ Thanks to Denis Ahearn at Riverock Technologies (http://www.riverocktech.com/) for creating the 1.4 update.
76
+
77
+ Thanks to George Anderson (http://github.com/george) and 'history' (http://github.com/history) for creating the 1.4.1 update.
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require File.dirname(__FILE__) + '/rails/init'
@@ -0,0 +1,88 @@
1
+ module ValidatesEmailFormatOf
2
+ require 'resolv'
3
+
4
+ LocalPartSpecialChars = Regexp.escape('!#$%&\'*-/=?+-^_`{|}~')
5
+ LocalPartUnquoted = '(([[:alnum:]' + LocalPartSpecialChars + ']+[\.\+]+))*[[:alnum:]' + LocalPartSpecialChars + '+]+'
6
+ LocalPartQuoted = '\"(([[:alnum:]' + LocalPartSpecialChars + '\.\+]*|(\\\\[\x00-\xFF]))*)\"'
7
+ Regex = Regexp.new('^((' + LocalPartUnquoted + ')|(' + LocalPartQuoted + ')+)@(((\w+\-+[^_])|(\w+\.[^_]))*([a-z0-9-]{1,63})\.[a-z]{2,6}$)', Regexp::EXTENDED | Regexp::IGNORECASE)
8
+
9
+ def self.validate_email_domain(email)
10
+ domain = email.match(/\@(.+)/)[1]
11
+ Resolv::DNS.open do |dns|
12
+ @mx = dns.getresources(domain, Resolv::DNS::Resource::IN::MX)
13
+ end
14
+ @mx.size > 0 ? true : false
15
+ end
16
+
17
+ # Validates whether the specified value is a valid email address. Returns nil if the value is valid, otherwise returns an array
18
+ # containing one or more validation error messages.
19
+ #
20
+ # Configuration options:
21
+ # * <tt>message</tt> - A custom error message (default is: "does not appear to be a valid e-mail address")
22
+ # * <tt>check_mx</tt> - Check for MX records (default is false)
23
+ # * <tt>mx_message</tt> - A custom error message when an MX record validation fails (default is: "is not routable.")
24
+ # * <tt>with</tt> The regex to use for validating the format of the email address (default is ValidatesEmailFormatOf::Regex)</tt>
25
+ def self.validate_email_format(email, options={})
26
+ default_options = { :message => 'does not appear to be a valid e-mail address',
27
+ :check_mx => false,
28
+ :mx_message => 'is not routable.',
29
+ :with => ValidatesEmailFormatOf::Regex }
30
+ options.merge!(default_options) {|key, old, new| old} # merge the default options into the specified options, retaining all specified options
31
+
32
+ # local part max is 64 chars, domain part max is 255 chars
33
+ # TODO: should this decode escaped entities before counting?
34
+ begin
35
+ domain, local = email.reverse.split('@', 2)
36
+ rescue
37
+ return [ options[:message] ]
38
+ end
39
+
40
+ unless email =~ options[:with] and not email =~ /\.\./ and domain.length <= 255 and local.length <= 64
41
+ return [ options[:message] ]
42
+ end
43
+
44
+ if options[:check_mx] and !ValidatesEmailFormatOf::validate_email_domain(email)
45
+ return [ options[:mx_message] ]
46
+ end
47
+
48
+ return nil # represents no validation errors
49
+ end
50
+ end
51
+
52
+ module ActiveRecord
53
+ module Validations
54
+ module ClassMethods
55
+ # Validates whether the value of the specified attribute is a valid email address
56
+ #
57
+ # class User < ActiveRecord::Base
58
+ # validates_email_format_of :email, :on => :create
59
+ # end
60
+ #
61
+ # Configuration options:
62
+ # * <tt>message</tt> - A custom error message (default is: "does not appear to be a valid e-mail address")
63
+ # * <tt>on</tt> - Specifies when this validation is active (default is :save, other options :create, :update)
64
+ # * <tt>allow_nil</tt> - Allow nil values (default is false)
65
+ # * <tt>allow_blank</tt> - Allow blank values (default is false)
66
+ # * <tt>check_mx</tt> - Check for MX records (default is false)
67
+ # * <tt>mx_message</tt> - A custom error message when an MX record validation fails (default is: "is not routable.")
68
+ # * <tt>if</tt> - Specifies a method, proc or string to call to determine if the validation should
69
+ # occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }). The
70
+ # method, proc or string should return or evaluate to a true or false value.
71
+ # * <tt>unless</tt> - See <tt>:if</tt>
72
+ def validates_email_format_of(*attr_names)
73
+ options = { :on => :save,
74
+ :allow_nil => false,
75
+ :allow_blank => false }
76
+ options.update(attr_names.pop) if attr_names.last.is_a?(Hash)
77
+
78
+ validates_each(attr_names, options) do |record, attr_name, value|
79
+ v = value.to_s
80
+ errors = ValidatesEmailFormatOf::validate_email_format(v, options)
81
+ errors.each do |error|
82
+ record.errors.add(attr_name, error)
83
+ end unless errors.nil?
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
data/rails/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'validates_email_format_of'
data/rakefile.rb ADDED
@@ -0,0 +1,28 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+
5
+ desc 'Default: run unit tests.'
6
+ task :default => [:clean_log, :test]
7
+
8
+ desc 'Remove the old log file'
9
+ task :clean_log do
10
+ "rm -f #{File.dirname(__FILE__)}/test/debug.log" if File.exists?(File.dirname(__FILE__) + '/test/debug.log')
11
+ end
12
+
13
+ desc 'Test the validates_email_format_of plugin.'
14
+ Rake::TestTask.new(:test) do |t|
15
+ t.libs << 'lib'
16
+ t.pattern = 'test/**/*_test.rb'
17
+ t.verbose = true
18
+ end
19
+
20
+ desc 'Generate documentation for the validates_email_format_of plugin.'
21
+ Rake::RDocTask.new(:rdoc) do |rdoc|
22
+ rdoc.rdoc_dir = 'rdoc'
23
+ rdoc.title = 'validates_email_format_of plugin'
24
+ rdoc.options << '--line-numbers --inline-source'
25
+ rdoc.rdoc_files.include('README')
26
+ rdoc.rdoc_files.include('TODO')
27
+ rdoc.rdoc_files.include('lib/**/*.rb')
28
+ end
@@ -0,0 +1,3 @@
1
+ existing:
2
+ id: 1
3
+ email: test@example.com
@@ -0,0 +1,12 @@
1
+ class Person < ActiveRecord::Base
2
+ validates_email_format_of :email,
3
+ :on => :create,
4
+ :message => 'fails with custom message',
5
+ :allow_nil => true
6
+ end
7
+
8
+ class MxRecord < ActiveRecord::Base
9
+ validates_email_format_of :email,
10
+ :on => :create,
11
+ :check_mx => true
12
+ end
data/test/schema.rb ADDED
@@ -0,0 +1,10 @@
1
+ ActiveRecord::Schema.define(:version => 0) do
2
+ create_table :people, :force => true do |t|
3
+ t.column "email", :string
4
+ end
5
+
6
+ create_table :mx_records, :force => true do |t|
7
+ t.column "email", :string
8
+ end
9
+
10
+ end
@@ -0,0 +1,40 @@
1
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
2
+ RAILS_ROOT = File.dirname(__FILE__)
3
+
4
+ require 'rubygems'
5
+ require 'test/unit'
6
+ require 'active_record'
7
+ require 'active_record/fixtures'
8
+ require "#{File.dirname(__FILE__)}/../init"
9
+
10
+
11
+ config = YAML::load(IO.read(File.dirname(__FILE__) + '/database.yml'))
12
+ ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + "/debug.log")
13
+ ActiveRecord::Base.establish_connection(config[ENV['DB'] || 'plugin_test'])
14
+
15
+ load(File.dirname(__FILE__) + "/schema.rb") if File.exist?(File.dirname(__FILE__) + "/schema.rb")
16
+
17
+ if ActiveSupport.const_defined?(:TestCase)
18
+ ActiveSupport::TestCase.send(:include, ActiveRecord::TestFixtures)
19
+ TEST_CASE = ActiveSupport::TestCase
20
+ else
21
+ TEST_CASE = Test::Unit::TestCase
22
+ end
23
+
24
+ TEST_CASE.fixture_path = File.dirname(__FILE__) + "/fixtures/"
25
+ $LOAD_PATH.unshift(TEST_CASE.fixture_path)
26
+
27
+ class TEST_CASE #:nodoc:
28
+ def create_fixtures(*table_names)
29
+ if block_given?
30
+ Fixtures.create_fixtures(TEST_CASE.fixture_path, table_names) { yield }
31
+ else
32
+ Fixtures.create_fixtures(TEST_CASE.fixture_path, table_names)
33
+ end
34
+ end
35
+
36
+ self.use_transactional_fixtures = false
37
+
38
+ self.use_instantiated_fixtures = false
39
+ end
40
+
@@ -0,0 +1,147 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class ValidatesEmailFormatOfTest < TEST_CASE
4
+ fixtures :people, :peoplemx
5
+
6
+ def setup
7
+ @valid_email = 'valid@example.com'
8
+ @invalid_email = 'invalid@example.'
9
+ end
10
+
11
+ def test_without_activerecord
12
+ assert_nil ValidatesEmailFormatOf::validate_email_format('valid@example.com')
13
+ err = ValidatesEmailFormatOf::validate_email_format('valid@example-com')
14
+ assert_equal 1, err.size
15
+ end
16
+
17
+ def test_should_allow_valid_email_addresses
18
+ ['valid@example.com',
19
+ 'Valid@test.example.com',
20
+ 'valid+valid123@test.example.com',
21
+ 'valid_valid123@test.example.com',
22
+ 'valid-valid+123@test.example.co.uk',
23
+ 'valid-valid+1.23@test.example.com.au',
24
+ 'valid@example.co.uk',
25
+ 'v@example.com',
26
+ 'valid@example.ca',
27
+ 'valid_@example.com',
28
+ 'valid123.456@example.org',
29
+ 'valid123.456@example.travel',
30
+ 'valid123.456@example.museum',
31
+ 'valid@example.mobi',
32
+ 'valid@example.info',
33
+ 'valid-@example.com',
34
+ # from RFC 3696, page 6
35
+ 'customer/department=shipping@example.com',
36
+ '$A12345@example.com',
37
+ '!def!xyz%abc@example.com',
38
+ '_somename@example.com',
39
+ # apostrophes
40
+ "test'test@example.com",
41
+ ].each do |email|
42
+ p = create_person(:email => email)
43
+ save_passes(p, email)
44
+ end
45
+ end
46
+
47
+ def test_should_not_allow_invalid_email_addresses
48
+ ['invalid@example-com',
49
+ # period can not start local part
50
+ '.invalid@example.com',
51
+ # period can not end local part
52
+ 'invalid.@example.com',
53
+ # period can not appear twice consecutively in local part
54
+ 'invali..d@example.com',
55
+ # should not allow underscores in domain names
56
+ 'invalid@ex_mple.com',
57
+ 'invalid@example.com.',
58
+ 'invalid@example.com_',
59
+ 'invalid@example.com-',
60
+ 'invalid-example.com',
61
+ 'invalid@example.b#r.com',
62
+ 'invalid@example.c',
63
+ 'invali d@example.com',
64
+ 'invalidexample.com',
65
+ 'invalid@example.'].each do |email|
66
+ p = create_person(:email => email)
67
+ save_fails(p, email)
68
+ end
69
+ end
70
+
71
+ # from http://www.rfc-editor.org/errata_search.php?rfc=3696
72
+ def test_should_allow_quoted_characters
73
+ ['"Abc\@def"@example.com',
74
+ '"Fred\ Bloggs"@example.com',
75
+ '"Joe.\\Blow"@example.com',
76
+ ].each do |email|
77
+ p = create_person(:email => email)
78
+ save_passes(p, email)
79
+ end
80
+ end
81
+
82
+ # from http://tools.ietf.org/html/rfc3696, page 5
83
+ # corrected in http://www.rfc-editor.org/errata_search.php?rfc=3696
84
+ def test_should_not_allow_escaped_characters_without_quotes
85
+ ['Fred\ Bloggs_@example.com',
86
+ 'Abc\@def+@example.com',
87
+ 'Joe.\\Blow@example.com'
88
+ ].each do |email|
89
+ p = create_person(:email => email)
90
+ save_fails(p, email)
91
+ end
92
+ end
93
+
94
+ def test_should_check_length_limits
95
+ ['aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@example.com',
96
+ 'test@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com'
97
+ ].each do |email|
98
+ p = create_person(:email => email)
99
+ save_fails(p, email)
100
+ end
101
+ end
102
+
103
+ def test_should_respect_validate_on_option
104
+ p = create_person(:email => @valid_email)
105
+ save_passes(p)
106
+
107
+ # we only asked to validate on :create so this should fail
108
+ assert p.update_attributes(:email => @invalid_email)
109
+ assert_equal @invalid_email, p.email
110
+ end
111
+
112
+ def test_should_allow_custom_error_message
113
+ p = create_person(:email => @invalid_email)
114
+ save_fails(p)
115
+ assert_equal 'fails with custom message', p.errors.on(:email)
116
+ end
117
+
118
+ def test_should_allow_nil
119
+ p = create_person(:email => nil)
120
+ save_passes(p)
121
+ end
122
+
123
+ def test_check_mx
124
+ pmx = MxRecord.new(:email => 'test@dunae.ca')
125
+ save_passes(pmx)
126
+
127
+ pmx = MxRecord.new(:email => 'test@example.com')
128
+ save_fails(pmx)
129
+ end
130
+
131
+ protected
132
+ def create_person(params)
133
+ Person.new(params)
134
+ end
135
+
136
+ def save_passes(p, email = '')
137
+ assert p.valid?, " validating #{email}"
138
+ assert p.save
139
+ assert_nil p.errors.on(:email)
140
+ end
141
+
142
+ def save_fails(p, email = '')
143
+ assert !p.valid?, " validating #{email}"
144
+ assert !p.save
145
+ assert p.errors.on(:email)
146
+ end
147
+ end
metadata ADDED
@@ -0,0 +1,68 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: validates_email_format_of
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.4.1
5
+ platform: ruby
6
+ authors:
7
+ - Alex Dunae
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-11-26 00:00:00 +01:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Validate e-mail addresses against RFC 2822 and RFC 3696.
17
+ email: code@dunae.ca
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README.rdoc
24
+ - CHANGELOG.rdoc
25
+ - MIT-LICENSE
26
+ files:
27
+ - init.rb
28
+ - rakefile.rb
29
+ - lib/validates_email_format_of.rb
30
+ - rails/init.rb
31
+ - README.rdoc
32
+ - CHANGELOG.rdoc
33
+ - MIT-LICENSE
34
+ has_rdoc: true
35
+ homepage: http://code.dunae.ca/validates_email_format_of.html
36
+ licenses: []
37
+
38
+ post_install_message:
39
+ rdoc_options:
40
+ - --title
41
+ - validates_email_format_of
42
+ require_paths:
43
+ - lib
44
+ required_ruby_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: "0"
49
+ version:
50
+ required_rubygems_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: "0"
55
+ version:
56
+ requirements: []
57
+
58
+ rubyforge_project:
59
+ rubygems_version: 1.3.5
60
+ signing_key:
61
+ specification_version: 3
62
+ summary: Validate e-mail addresses against RFC 2822 and RFC 3696.
63
+ test_files:
64
+ - test/validates_email_format_of_test.rb
65
+ - test/test_helper.rb
66
+ - test/schema.rb
67
+ - test/fixtures/person.rb
68
+ - test/fixtures/people.yml