1212ALLOW_SMTPUTF8 = True
1313CHECK_DELIVERABILITY = True
1414TEST_ENVIRONMENT = False
15+ GLOBALLY_DELIVERABLE = True
1516DEFAULT_TIMEOUT = 15 # secs
1617
1718# Based on RFC 2822 section 3.2.4 / RFC 5322 section 3.2.3, these
@@ -268,6 +269,7 @@ def validate_email(
268269 allow_empty_local = False ,
269270 check_deliverability = None ,
270271 test_environment = None ,
272+ globally_deliverable = GLOBALLY_DELIVERABLE ,
271273 timeout = None ,
272274 dns_resolver = None
273275):
@@ -314,7 +316,7 @@ def validate_email(
314316 ret .smtputf8 = local_part_info ["smtputf8" ]
315317
316318 # Validate the email address's domain part syntax and get a normalized form.
317- domain_part_info = validate_email_domain_part (parts [1 ], test_environment = test_environment )
319+ domain_part_info = validate_email_domain_part (parts [1 ], test_environment = test_environment , globally_deliverable = globally_deliverable )
318320 ret .domain = domain_part_info ["domain" ]
319321 ret .ascii_domain = domain_part_info ["ascii_domain" ]
320322
@@ -473,7 +475,7 @@ def validate_email_local_part(local, allow_smtputf8=True, allow_empty_local=Fals
473475 }
474476
475477
476- def validate_email_domain_part (domain , test_environment = False ):
478+ def validate_email_domain_part (domain , test_environment = False , globally_deliverable = True ):
477479 # Empty?
478480 if len (domain ) == 0 :
479481 raise EmailSyntaxError ("There must be something after the @-sign." )
@@ -551,13 +553,20 @@ def validate_email_domain_part(domain, test_environment=False):
551553 if not m :
552554 raise EmailSyntaxError ("The email address contains invalid characters after the @-sign." )
553555
554- # All publicly deliverable addresses have domain named with at least
555- # one period, and we'll consider the lack of a period a syntax error
556- # since that will match people's sense of what an email address looks
557- # like. We'll skip this in test environments to allow '@test' email
558- # addresses.
559- if "." not in ascii_domain and not (ascii_domain == "test" and test_environment ):
560- raise EmailSyntaxError ("The domain name %s is not valid. It should have a period." % domain_i18n )
556+ if globally_deliverable :
557+ # All publicly deliverable addresses have domain named with at least
558+ # one period, and we'll consider the lack of a period a syntax error
559+ # since that will match people's sense of what an email address looks
560+ # like. We'll skip this in test environments to allow '@test' email
561+ # addresses.
562+ if "." not in ascii_domain and not (ascii_domain == "test" and test_environment ):
563+ raise EmailSyntaxError ("The domain name %s is not valid. It should have a period." % domain_i18n )
564+
565+ # We also know that all TLDs currently end with a letter.
566+ if not re .search (r"[A-Za-z]\Z" , ascii_domain ):
567+ raise EmailSyntaxError (
568+ "The domain name %s is not valid. It is not within a valid top-level domain." % domain_i18n
569+ )
561570
562571 # Check special-use and reserved domain names.
563572 # Some might fail DNS-based deliverability checks, but that
@@ -570,12 +579,6 @@ def validate_email_domain_part(domain, test_environment=False):
570579 if ascii_domain == d or ascii_domain .endswith ("." + d ):
571580 raise EmailSyntaxError ("The domain name %s is a special-use or reserved name that cannot be used with email." % domain_i18n )
572581
573- # We also know that all TLDs currently end with a letter.
574- if not re .search (r"[A-Za-z]\Z" , ascii_domain ):
575- raise EmailSyntaxError (
576- "The domain name %s is not valid. It is not within a valid top-level domain." % domain_i18n
577- )
578-
579582 # Return the IDNA ASCII-encoded form of the domain, which is how it
580583 # would be transmitted on the wire (except when used with SMTPUTF8
581584 # possibly), as well as the canonical Unicode form of the domain,
0 commit comments