validates_email_format_of 1.4.5 → 1.4.6

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/README.rdoc CHANGED
@@ -23,6 +23,11 @@ Or in your Rails 3 Gemfile
23
23
  validates_email_format_of :email
24
24
  end
25
25
 
26
+ # Rails 3
27
+ class Person < ActiveRecord::Base
28
+ validates :email, :email_format => {:message => 'is not looking good'}
29
+ end
30
+
26
31
  As of version 1.4, it's possible to run e-mail validation tests (including MX
27
32
  checks) without using ActiveRecord or even touching a database. The
28
33
  <tt>validate_email_format</tt> method will return <tt>nil</tt> on a valid
@@ -1,11 +1,13 @@
1
1
  # encoding: utf-8
2
2
  module ValidatesEmailFormatOf
3
3
  require 'resolv'
4
-
4
+
5
+ MessageScope = defined?(ActiveModel) ? :activemodel : :activerecord
6
+
5
7
  LocalPartSpecialChars = Regexp.escape('!#$%&\'*-/=?+-^_`{|}~')
6
8
  LocalPartUnquoted = '([[:alnum:]' + LocalPartSpecialChars + ']+[\.]+)*[[:alnum:]' + LocalPartSpecialChars + '+]+'
7
9
  LocalPartQuoted = '\"([[:alnum:]' + LocalPartSpecialChars + '\.]|\\\\[\x00-\xFF])*\"'
8
- Regex = Regexp.new('\A(' + LocalPartUnquoted + '|' + LocalPartQuoted + '+)@(((\w+\-+[^_])|(\w+\.[a-z0-9-]*))*([a-z0-9-]{1,63})\.[a-z]{2,6}(?:\.[a-z]{2,6})?\Z)', Regexp::EXTENDED | Regexp::IGNORECASE, 'n')
10
+ Regex = Regexp.new('\A(' + LocalPartUnquoted + '|' + LocalPartQuoted + '+)@(((\w+\-+[^_])|(\w+\.[a-z0-9-]*))*([a-z0-9\-\.]{1,63})\.[a-z]{2,6}(?:\.[a-z]{2,6})?\Z)', Regexp::EXTENDED | Regexp::IGNORECASE, 'n')
9
11
 
10
12
  def self.validate_email_domain(email)
11
13
  domain = email.match(/\@(.+)/)[1]
@@ -14,26 +16,26 @@ module ValidatesEmailFormatOf
14
16
  end
15
17
  @mx.size > 0 ? true : false
16
18
  end
17
-
19
+
18
20
  # Validates whether the specified value is a valid email address. Returns nil if the value is valid, otherwise returns an array
19
21
  # containing one or more validation error messages.
20
22
  #
21
23
  # Configuration options:
22
- # * <tt>message</tt> - A custom error message (default is: "does not appear to be a valid e-mail address")
24
+ # * <tt>message</tt> - A custom error message (default is: "does not appear to be valid")
23
25
  # * <tt>check_mx</tt> - Check for MX records (default is false)
24
26
  # * <tt>mx_message</tt> - A custom error message when an MX record validation fails (default is: "is not routable.")
25
27
  # * <tt>with</tt> The regex to use for validating the format of the email address (default is ValidatesEmailFormatOf::Regex)</tt>
26
28
  # * <tt>local_length</tt> Maximum number of characters allowed in the local part (default is 64)
27
29
  # * <tt>domain_length</tt> Maximum number of characters allowed in the domain part (default is 255)
28
30
  def self.validate_email_format(email, options={})
