Skip to content

Commit

Permalink
Improvements for more PEP compliance (duplicate imports, raise from, …
Browse files Browse the repository at this point in the history
…else's) (#125)

1. Removed duplicate imports
2. Added `raise from` for better exception tracing
3. Removed `else` in the check that handles the exception
  • Loading branch information
mrcnkwcz authored Feb 7, 2024
1 parent 5d72f53 commit a584257
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 25 deletions.
10 changes: 5 additions & 5 deletions email_validator/deliverability.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,12 @@ def validate_email_deliverability(domain: str, domain_i18n: str, timeout: Option
deliverability_info["mx"] = [(0, str(r)) for r in response]
deliverability_info["mx_fallback_type"] = "AAAA"

except dns.resolver.NoAnswer:
except dns.resolver.NoAnswer as e:
# If there was no MX, A, or AAAA record, then mail to
# this domain is not deliverable, although the domain
# name has other records (otherwise NXDOMAIN would
# have been raised).
raise EmailUndeliverableError(f"The domain name {domain_i18n} does not accept email.")
raise EmailUndeliverableError(f"The domain name {domain_i18n} does not accept email.") from e

# Check for a SPF (RFC 7208) reject-all record ("v=spf1 -all") which indicates
# no emails are sent from this domain (similar to a Null MX record
Expand All @@ -96,10 +96,10 @@ def validate_email_deliverability(domain: str, domain_i18n: str, timeout: Option
# No TXT records means there is no SPF policy, so we cannot take any action.
pass

except dns.resolver.NXDOMAIN:
except dns.resolver.NXDOMAIN as e:
# The domain name does not exist --- there are no records of any sort
# for the domain name.
raise EmailUndeliverableError(f"The domain name {domain_i18n} does not exist.")
raise EmailUndeliverableError(f"The domain name {domain_i18n} does not exist.") from e

except dns.resolver.NoNameservers:
# All nameservers failed to answer the query. This might be a problem
Expand All @@ -122,6 +122,6 @@ def validate_email_deliverability(domain: str, domain_i18n: str, timeout: Option
# Unhandled conditions should not propagate.
raise EmailUndeliverableError(
"There was an error while checking if the domain name in the email address is deliverable: " + str(e)
)
) from e

return deliverability_info
1 change: 0 additions & 1 deletion email_validator/exceptions_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ def __getattr__(self, key):

@property
def email(self):
import warnings
warnings.warn("ValidatedEmail.email is deprecated and will be removed, use ValidatedEmail.normalized instead", DeprecationWarning)
return self.normalized

Expand Down
33 changes: 16 additions & 17 deletions email_validator/syntax.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ def split_email(email):
# Since backslash-escaping is no longer needed because
# the quotes are removed, remove backslash-escaping
# to return in the normalized form.
import re
local_part = re.sub(r"\\(.)", "\\1", local_part)

return local_part, domain_part, True
Expand Down Expand Up @@ -72,14 +71,14 @@ def validate_email_local_part(local: str, allow_smtputf8: bool = True, allow_emp
if len(local) == 0:
if not allow_empty_local:
raise EmailSyntaxError("There must be something before the @-sign.")
else:
# The caller allows an empty local part. Useful for validating certain
# Postfix aliases.
return {
"local_part": local,
"ascii_local_part": local,
"smtputf8": False,
}

# The caller allows an empty local part. Useful for validating certain
# Postfix aliases.
return {
"local_part": local,
"ascii_local_part": local,
"smtputf8": False,
}

# Check the length of the local part by counting characters.
# (RFC 5321 4.5.3.1.1)
Expand Down Expand Up @@ -191,8 +190,8 @@ def validate_email_local_part(local: str, allow_smtputf8: bool = True, allow_emp
# want to have an unhandled exception later.
try:
local.encode("utf8")
except ValueError:
raise EmailSyntaxError("The email address contains an invalid character.")
except ValueError as e:
raise EmailSyntaxError("The email address contains an invalid character.") from e

# If this address passes only by the quoted string form, re-quote it
# and backslash-escape quotes and backslashes (removing any unnecessary
Expand Down Expand Up @@ -330,7 +329,7 @@ def validate_email_domain_name(domain, test_environment=False, globally_delivera
try:
domain = idna.uts46_remap(domain, std3_rules=False, transitional=False)
except idna.IDNAError as e:
raise EmailSyntaxError(f"The part after the @-sign contains invalid characters ({e}).")
raise EmailSyntaxError(f"The part after the @-sign contains invalid characters ({e}).") from e

# The domain part is made up dot-separated "labels." Each label must
# have at least one character and cannot start or end with dashes, which
Expand Down Expand Up @@ -374,11 +373,11 @@ def validate_email_domain_name(domain, test_environment=False, globally_delivera
# the length check is applied to a string that is different from the
# one the user supplied. Also I'm not sure if the length check applies
# to the internationalized form, the IDNA ASCII form, or even both!
raise EmailSyntaxError("The email address is too long after the @-sign.")
raise EmailSyntaxError("The email address is too long after the @-sign.") from e

# Other errors seem to not be possible because the call to idna.uts46_remap
# would have already raised them.
raise EmailSyntaxError(f"The part after the @-sign contains invalid characters ({e}).")
raise EmailSyntaxError(f"The part after the @-sign contains invalid characters ({e}).") from e

# Check the syntax of the string returned by idna.encode.
# It should never fail.
Expand Down Expand Up @@ -440,7 +439,7 @@ def validate_email_domain_name(domain, test_environment=False, globally_delivera
try:
domain_i18n = idna.decode(ascii_domain.encode('ascii'))
except idna.IDNAError as e:
raise EmailSyntaxError(f"The part after the @-sign is not valid IDNA ({e}).")
raise EmailSyntaxError(f"The part after the @-sign is not valid IDNA ({e}).") from e

# Check for invalid characters after normalization. These
# should never arise. See the similar checks above.
Expand Down Expand Up @@ -518,7 +517,7 @@ def validate_email_domain_literal(domain_literal):
try:
addr = ipaddress.IPv4Address(domain_literal)
except ValueError as e:
raise EmailSyntaxError(f"The address in brackets after the @-sign is not valid: It is not an IPv4 address ({e}) or is missing an address literal tag.")
raise EmailSyntaxError(f"The address in brackets after the @-sign is not valid: It is not an IPv4 address ({e}) or is missing an address literal tag.") from e

# Return the IPv4Address object and the domain back unchanged.
return {
Expand All @@ -531,7 +530,7 @@ def validate_email_domain_literal(domain_literal):
try:
addr = ipaddress.IPv6Address(domain_literal[5:])
except ValueError as e:
raise EmailSyntaxError(f"The IPv6 address in brackets after the @-sign is not valid ({e}).")
raise EmailSyntaxError(f"The IPv6 address in brackets after the @-sign is not valid ({e}).") from e

# Return the IPv6Address object and construct a normalized
# domain literal.
Expand Down
4 changes: 2 additions & 2 deletions email_validator/validate_email.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ def validate_email(
if not isinstance(email, str):
try:
email = email.decode("ascii")
except ValueError:
raise EmailSyntaxError("The email address is not valid ASCII.")
except ValueError as e:
raise EmailSyntaxError("The email address is not valid ASCII.") from e

# Split the address into the local part (before the @-sign)
# and the domain part (after the @-sign). Normally, there
Expand Down

0 comments on commit a584257

Please sign in to comment.