Increase consistency at handling domain literals #15

Merged
reinhard-mueller merged 1 commit from master into master 2020-04-14 12:25:02 +02:00
3 changed files with 30 additions and 15 deletions

View file

@ -1,3 +1,5 @@
from typing import Optional
from idna.core import IDNAError, encode
from .exceptions import AddressFormatError
@ -22,7 +24,7 @@ class EmailAddress(object):
raise AddressFormatError
# Convert internationalized domain name into the ACE encoding
if self._domain.startswith('[') and self._domain.endswith(']'):
if self.domain_literal_ip:
self._ace_domain = self._domain
else:
try:
@ -46,6 +48,16 @@ class EmailAddress(object):
"""
return self._domain
@property
def domain_literal_ip(self) -> Optional[str]:
"""
If the domain part of the email address is a literal IP address
enclosed in brackets, that IP address (without the brakcets) is
returned. Otherwise, `None` is returned.
"""
if self._domain.startswith('[') and self._domain.endswith(']'):
return self._domain[1:-1]
@property
def ace(self) -> str:
'The ASCII-compatible encoding for the email address.'

View file

@ -109,8 +109,11 @@ def mx_check(
"""
host = helo_host or gethostname()
from_address = from_address or email_address
mx_records = _get_mx_records(
domain=email_address.domain, timeout=dns_timeout)
if email_address.domain_literal_ip:
mx_records = [email_address.domain_literal_ip]
else:
mx_records = _get_mx_records(
domain=email_address.domain, timeout=dns_timeout)
return _check_mx_records(
mx_records=mx_records, smtp_timeout=smtp_timeout, helo_host=host,
from_address=from_address, email_address=email_address)

View file

@ -35,16 +35,16 @@ def regex_check(address: EmailAddress) -> bool:
if not USER_REGEX.match(address.user):
raise AddressFormatError
# Validate domain part: a) hostname.
if HOST_REGEX.match(address.ace_domain):
return True
# Validate domain part.
if address.domain_literal_ip:
literal_match = LITERAL_REGEX.match(address.ace_domain)
if literal_match is None:
raise AddressFormatError
if not _validate_ipv46_address(literal_match[1]):
raise AddressFormatError
else:
if HOST_REGEX.match(address.ace_domain) is None:
raise AddressFormatError
# Validate domain part: b) literal IP address.
literal_match = LITERAL_REGEX.match(address.ace_domain)
if literal_match:
ip_address = literal_match.group(1)
if _validate_ipv46_address(ip_address):
return True
# Domain part not successfully validated.
raise AddressFormatError
# All validations successful.
return True