29
- default_options = { :message => I18n.t(:invalid_email_address, :scope => [:activerecord, :errors, :messages], :default => 'does not appear to be a valid e-mail address'),
31
+ default_options = { :message => I18n.t(:invalid_email_address, :scope => [MessageScope, :errors, :messages], :default => 'does not appear to be valid'),
30
32
  :check_mx => false,
31
- :mx_message => I18n.t(:email_address_not_routable, :scope => [:activerecord, :errors, :messages], :default => 'is not routable'),
33
+ :mx_message => I18n.t(:email_address_not_routable, :scope => [MessageScope, :errors, :messages], :default => 'is not routable'),
32
34
  :with => ValidatesEmailFormatOf::Regex ,
33
35
  :domain_length => 255,
34
36
  :local_length => 64
35
37
  }
36
- options.merge!(default_options) {|key, old, new| old} # merge the default options into the specified options, retaining all specified options
38
+ opts = options.merge(default_options) {|key, old, new| old} # merge the default options into the specified options, retaining all specified options
37
39
 
38
40
  email.strip!
39
41
 
@@ -42,55 +44,92 @@ module ValidatesEmailFormatOf
42
44
  begin
43
45
  domain, local = email.reverse.split('@', 2)
44
46
  rescue
45
- return [ options[:message] ]
47
+ return [ opts[:message] ]
46
48
  end
47
49
 
48
- unless email =~ options[:with] and not email =~ /\.\./ and domain.length <= options[:domain_length] and local.length <= options[:local_length]
49
- return [ options[:message] ]
50
+ unless email =~ opts[:with] and not email =~ /\.\./ and domain.length <= opts[:domain_length] and local.length <= opts[:local_length]
51
+ return [ opts[:message] ]
50
52
  end
51
-
52
- if options[:check_mx] and !ValidatesEmailFormatOf::validate_email_domain(email)
53
- return [ options[:mx_message] ]
53
+
54
+ if opts[:check_mx] and !ValidatesEmailFormatOf::validate_email_domain(email)
55
+ return [ opts[:mx_message] ]
56
+ end
57
+
58
+ local.reverse!
59
+
60
+ # check for proper escaping
61
+
62
+ if local[0] == '"'
63
+ local.gsub!(/\A\"|\"\Z/, '')
64
+ escaped = false
65
+ local.each_char do |c|
66
+ if escaped
67
+ escaped = false
68
+ elsif c == '"' # can't have a double quote without a preceding backslash
69
+ return [ opts[:mx_message] ]
70
+ else
71
+ escaped = c == '\\'
72
+ end
73
+ end
74
+
75
+ return [ opts[:mx_message] ] if escaped
54
76
  end
55
-
77
+
56
78
  return nil # represents no validation errors
57
79
  end
58
- end
59
80
 
60
- module ActiveRecord
61
81
  module Validations
62
- module ClassMethods
63
- # Validates whether the value of the specified attribute is a valid email address
64
- #
65
- # class User < ActiveRecord::Base
66
- # validates_email_format_of :email, :on => :create
67
- # end
68
- #
69
- # Configuration options:
70
- # * <tt>message</tt> - A custom error message (default is: "does not appear to be a valid e-mail address")
71
- # * <tt>on</tt> - Specifies when this validation is active (default is :save, other options :create, :update)
72
- # * <tt>allow_nil</tt> - Allow nil values (default is false)
73
- # * <tt>allow_blank</tt> - Allow blank values (default is false)
74
- # * <tt>check_mx</tt> - Check for MX records (default is false)
75
- # * <tt>mx_message</tt> - A custom error message when an MX record validation fails (default is: "is not routable.")
76
- # * <tt>if</tt> - Specifies a method, proc or string to call to determine if the validation should
77
- # occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }). The
78
- # method, proc or string should return or evaluate to a true or false value.
79
- # * <tt>unless</tt> - See <tt>:if</tt>
80
- def validates_email_format_of(*attr_names)
81
- options = { :on => :save,
82
- :allow_nil => false,
83
- :allow_blank => false }
84
- options.update(attr_names.pop) if attr_names.last.is_a?(Hash)
85
-
86
- validates_each(attr_names, options) do |record, attr_name, value|
87
- v = value.to_s
88
- errors = ValidatesEmailFormatOf::validate_email_format(v, options)
89
- errors.each do |error|
90
- record.errors.add(attr_name, error)
91
- end unless errors.nil?
92
- end
82
+ # Validates whether the value of the specified attribute is a valid email address
83
+ #
84
+ # class User < ActiveRecord::Base
85
+ # validates_email_format_of :email, :on => :create
86
+ # end
87
+ #
88
+ # Configuration options:
89
+ # * <tt>message</tt> - A custom error message (default is: "does not appear to be valid")
90
+ # * <tt>on</tt> - Specifies when this validation is active (default is :save, other options :create, :update)
91
+ # * <tt>allow_nil</tt> - Allow nil values (default is false)
92
+ # * <tt>allow_blank</tt> - Allow blank values (default is false)
93
+ # * <tt>check_mx</tt> - Check for MX records (default is false)
94
+ # * <tt>mx_message</tt> - A custom error message when an MX record validation fails (default is: "is not routable.")
95
+ # * <tt>if</tt> - Specifies a method, proc or string to call to determine if the validation should
96
+ # occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }). The
97
+ # method, proc or string should return or evaluate to a true or false value.
98
+ # * <tt>unless</tt> - See <tt>:if</tt>
99
+ def validates_email_format_of(*attr_names)
100
+ options = { :on => :save,
101
+ :allow_nil => false,
102
+ :allow_blank => false }
103
+ options.update(attr_names.pop) if attr_names.last.is_a?(Hash)
104
+
105
+ validates_each(attr_names, options) do |record, attr_name, value|
106
+ v = value.to_s
107
+ errors = ValidatesEmailFormatOf::validate_email_format(v, options)
108
+ errors.each do |error|
109
+ record.errors.add(attr_name, error)
110
+ end unless errors.nil?
93
111
  end
94
- end
112
+ end
113
+ end
114
+ end
115
+
116
+ if defined?(ActiveModel)
117
+ class EmailFormatValidator < ActiveModel::EachValidator
118
+ def validate_each(record, attribute, value)
119
+ err = ValidatesEmailFormatOf::validate_email_format(value, options)
120
+ record.errors[attribute] << err unless err.nil?
121
+ record.errors[attribute].flatten!
122
+ end
95
123
  end
96
- end
124
+
125
+ module ActiveModel::Validations::HelperMethods
126
+ def validates_email_format_of(*attr_names)
127
+ validates_with EmailFormatValidator, _merge_attributes(attr_names)
128
+ end
129
+ end
130
+ else
131
+ class ActiveRecord::Base
132
+ extend ValidatesEmailFormatOf::Validations
133
+ end
134
+ end
135
+
data/rakefile.rb CHANGED
@@ -17,12 +17,11 @@ Rake::TestTask.new(:test) do |t|
17
17
  t.verbose = true
18
18
  end
19
19
 
20
- desc 'Generate documentation for the validates_email_format_of plugin.'
20
+ desc 'Generate documentation for the validates_email_format_of plugin and gem.'
21
21
  Rake::RDocTask.new(:rdoc) do |rdoc|
22
22
  rdoc.rdoc_dir = 'rdoc'
23
- rdoc.title = 'validates_email_format_of plugin'
23
+ rdoc.title = 'validates_email_format_of plugin and gem'
24
24
  rdoc.options << '--line-numbers --inline-source'
25
- rdoc.rdoc_files.include('README')
26
- rdoc.rdoc_files.include('TODO')
25
+ rdoc.rdoc_files.include('README.rdoc')
27
26
  rdoc.rdoc_files.include('lib/**/*.rb')
28
27
  end
@@ -6,7 +6,19 @@ class Person < ActiveRecord::Base
6
6
  end
7
7
 
8
8
  class MxRecord < ActiveRecord::Base
9
+ set_table_name 'people'
10
+
9
11
  validates_email_format_of :email,
10
12
  :on => :create,
11
13
  :check_mx => true
12
14
  end
15
+
16
+ if ActiveRecord::VERSION::MAJOR >= 3
17
+ class Shorthand < ActiveRecord::Base
18
+ set_table_name 'people'
19
+
20
+ validates :email, :email_format => { :message => 'fails with shorthand message' },
21
+ :length => { :maximum => 1 }
22
+
23
+ end
24
+ end
data/test/schema.rb CHANGED
@@ -2,9 +2,4 @@ ActiveRecord::Schema.define(:version => 0) do
2
2
  create_table :people, :force => true do |t|
3
3
  t.column "email", :string
4
4
  end
5
-
6
- create_table :mx_records, :force => true do |t|
7
- t.column "email", :string
8
- end
9
-
10
5
  end
@@ -8,10 +8,17 @@ class ValidatesEmailFormatOfTest < TEST_CASE
8
8
  @invalid_email = 'invalid@example.'
9
9
  end
10
10
 
11
+ def test_with_activerecord
12
+ p = create_person(:email => @valid_email)
13
+ save_passes(p)
14
+
15
+ p = create_person(:email => @invalid_email)
16
+ save_fails(p)
17
+ end
18
+
11
19
  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
20
+ assert_valid(@valid_email)
21
+ assert_invalid(@invalid_email)
15
22
  end
16
23
 
17
24
  def test_should_allow_valid_email_addresses
@@ -31,6 +38,7 @@ class ValidatesEmailFormatOfTest < TEST_CASE
31
38
  'valid@example.mobi',
32
39
  'valid@example.info',
33
40
  'valid-@example.com',
41
+ 'fake@p-t.k12.ok.us',
34
42
  # allow single character domain parts
35
43
  'valid@mail.x.example.com',
36
44
  'valid@x.com',
@@ -43,8 +51,7 @@ class ValidatesEmailFormatOfTest < TEST_CASE
43
51
  # apostrophes
44
52
  "test'test@example.com",
45
53
  ].each do |email|
46
- p = create_person(:email => email)
47
- save_passes(p, email)
54
+ assert_valid(email)
48
55
  end
49
56
  end
50
57
 
@@ -58,6 +65,8 @@ class ValidatesEmailFormatOfTest < TEST_CASE
58
65
  'invali..d@example.com',
59
66
  # should not allow underscores in domain names
60
67
  'invalid@ex_mple.com',
68
+ 'invalid@e..example.com',
69
+ 'invalid@p-t..example.com',
61
70
  'invalid@example.com.',
62
71
  'invalid@example.com_',
63
72
  'invalid@example.com-',
@@ -76,22 +85,26 @@ class ValidatesEmailFormatOfTest < TEST_CASE
76
85
  # one at a time
77
86
  "foo@example.com\nexample@gmail.com",
78
87
  'invalid@example.'].each do |email|
