Index: Gemfile =================================================================== --- Gemfile (revision 17428) +++ Gemfile (working copy) @@ -14,6 +14,7 @@ gem "mimemagic" gem "mail", "~> 2.6.4" gem "csv", "~> 1.0.2" if RUBY_VERSION >= "2.3" +gem "simpleidn" gem "nokogiri", "~> 1.8.0" gem "i18n", "~> 0.7.0" Index: app/models/email_address.rb =================================================================== --- app/models/email_address.rb (revision 17428) +++ app/models/email_address.rb (working copy) @@ -25,7 +25,7 @@ after_destroy :destroy_tokens, :deliver_security_notification_destroy validates_presence_of :address - validates_format_of :address, :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i, :allow_blank => true + validates_format_of :address, :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+(xn--)?[a-z0-9]{2,})\z/i, :allow_blank => true validates_length_of :address, :maximum => User::MAIL_LENGTH_LIMIT, :allow_nil => true validates_uniqueness_of :address, :case_sensitive => false, :if => Proc.new {|email| email.address_changed? && email.address.present?} @@ -33,7 +33,9 @@ safe_attributes 'address' def address=(arg) - write_attribute(:address, arg.to_s.strip) + local_part, at, domain = arg.to_s.strip.rpartition('@') + ascii_address = at.empty? ? domain : local_part + at + SimpleIDN.to_ascii(domain) + write_attribute(:address, ascii_address) end def destroy Index: test/unit/user_test.rb =================================================================== --- test/unit/user_test.rb (revision 17428) +++ test/unit/user_test.rb (working copy) @@ -84,6 +84,12 @@ assert_equal "foo@bar.com", u.mail end + def test_mail_should_accept_idn + u = User.new + u.mail = "maeda@испытание.test.テスト" + assert_equal "maeda@xn--80akhbyknj4f.test.xn--zckzah", u.mail + end + def test_should_create_email_address u = User.new(:firstname => "new", :lastname => "user") u.login = "create_email_address"