Skip to content

Commit

Permalink
Add undocumented globally_deliverable option for #86
Browse files Browse the repository at this point in the history
  • Loading branch information
JoshData committed Sep 15, 2022
1 parent f728d88 commit a666481
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 15 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Unreleased changes in development
* The keyword arguments of the public methods are now marked as keyword-only.
* [pyIsEmail](https://github.com/michaelherold/pyIsEmail)'s test cases are added to the tests.
* Recommend that check_deliverability be set to False for validation on login pages.
* Added an undocumented globally_deliverable option.

Version 1.2.1 (May 1, 2022)
---------------------------
Expand Down
33 changes: 18 additions & 15 deletions email_validator/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
ALLOW_SMTPUTF8 = True
CHECK_DELIVERABILITY = True
TEST_ENVIRONMENT = False
GLOBALLY_DELIVERABLE = True
DEFAULT_TIMEOUT = 15 # secs

# Based on RFC 2822 section 3.2.4 / RFC 5322 section 3.2.3, these
Expand Down Expand Up @@ -268,6 +269,7 @@ def validate_email(
allow_empty_local=False,
check_deliverability=None,
test_environment=None,
globally_deliverable=GLOBALLY_DELIVERABLE,
timeout=None,
dns_resolver=None
):
Expand Down Expand Up @@ -314,7 +316,7 @@ def validate_email(
ret.smtputf8 = local_part_info["smtputf8"]

# Validate the email address's domain part syntax and get a normalized form.
domain_part_info = validate_email_domain_part(parts[1], test_environment=test_environment)
domain_part_info = validate_email_domain_part(parts[1], test_environment=test_environment, globally_deliverable=globally_deliverable)
ret.domain = domain_part_info["domain"]
ret.ascii_domain = domain_part_info["ascii_domain"]

Expand Down Expand Up @@ -473,7 +475,7 @@ def validate_email_local_part(local, allow_smtputf8=True, allow_empty_local=Fals
}


def validate_email_domain_part(domain, test_environment=False):
def validate_email_domain_part(domain, test_environment=False, globally_deliverable=True):
# Empty?
if len(domain) == 0:
raise EmailSyntaxError("There must be something after the @-sign.")
Expand Down Expand Up @@ -551,13 +553,20 @@ def validate_email_domain_part(domain, test_environment=False):
if not m:
raise EmailSyntaxError("The email address contains invalid characters after the @-sign.")

# All publicly deliverable addresses have domain named with at least
# one period, and we'll consider the lack of a period a syntax error
# since that will match people's sense of what an email address looks
# like. We'll skip this in test environments to allow '@test' email
# addresses.
if "." not in ascii_domain and not (ascii_domain == "test" and test_environment):
raise EmailSyntaxError("The domain name %s is not valid. It should have a period." % domain_i18n)
if globally_deliverable:
# All publicly deliverable addresses have domain named with at least
# one period, and we'll consider the lack of a period a syntax error
# since that will match people's sense of what an email address looks
# like. We'll skip this in test environments to allow '@test' email
# addresses.
if "." not in ascii_domain and not (ascii_domain == "test" and test_environment):
raise EmailSyntaxError("The domain name %s is not valid. It should have a period." % domain_i18n)

# We also know that all TLDs currently end with a letter.
if not re.search(r"[A-Za-z]\Z", ascii_domain):
raise EmailSyntaxError(
"The domain name %s is not valid. It is not within a valid top-level domain." % domain_i18n
)

# Check special-use and reserved domain names.
# Some might fail DNS-based deliverability checks, but that
Expand All @@ -570,12 +579,6 @@ def validate_email_domain_part(domain, test_environment=False):
if ascii_domain == d or ascii_domain.endswith("." + d):
raise EmailSyntaxError("The domain name %s is a special-use or reserved name that cannot be used with email." % domain_i18n)

# We also know that all TLDs currently end with a letter.
if not re.search(r"[A-Za-z]\Z", ascii_domain):
raise EmailSyntaxError(
"The domain name %s is not valid. It is not within a valid top-level domain." % domain_i18n
)

# Return the IDNA ASCII-encoded form of the domain, which is how it
# would be transmitted on the wire (except when used with SMTPUTF8
# possibly), as well as the canonical Unicode form of the domain,
Expand Down

0 comments on commit a666481

Please sign in to comment.