79
- p = create_person(:email => email)
80
- save_fails(p, email)
88
+ assert_invalid(email)
81
89
  end
82
90
  end
83
-
91
+
84
92
  # from http://www.rfc-editor.org/errata_search.php?rfc=3696
85
93
  def test_should_allow_quoted_characters
86
94
  ['"Abc\@def"@example.com',
87
95
  '"Fred\ Bloggs"@example.com',
88
96
  '"Joe.\\Blow"@example.com',
89
97
  ].each do |email|
90
- p = create_person(:email => email)
91
- save_passes(p, email)
98
+ assert_valid(email)
92
99
  end
93
100
  end
94
101
 
102
+ def test_should_required_balanced_quoted_characters
103
+ assert_valid(%!"example\\\\\\""@example.com!)
104
+ assert_valid(%!"example\\\\"@example.com!)
105
+ assert_invalid(%!"example\\\\""example.com!)
106
+ end
107
+
95
108
  # from http://tools.ietf.org/html/rfc3696, page 5
96
109
  # corrected in http://www.rfc-editor.org/errata_search.php?rfc=3696
97
110
  def test_should_not_allow_escaped_characters_without_quotes
@@ -99,8 +112,7 @@ class ValidatesEmailFormatOfTest < TEST_CASE
99
112
  'Abc\@def+@example.com',
100
113
  'Joe.\\Blow@example.com'
101
114
  ].each do |email|
102
- p = create_person(:email => email)
103
- save_fails(p, email)
115
+ assert_invalid(email)
104
116
  end
105
117
  end
106
118
 
@@ -108,8 +120,7 @@ class ValidatesEmailFormatOfTest < TEST_CASE
108
120
  ['aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@example.com',
109
121
  'test@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com'
110
122
  ].each do |email|
111
- p = create_person(:email => email)
112
- save_fails(p, email)
123
+ assert_invalid(email)
113
124
  end
114
125
  end
115
126
 
@@ -156,14 +167,36 @@ class ValidatesEmailFormatOfTest < TEST_CASE
156
167
  pmx = MxRecord.new(:email => 'test@code.dunae.ca')
157
168
  save_passes(pmx)
158
169
  end
170
+
171
+ def test_shorthand
172
+ if ActiveRecord::VERSION::MAJOR >= 3
173
+ s = Shorthand.new(:email => 'invalid')
174
+ assert !s.save
175
+ assert_equal 2, s.errors[:email].size
176
+ assert_block do
177
+ s.errors[:email].any? do |err|
178
+ err =~ /fails with shorthand message/
179
+ end
180
+ end
181
+ end
182
+ end
159
183
 
160
184
  protected
161
185
  def create_person(params)
162
186
  Person.new(params)
163
187
  end
188
+
189
+ def assert_valid(email)
190
+ assert_nil ValidatesEmailFormatOf::validate_email_format(email)
191
+ end
192
+
193
+ def assert_invalid(email)
194
+ err = ValidatesEmailFormatOf::validate_email_format(email)
195
+ assert_equal 1, err.size
196
+ end
164
197
 
165
198
  def save_passes(p, email = '')
166
- assert p.valid?, " validating #{email}"
199
+ assert p.valid?, " #{email} should pass"
167
200
  assert p.save
168
201
  if ActiveRecord::VERSION::MAJOR >= 3
169
202
  assert p.errors[:email].empty?
@@ -173,7 +206,7 @@ class ValidatesEmailFormatOfTest < TEST_CASE
173
206
  end
174
207
 
175
208
  def save_fails(p, email = '')
176
- assert !p.valid?, " validating #{email}"
209
+ assert !p.valid?, " #{email} should fail"
177
210
  assert !p.save
178
211
  if ActiveRecord::VERSION::MAJOR >= 3
179
212
  assert_equal 1, p.errors[:email].size
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: validates_email_format_of
3
3
  version: !ruby/object:Gem::Version
4
+ hash: 11
4
5
  prerelease: false
5
6
  segments:
6
7
  - 1
7
8
  - 4
8
- - 5
9
- version: 1.4.5
9
+ - 6
10
+ version: 1.4.6
10
11
  platform: ruby
11
12
  authors:
12
13
  - Alex Dunae
@@ -14,7 +15,7 @@ autorequire:
14
15
  bindir: bin
15
16
  cert_chain: []
16
17
 
17
- date: 2011-01-20 00:00:00 -08:00
18
+ date: 2011-05-02 00:00:00 -07:00
18
19
  default_executable:
19
20
  dependencies: []
20
21
 
@@ -26,13 +27,11 @@ extensions: []
26
27
 
27
28
  extra_rdoc_files:
28
29
  - README.rdoc
29
- - CHANGELOG.rdoc
30
30
  - MIT-LICENSE
31
31
  files:
32
32
  - MIT-LICENSE
33
33
  - init.rb
34
34
  - rakefile.rb
35
- - CHANGELOG.rdoc
36
35
  - README.rdoc
37
36
  - lib/validates_email_format_of.rb
38
37
  - test/fixtures/person.rb
@@ -56,6 +55,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
56
55
  requirements:
57
56
  - - ">="
58
57
  - !ruby/object:Gem::Version
58
+ hash: 3
59
59
  segments:
60
60
  - 0
61
61
  version: "0"
@@ -64,6 +64,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
64
64
  requirements:
65
65
  - - ">="
66
66
  - !ruby/object:Gem::Version
67
+ hash: 3
67
68
  segments:
68
69
  - 0
69
70
  version: "0"
data/CHANGELOG.rdoc DELETED
@@ -1,45 +0,0 @@
1
- = CHANGELOG
2
-
3
- == Version 1.4.4
4
-
5
- * https://github.com/alexdunae/validates_email_format_of/compare/1.4.3...1.4.4
6
-
7
- == Version 1.4.3
8
-
9
- * https://github.com/alexdunae/validates_email_format_of/compare/1.4.2...1.4.3
10
-
11
- == Version 1.4.2
12
-
13
- * See https://github.com/alexdunae/validates_email_format_of/compare/1.4.1...1.4.2
14
-
15
- == Version 1.4.1 (the George Anderson and 'history' edition)
16
- * don't allow domains with underscores
17
- * removed extra spaces in validation messages
18
- * updated tests for Rails 2.3+
19
-
20
- == Version 1.4 (the Denis Ahearn edition)
21
- * added ability to run validation tests without touching ActiveRecord or a database
22
-
23
- == Version 1.3.1 (the Github edition)
24
- * updated for github
25
-
26
- == Version 1.3 (the Travis Sinnott edition)
27
- * added optional MX record check
28
- * now available as a gem
29
-
30
- == Version 1.2.1 (the RTFM edition)
31
- * added support for quoted local parts
32
- * added length checks for domain and local parts
33
- * corrected escaped character support for RFC 3696 Errata
34
- * added :allow_blank option
35
- * added :unless option
36
-
37
- == Version 1.2 (the Ismael Santos Kafeltz and Michael MacDonald edition)
38
- * added support for un-escaped and escaped special characters in the local part, per RFC 3696
39
- * added :allow_nil option
40
-
41
- == Version 1.1 (the Francis Hwang edition)
42
- * moved Regexp out of class methods into the ValidatesEmailFormatOf module
43
-
44
- == Version 1.0
45
- * initial version