Skip to content

Commit

Permalink
Fixes more Host validation issues
Browse files Browse the repository at this point in the history
From Issue #13

    EmailAddress.valid? 'asdf@YA hoo.com', dns_lookup: :off # => true

When no DNS is done, a Regex validation should still be performed.

Refactored Host#valid? to provide more detailed error messages and
ensure Regex validation is always done for all domain names.
  • Loading branch information
afair committed Dec 7, 2017
1 parent 155aa8a commit 6c4fcd2
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 17 deletions.
4 changes: 2 additions & 2 deletions lib/email_address/address.rb
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ def valid?(options={})
return set_error :invalid_mailbox
end
unless self.host.valid?
return set_error :invalid_host
return set_error self.host.error_message
end
if @config[:address_size] && !@config[:address_size].include?(self.to_s.size)
return set_error :exceeds_size
Expand All @@ -237,7 +237,7 @@ def valid?(options={})
end

def set_error(err)
@error = EmailAddress::Config.error_messages[err] || err
@error = EmailAddress::Config.error_messages.fetch(err) { err }
false
end

Expand Down
63 changes: 48 additions & 15 deletions lib/email_address/host.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class Host
attr_reader :host_name
attr_accessor :dns_name, :domain_name, :registration_name,
:tld, :tld2, :subdomains, :ip_address, :config, :provider,
:comment
:comment, :error_message
MAX_HOST_LENGTH = 255

# Sometimes, you just need a Regexp...
Expand Down Expand Up @@ -313,11 +313,6 @@ def dns_enabled?
EmailAddress::Config.setting(:dns_lookup).equal?(:off) ? false : true
end

# True if the host name has a DNS A Record
def has_dns_a_record?
dns_a_record.size > 0 ? true : false
end

# Returns: [official_hostname, alias_hostnames, address_family, *address_list]
def dns_a_record
@_dns_a_record ||= Socket.gethostbyname(self.dns_name)
Expand Down Expand Up @@ -366,31 +361,69 @@ def dmarc

# Returns true if the host name is valid according to the current configuration
def valid?(rule=@config[:dns_lookup]||:mx)
self.error_message = nil
if self.ip_address
@config[:host_allow_ip] && self.valid_ip?
valid_ip?
elsif ! valid_format?
false
elsif rule == :mx
self.exchangers.mx_ips.size > 0
valid_mx?
elsif rule == :a
self.has_dns_a_record?
valid_dns?
elsif rule == :off
self.to_s.size <= MAX_HOST_LENGTH
true
else
false
set_error(:domain_bad_validation_rule)
end
end

# The inverse of valid? -- Returns nil (falsey) if valid, otherwise error message
def error
valid? ? nil : @error_message
end

# True if the host name has a DNS A Record
def valid_dns?
dns_a_record.size > 0 || set_error(:domain_unknown)
end

# True if the host name has valid MX servers configured in DNS
def valid_mx?
if self.exchangers.mx_ips.size > 0
true
elsif valid_dns?
set_error(:domain_does_not_accept_email)
else
set_error(:domain_unknown)
end
end

# True if the host_name passes Regular Expression match and size limits.
def valid_format?
if self.host_name =~ CANONICAL_HOST_REGEX && self.to_s.size <= MAX_HOST_LENGTH
true
else
set_error(:domain_invalid)
end
end

# Returns true if the IP address given in that form of the host name
# is a potentially valid IP address. It does not check if the address
# is reachable.
def valid_ip?
if self.ip_address.nil?
false
if ! @config[:host_allow_ip]
set_error(:ip_address_forbidden)
elsif self.ip_address.include?(":")
self.ip_address =~ Resolv::IPv6::Regex ? true : false
self.ip_address =~ Resolv::IPv6::Regex ? true : set_error(:ipv6_address_invalid)
elsif self.ip_address.include?(".")
self.ip_address =~ Resolv::IPv4::Regex ? true : false
self.ip_address =~ Resolv::IPv4::Regex ? true : set_error(:ipv4_address_invalid)
end
end

def set_error(err)
@error_message = EmailAddress::Config.error_messages.fetch(err) { err }
false
end

end
end

0 comments on commit 6c4fcd2

Please sign in to comment.