diff options
author | ThibG <thib@sitedethib.com> | 2020-08-12 12:40:25 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-08-12 12:40:25 +0200 |
commit | 8d217d7231be46af552c63aff9e53d0ed5dca0f6 (patch) | |
tree | cc45f0433545e57aafee21f5aa463ff5919a6bae /app/validators | |
parent | 7dc4c742650ac69ec9a4459b656e172283511e4c (diff) |
Improve email address validation (#14565)
* Increase DNS timeout from 1 second to 5 seconds for MX check 1 seconds is rather short when using a recursive DNS resolver which hasn't got a cached result already available. Use 5 seconds instead, which is the timeout value we use for outgoing HTTP queries. * Add more precise error messages for invalid e-mail addresses
Diffstat (limited to 'app/validators')
-rw-r--r-- | app/validators/blacklisted_email_validator.rb | 2 | ||||
-rw-r--r-- | app/validators/email_mx_validator.rb | 30 |
2 files changed, 23 insertions, 9 deletions
diff --git a/app/validators/blacklisted_email_validator.rb b/app/validators/blacklisted_email_validator.rb index 0d01a1c47..16e3abf12 100644 --- a/app/validators/blacklisted_email_validator.rb +++ b/app/validators/blacklisted_email_validator.rb @@ -6,7 +6,7 @@ class BlacklistedEmailValidator < ActiveModel::Validator @email = user.email - user.errors.add(:email, I18n.t('users.invalid_email')) if blocked_email? + user.errors.add(:email, I18n.t('users.blocked_email_provider')) if blocked_email? end private diff --git a/app/validators/email_mx_validator.rb b/app/validators/email_mx_validator.rb index 9b5009966..ef1554494 100644 --- a/app/validators/email_mx_validator.rb +++ b/app/validators/email_mx_validator.rb @@ -4,22 +4,38 @@ require 'resolv' class EmailMxValidator < ActiveModel::Validator def validate(user) - user.errors.add(:email, I18n.t('users.invalid_email')) if invalid_mx?(user.email) + domain = get_domain(user.email) + + if domain.nil? + user.errors.add(:email, I18n.t('users.invalid_email')) + else + ips, hostnames = resolve_mx(domain) + if ips.empty? + user.errors.add(:email, I18n.t('users.invalid_email_mx')) + elsif on_blacklist?(hostnames + ips) + user.errors.add(:email, I18n.t('users.blocked_email_provider')) + end + end end private - def invalid_mx?(value) + def get_domain(value) _, domain = value.split('@', 2) - return true if domain.nil? + return nil if domain.nil? + + TagManager.instance.normalize_domain(domain) + rescue Addressable::URI::InvalidURIError + nil + end - domain = TagManager.instance.normalize_domain(domain) + def resolve_mx(domain) hostnames = [] ips = [] Resolv::DNS.open do |dns| - dns.timeouts = 1 + dns.timeouts = 5 hostnames = dns.getresources(domain, Resolv::DNS::Resource::IN::MX).to_a.map { |e| e.exchange.to_s } @@ -29,9 +45,7 @@ class EmailMxValidator < ActiveModel::Validator end end - ips.empty? || on_blacklist?(hostnames + ips) - rescue Addressable::URI::InvalidURIError - true + [ips, hostnames] end def on_blacklist?(values) |