Add email description to epp responce on contact creation

This commit is contained in:
Alex Sherman 2020-07-13 13:48:08 +05:00
parent 294c765819
commit 0a7b754c4c
7 changed files with 284 additions and 6 deletions

View file

@ -0,0 +1,89 @@
module Concerns
module EmailVerifable
extend ActiveSupport::Concern
def email_verification
@email_verification ||= EmailAddressVerification.find_or_create_by(email: unicode_email,
domain: domain(email))
end
def billing_email_verification
return unless attribute_names.include?('billing_email')
@billing_email_verification ||= EmailAddressVerification
.find_or_create_by(email: 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 unicode_billing_email
self.class.punycode_to_unicode(billing_email)
end
def unicode_email
self.class.punycode_to_unicode(email)
end
def domain(email)
SimpleIDN.to_unicode(self.class.domain(email))
end
def punycode_to_unicode(email)
self.class.punycode_to_unicode(email)
end
def correct_email_format
return if email.blank?
result = email_verification.verify
process_result(result: result, field: :email)
end
def correct_billing_email_format
return if email.blank?
result = billing_email_verification.verify
process_result(result: result, field: :billing_email)
end
def process_result(result:, field:)
case result[:errors].keys.first
when :smtp
errors.add(field, I18n.t('activerecord.errors.models.contact.attributes.email.email_smtp_check_error'))
when :mx
errors.add(field, I18n.t('activerecord.errors.models.contact.attributes.email.email_mx_check_error'))
when :regex
errors.add(field, I18n.t('activerecord.errors.models.contact.attributes.email.email_regex_check_error'))
end
end
end
end

View file

@ -77,7 +77,10 @@ class Epp::Contact < Contact
[:email, :invalid],
[:country_code, :invalid],
[:code, :invalid],
[:code, :too_long_contact_code]
[:code, :too_long_contact_code],
[:email, :email_smtp_check_error],
[:email, :email_mx_check_error],
[:email, :email_regex_check_error]
],
'2302' => [ # Object exists
[:code, :epp_id_taken]

View file

@ -0,0 +1,77 @@
require 'truemail'
Truemail.configure do |config|
# Required parameter. Must be an existing email on behalf of which verification will be performed
config.verifier_email = ENV['action_mailer_default_from']
# Optional parameter. Must be an existing domain on behalf of which verification will be performed.
# By default verifier domain based on verifier email
# config.verifier_domain = 'internet.ee'
# Optional parameter. You can override default regex pattern
# config.email_pattern = /regex_pattern/
# Optional parameter. You can override default regex pattern
# config.smtp_error_body_pattern = /regex_pattern/
# Optional parameter. Connection timeout is equal to 2 ms by default.
# config.connection_timeout = 1
# Optional parameter. A SMTP server response timeout is equal to 2 ms by default.
# config.response_timeout = 1
# Optional parameter. Total of connection attempts. It is equal to 2 by default.
# This parameter uses in mx lookup timeout error and smtp request (for cases when
# there is one mx server).
config.connection_attempts = 3
# Optional parameter. You can predefine default validation type for
# Truemail.validate('email@email.com') call without with-parameter
# Available validation types: :regex, :mx, :smtp
if Rails.env.production?
config.default_validation_type = :smtp
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.
# Also you can skip validation by domain. Available validation types: :regex, :mx, :smtp
# This configuration will be used over current or default validation type parameter
# All of validations for 'somedomain.com' will be processed with regex validation only.
# And all of validations for 'otherdomain.com' will be processed with mx validation only.
# It is equal to empty hash by default.
# config.validation_type_for = { 'somedomain.com' => :regex, 'otherdomain.com' => :mx }
# Optional parameter. Validation of email which contains whitelisted domain always will
# return true. Other validations will not processed even if it was defined in validation_type_for
# It is equal to empty array by default.
# config.whitelisted_domains = []
# Optional parameter. With this option Truemail will validate email which contains whitelisted
# domain only, i.e. if domain whitelisted, validation will passed to Regex, MX or SMTP validators.
# Validation of email which not contains whitelisted domain always will return false.
# It is equal false by default.
#config.whitelist_validation = true
# Optional parameter. Validation of email which contains blacklisted domain always will
# return false. Other validations will not processed even if it was defined in validation_type_for
# It is equal to empty array by default.
#config.blacklisted_domains = []
# Optional parameter. This option will provide to use not RFC MX lookup flow.
# It means that MX and Null MX records will be cheked on the DNS validation layer only.
# By default this option is disabled.
# config.not_rfc_mx_lookup_flow = true
# Optional parameter. This option will be parse bodies of SMTP errors. It will be helpful
# if SMTP server does not return an exact answer that the email does not exist
# By default this option is disabled, available for SMTP validation only.
# config.smtp_safe_check = true
# Optional parameter. This option will enable tracking events. You can print tracking events to
# stdout, write to file or both of these. Tracking event by default is :error
# Available tracking event: :all, :unrecognized_error, :recognized_error, :error
# config.logger = { tracking_event: :all, stdout: true, log_absolute_path: '/home/app/log/truemail.log' }
end

View file

@ -20,6 +20,9 @@ en:
email:
blank: "Required parameter missing - email"
invalid: "Email is invalid"
email_smtp_check_error: SMTP check error
email_mx_check_error: Mail domain not found
email_regex_check_error: Invalid format
domains:
exist: 'Object association prohibits operation'
statuses:

View file

@ -41,6 +41,41 @@ class EppContactCreateBaseTest < EppTestCase
assert_not_empty contact.code
end
def test_responces_error_with_email_error
name = 'new'
email = 'new@registrar@test'
phone = '+1.2'
request_xml = <<-XML
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<epp xmlns="https://epp.tld.ee/schema/epp-ee-1.0.xsd">
<command>
<create>
<contact:create xmlns:contact="https://epp.tld.ee/schema/contact-ee-1.1.xsd">
<contact:postalInfo>
<contact:name>#{name}</contact:name>
</contact:postalInfo>
<contact:voice>#{phone}</contact:voice>
<contact:email>#{email}</contact:email>
</contact:create>
</create>
<extension>
<eis:extdata xmlns:eis="https://epp.tld.ee/schema/eis-1.0.xsd">
<eis:ident type="priv" cc="US">any</eis:ident>
</eis:extdata>
</extension>
</command>
</epp>
XML
assert_no_difference 'Contact.count' do
post epp_create_path, params: { frame: request_xml },
headers: { 'HTTP_COOKIE' => 'session=api_bestnames' }
end
assert_epp_response :parameter_value_syntax_error
end
def test_respects_custom_code
name = 'new'
code = 'custom-id'

View file

@ -66,9 +66,25 @@ class ContactTest < ActiveSupport::TestCase
contact.email = 'invalid'
assert contact.invalid?
assert_equal I18n.t('activerecord.errors.models.contact.attributes.email.email_smtp_check_error'), contact.errors.messages[:email].first
end
contact.email = 'valid@registrar.test'
assert contact.valid?
def test_email_verification_mx_error
Truemail.configure.default_validation_type = :mx
contact = valid_contact
contact.email = 'somecrude31337joke@somestrange31337domain.ee'
assert contact.invalid?
assert_equal I18n.t('activerecord.errors.models.contact.attributes.email.email_mx_check_error'), contact.errors.messages[:email].first
end
def test_email_verification_regex_error
Truemail.configure.default_validation_type = :regex
contact = valid_contact
contact.email = 'some@strangesentence@internet.ee'
assert contact.invalid?
assert_equal I18n.t('activerecord.errors.models.contact.attributes.email.email_regex_check_error'), contact.errors.messages[:email].first
end
def test_invalid_without_phone

View file

@ -43,15 +43,25 @@ class RegistrarTest < ActiveSupport::TestCase
registrar.email = 'invalid'
assert registrar.invalid?
assert_equal I18n.t('activerecord.errors.models.contact.attributes.email.email_smtp_check_error'), registrar.errors.messages[:email].first
end
registrar.email = 'valid@email.test'
assert registrar.valid?
def test_email_verification_mx_error
Truemail.configure.default_validation_type = :mx
registrar = valid_registrar
registrar.email = 'somecrude31337joke@somestrange31337domain.ee'
registrar.billing_email = nil
assert registrar.invalid?
assert_equal I18n.t('activerecord.errors.models.contact.attributes.email.email_mx_check_error'), registrar.errors.messages[:email].first
end
def test_invalid_without_accounting_customer_code
registrar = valid_registrar
registrar.accounting_customer_code = ''
assert registrar.invalid?
assert_equal I18n.t('activerecord.errors.models.contact.attributes.email.email_regex_check_error'), registrar.errors.messages[:email].first
end
def test_optional_billing_email
@ -65,8 +75,53 @@ class RegistrarTest < ActiveSupport::TestCase
registrar.billing_email = 'invalid'
assert registrar.invalid?
assert_equal I18n.t('activerecord.errors.models.contact.attributes.email.email_smtp_check_error'), registrar.errors.messages[:billing_email].first
end
registrar.billing_email = 'valid@email.test'
def test_billing_email_verification_mx_error
Truemail.configure.default_validation_type = :mx
registrar = valid_registrar
registrar.billing_email = 'somecrude31337joke@somestrange31337domain.ee'
assert registrar.invalid?
assert_equal I18n.t('activerecord.errors.models.contact.attributes.email.email_mx_check_error'), registrar.errors.messages[:billing_email].first
end
def test_billing_email_verification_regex_error
Truemail.configure.default_validation_type = :regex
registrar = valid_registrar
registrar.billing_email = 'some@strangesentence@internet.ee'
assert registrar.invalid?
assert_equal I18n.t('activerecord.errors.models.contact.attributes.email.email_regex_check_error'), registrar.errors.messages[:billing_email].first
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 = ''
assert registrar.invalid?
end
def test_optional_billing_email
registrar = valid_registrar
registrar.billing_email = ''
assert registrar.valid?
end