diff --git a/app/models/email_address.rb b/app/models/email_address.rb index a62ac9cf9..9f06c3b62 100644 --- a/app/models/email_address.rb +++ b/app/models/email_address.rb @@ -39,7 +39,17 @@ class EmailAddress < ApplicationRecord safe_attributes 'address' def address=(arg) - write_attribute(:address, arg.to_s.strip) + normalized_address = arg.to_s.strip + + # Convert internationalized domain name (IDN) to Punycode + # e.g. 'marie@société.example' => 'marie@xn--socit-esab.example' + local_part, _at, domain = normalized_address.partition('@') + if domain.present? + ascii_domain = Addressable::IDNA.to_ascii(domain) + normalized_address = "#{local_part}@#{ascii_domain}" + end + + write_attribute(:address, normalized_address) end def destroy diff --git a/test/unit/email_address_test.rb b/test/unit/email_address_test.rb index 6fa1d7882..03d249403 100644 --- a/test/unit/email_address_test.rb +++ b/test/unit/email_address_test.rb @@ -68,4 +68,10 @@ class EmailAddressTest < ActiveSupport::TestCase def test_should_reject_invalid_email assert_not EmailAddress.new(address: 'invalid,email@example.com').valid? end + + def test_should_normalize_idn_email_address + email = EmailAddress.new(address: 'marie@société.example') + assert_equal 'marie@xn--socit-esab.example', email.address + assert email.valid? + end end