diff --git a/app/models/concerns/email_verifable.rb b/app/models/concerns/email_verifable.rb index f7c9e59fb..ea55ad3b9 100644 --- a/app/models/concerns/email_verifable.rb +++ b/app/models/concerns/email_verifable.rb @@ -3,21 +3,54 @@ module Concerns extend ActiveSupport::Concern def email_verification - EmailAddressVerification.find_or_create_by(email: email.downcase, - domain: domain(email.downcase)) + EmailAddressVerification.find_or_create_by(email: self.class.punycode_to_unicode(email), + domain: domain(email)) end def billing_email_verification return unless attribute_names.include?('billing_email') - EmailAddressVerification.find_or_create_by(email: billing_email.downcase, - domain: domain(email.downcase)) + EmailAddressVerification.find_or_create_by(email: self.class + .punycode_to_unicode(billing_email), + domain: domain(billing_email)) + end + + class_methods do + def domain(email) + Mail::Address.new(email).domain&.downcase || 'not_found' + rescue Mail::Field::IncompleteParseError + 'not_found' + end + + def local(email) + Mail::Address.new(email).local&.downcase || email + rescue Mail::Field::IncompleteParseError + email + end + + def punycode_to_unicode(email) + return email if domain(email) == 'not_found' + + local = local(email) + domain = SimpleIDN.to_unicode(domain(email)) + "#{local}@#{domain}"&.downcase + end + + def unicode_to_punycode(email) + return email if domain(email) == 'not_found' + + local = local(email) + domain = SimpleIDN.to_ascii(domain(email)) + "#{local}@#{domain}"&.downcase + end end def domain(email) - Mail::Address.new(email).domain || 'not_found' - rescue Mail::Field::IncompleteParseError - 'not_found' + SimpleIDN.to_unicode(self.class.domain(email)) + end + + def punycode_to_unicode(email) + self.class.punycode_to_unicode(email) end def verify_email_mx_smtp(field:, email:) diff --git a/app/models/email_address_verification.rb b/app/models/email_address_verification.rb index b478ab0f8..5cc982da6 100644 --- a/app/models/email_address_verification.rb +++ b/app/models/email_address_verification.rb @@ -39,8 +39,7 @@ class EmailAddressVerification < ApplicationRecord end def verify - # media = success ? :mx : :smtp - media = :regex + media = :mx validation_request = Truemail.validate(email, with: media) if validation_request.result.success diff --git a/config/initializers/truemail.rb b/config/initializers/truemail.rb index 337ac8605..cfc8e14b1 100644 --- a/config/initializers/truemail.rb +++ b/config/initializers/truemail.rb @@ -30,8 +30,10 @@ Truemail.configure do |config| # Available validation types: :regex, :mx, :smtp if Rails.env.production? config.default_validation_type = :smtp - else + elsif Rails.env.test? config.default_validation_type = :regex + else + config.default_validation_type = :mx end # Optional parameter. You can predefine which type of validation will be used for domains. diff --git a/db/data/20200608084321_fill_email_verifications.rb b/db/data/20200608084321_fill_email_verifications.rb index 073bf2b24..37a7f275c 100644 --- a/db/data/20200608084321_fill_email_verifications.rb +++ b/db/data/20200608084321_fill_email_verifications.rb @@ -1,10 +1,13 @@ class FillEmailVerifications < ActiveRecord::Migration[6.0] - def up - registrar_billing_emails = Registrar.pluck(:billing_email).uniq.reject(&:blank?).map(&:downcase) - registrar_emails = Registrar.pluck(:email).uniq.reject(&:blank?).map(&:downcase) - contact_emails = Contact.pluck(:email).uniq.reject(&:blank?).map(&:downcase) + include Concerns::EmailVerifable - emails = (contact_emails + registrar_emails + registrar_billing_emails).uniq + def up + registrar_billing_emails = Registrar.pluck(:billing_email).uniq.reject(&:blank?) + registrar_emails = Registrar.pluck(:email).uniq.reject(&:blank?) + contact_emails = Contact.pluck(:email).uniq.reject(&:blank?) + + emails = (contact_emails + registrar_emails + registrar_billing_emails) + emails = emails.map{ |email| punycode_to_unicode(email) }.uniq result = emails.map do |email| { email: email, domain: domain(email) } @@ -15,10 +18,4 @@ class FillEmailVerifications < ActiveRecord::Migration[6.0] def down EmailAddressVerification.delete_all end - - def domain(email) - Mail::Address.new(email).domain || 'not_found' - rescue Mail::Field::IncompleteParseError - 'not_found' - end end diff --git a/test/models/contact_test.rb b/test/models/contact_test.rb index 77e959a95..a412df203 100644 --- a/test/models/contact_test.rb +++ b/test/models/contact_test.rb @@ -270,6 +270,16 @@ class ContactTest < ActiveSupport::TestCase assert_equal domain.whois_record.try(:json).try(:[], 'registrant'), @contact.name end + def test_creates_email_verification_in_unicode + unicode_email = 'suur@äri.ee' + punycode_email = Contact.unicode_to_punycode(unicode_email) + + @contact.email = punycode_email + @contact.save + + assert_equal @contact.email_verification.email, unicode_email + end + private def make_contact_free_of_domains_where_it_acts_as_a_registrant(contact) diff --git a/test/models/registrar_test.rb b/test/models/registrar_test.rb index 6db466e1c..5a497fd76 100644 --- a/test/models/registrar_test.rb +++ b/test/models/registrar_test.rb @@ -61,6 +61,21 @@ class RegistrarTest < ActiveSupport::TestCase end end + def test_creates_email_verification_in_unicode + unicode_email = 'suur@äri.ee' + punycode_email = Registrar.unicode_to_punycode(unicode_email) + unicode_billing_email = 'billing@äri.ee' + punycode_billing_email = Registrar.unicode_to_punycode(unicode_billing_email) + + registrar = valid_registrar + registrar.email = punycode_email + registrar.billing_email = punycode_billing_email + registrar.save + + assert_equal registrar.email_verification.email, unicode_email + assert_equal registrar.billing_email_verification.email, unicode_billing_email + end + def test_invalid_without_accounting_customer_code registrar = valid_registrar registrar.accounting_customer_code = ''