Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge pull request #450 from rchekaluk/master

Add Authlogic::Regex::email_nonascii
  • Loading branch information...
commit 1040e1026053d8347b4bbd5dce6e9ee8be3229b9 2 parents ea67a9b + b42332e
@tiegz tiegz authored
View
4 README.rdoc
@@ -49,6 +49,10 @@ You may specify how passwords are cryptographically hashed (or encrypted) by set
c.crypto_provider = Authlogic::CryptoProviders::BCrypt
+You may validate international email addresses by enabling the provided alternate regex:
+
+ c.validates_format_of_email_field_options = {:with => Authlogic::Regex.email_nonascii}
+
Also, sessions are automatically maintained. You can switch this on and off with configuration, but the following will automatically log a user in after a successful registration:
User.create(params[:user])
View
3  lib/authlogic/acts_as_authentic/email.rb
@@ -62,6 +62,9 @@ def merge_validates_length_of_email_field_options(options = {})
# merge options into it. Checkout the convenience function merge_validates_format_of_email_field_options to merge
# options.</b>
#
+ # To validate international email addresses, enable the provided alternate regex:
+ # * <tt>validates_format_of_email_field_options({:with => Authlogic::Regex.email_nonascii})</tt>
+ #
# * <tt>Default:</tt> {:with => Authlogic::Regex.email, :message => Proc.new {I18n.t('error_messages.email_invalid', :default => "should look like an email address.")}}
# * <tt>Accepts:</tt> Hash of options accepted by validates_format_of
def validates_format_of_email_field_options(value = nil)
View
1  lib/authlogic/i18n.rb
@@ -34,6 +34,7 @@ module Authlogic
# login_invalid: should use only letters, numbers, spaces, and .-_@ please.
# consecutive_failed_logins_limit_exceeded: Consecutive failed logins limit exceeded, account is disabled.
# email_invalid: should look like an email address.
+ # email_invalid_international: should look like an international email address.
# password_blank: can not be blank
# password_invalid: is not valid
# not_active: Your account is not active
View
20 lib/authlogic/regex.rb
@@ -18,6 +18,26 @@ def self.email
end
end
+ # A draft regular expression for internationalized email addresses.
+ # Given that the standard may be in flux, this simply emulates @email_regex but rather than
+ # allowing specific characters for each part, it instead disallows the complement set of characters:
+ # - email_name_regex disallows: @[]^ !"#$()*,/:;<=>?`{|}~\ and control characters
+ # - domain_head_regex disallows: _%+ and all characters in email_name_regex
+ # - domain_tld_regex disallows: 0123456789- and all characters in domain_head_regex
+ # http://en.wikipedia.org/wiki/Email_address#Internationalization
+ # http://tools.ietf.org/html/rfc6530
+ # http://www.unicode.org/faq/idn.html
+ # http://ruby-doc.org/core-2.1.5/Regexp.html#class-Regexp-label-Character+Classes
+ # http://en.wikipedia.org/wiki/Unicode_character_property#General_Category
+ def self.email_nonascii
+ @email_nonascii_regex ||= begin
+ email_name_regex = '[^[:cntrl:][@\[\]\^ \!\"#$\(\)*,/:;<=>\?`{|}~\\\]]+'
+ domain_head_regex = '(?:[^[:cntrl:][@\[\]\^ \!\"#$&\(\)*,/:;<=>\?`{|}~\\\_\.%\+\']]+\.)+'
+ domain_tld_regex = '(?:[^[:cntrl:][@\[\]\^ \!\"#$&\(\)*,/:;<=>\?`{|}~\\\_\.%\+\-\'0-9]]{2,13})'
+ /\A#{email_name_regex}@#{domain_head_regex}#{domain_tld_regex}\z/
+ end
+ end
+
# A simple regular expression that only allows for letters, numbers, spaces, and .-_@. Just a standard login / username
# regular expression.
def self.login
View
78 test/acts_as_authentic_test/email_test.rb
@@ -1,7 +1,67 @@
+# encoding: utf-8
require 'test_helper'
module ActsAsAuthenticTest
class EmailTest < ActiveSupport::TestCase
+
+ GOOD_ASCII_EMAILS = [
+ "a@a.com",
+ "damien+test1...etc..@mydomain.com",
+ "dakota.dux+1@gmail.com",
+ "dakota.d'ux@gmail.com",
+ "a&b@c.com",
+ ]
+
+ BAD_ASCII_EMAILS = [
+ "",
+ "aaaaaaaaaaaaa",
+ "question?mark@gmail.com",
+ "backslash@g\\mail.com",
+ "<script>alert(123);</script>\nnobody@example.com",
+ ]
+
+ # http://en.wikipedia.org/wiki/ISO/IEC_8859-1#Codepage_layout
+ GOOD_ISO88591_EMAILS = [
+ "töm.öm@dömain.fi", # https://github.com/binarylogic/authlogic/issues/176
+ "Pelé@examplé.com", # http://en.wikipedia.org/wiki/Email_address#Internationalization_examples
+ ]
+
+ BAD_ISO88591_EMAILS = [
+ "",
+ "öm(@ava.fi", # L paren
+ "é)@domain.com", # R paren
+ "é[@example.com", # L bracket
+ "question?mark@gmail.com", # question mark
+ "back\\slash@gmail.com", # backslash
+ ]
+
+ GOOD_UTF8_EMAILS = [
+ "δκιμή@παράδεγμα.δοκμή", # http://en.wikipedia.org/wiki/Email_address#Internationalization_examples
+ "我本@屋企.香港", # http://en.wikipedia.org/wiki/Email_address#Internationalization_examples
+ "甲斐@黒川.日買", # http://en.wikipedia.org/wiki/Email_address#Internationalization_examples
+ "чебурша@ящик-с-пельнами.рф", # Contains dashes in domain head
+ "企斐@黒川.みんな", # https://github.com/binarylogic/authlogic/issues/176#issuecomment-55829320
+ ]
+
+ BAD_UTF8_EMAILS = [
+ "",
+ ".みんな", # https://github.com/binarylogic/authlogic/issues/176#issuecomment-55829320
+ 'δκιμή@παράδεγμα.δ', # short TLD
+ "öm(@ava.fi", # L paren
+ "é)@domain.com", # R paren
+ "é[@example.com", # L bracket
+ "δ]@πράιγμα.δοκμή", # R bracket
+ "\.香港", # slash
+ "甲;.日本", # semicolon
+ "ч:@ящик-с-пельнами.рф", # colon
+ "斐,.みんな", # comma
+ "香<.香港", # less than
+ "我>.香港", # greater than
+ "我?本@屋企.香港", # question mark
+ "чебурша@ьн\\ами.рф", # backslash
+ "user@domain.com%0A<script>alert('hello')</script>",
+ ]
+
def test_email_field_config
assert_equal :email, User.email_field
assert_equal :email, Employee.email_field
@@ -53,6 +113,12 @@ def test_validates_format_of_email_field_options_config
assert_equal({:yes => "no"}, User.validates_format_of_email_field_options)
User.validates_format_of_email_field_options default
assert_equal default, User.validates_format_of_email_field_options
+
+ with_email_nonascii = {:with => Authlogic::Regex.email_nonascii, :message => Proc.new{I18n.t('error_messages.email_invalid_international', :default => "should look like an international email address.")}}
+ User.validates_format_of_email_field_options = with_email_nonascii
+ assert_equal(with_email_nonascii, User.validates_format_of_email_field_options)
+ User.validates_format_of_email_field_options with_email_nonascii
+ assert_equal with_email_nonascii, User.validates_format_of_email_field_options
end
def test_deferred_error_message_translation
@@ -126,6 +192,18 @@ def test_validates_format_of_email_field
assert u.errors[:email].size == 0
end
+ def test_validates_format_of_nonascii_email_field
+
+ (GOOD_ASCII_EMAILS + GOOD_ISO88591_EMAILS + GOOD_UTF8_EMAILS).each do |e|
+ assert e =~ Authlogic::Regex.email_nonascii, "Good email should validate: #{e}"
+ end
+
+ (BAD_ASCII_EMAILS + BAD_ISO88591_EMAILS + BAD_UTF8_EMAILS).each do |e|
+ assert e !~ Authlogic::Regex.email_nonascii, "Bad email should not validate: #{e}"
+ end
+
+ end
+
def test_validates_uniqueness_of_email_field
u = User.new
u.email = "bjohnson@binarylogic.com"
Please sign in to comment.
Something went wrong with that request. Please try again.