39
39
DOT_ATOM_TEXT = DOT_ATOM_TEXT .decode ("ascii" )
40
40
ATEXT_HOSTNAME = ATEXT_HOSTNAME .decode ("ascii" )
41
41
42
+ DEFAULT_TIMEOUT = 15 # secs
43
+
42
44
class EmailNotValidError (ValueError ):
43
45
"""Parent class of all exceptions raised by this module."""
44
46
pass
@@ -55,7 +57,8 @@ def validate_email(
55
57
email ,
56
58
allow_smtputf8 = True ,
57
59
allow_empty_local = False ,
58
- check_deliverability = True ):
60
+ check_deliverability = True ,
61
+ timeout = DEFAULT_TIMEOUT ):
59
62
60
63
"""Validates an email address, raising an EmailNotValidError if the address is not valid or returning a dict of information
61
64
when the address is valid. The email argument can be a str or a bytes instance, but if bytes it must be ASCII-only."""
@@ -88,7 +91,7 @@ def validate_email(
88
91
if check_deliverability :
89
92
# Validate the email address's deliverability and update the
90
93
# return dict with metadata.
91
- ret .update (validate_email_deliverability (ret ["domain" ], ret ["domain_i18n" ]))
94
+ ret .update (validate_email_deliverability (ret ["domain" ], ret ["domain_i18n" ], timeout ))
92
95
93
96
# If the email address has an ASCII form, add it.
94
97
ret ["email" ] = ret ["local" ] + "@" + ret ["domain_i18n" ]
@@ -233,13 +236,16 @@ def validate_email_domain_part(domain):
233
236
"domain_i18n" : domain_i18n ,
234
237
}
235
238
236
- def validate_email_deliverability (domain , domain_i18n ):
239
+ def validate_email_deliverability (domain , domain_i18n , timeout = DEFAULT_TIMEOUT ):
237
240
# Check that the domain resolves to an MX record. If there is no MX record,
238
241
# try an A or AAAA record which is a deprecated fallback for deliverability.
239
242
240
243
try :
241
244
resolver = dns .resolver .get_default_resolver ()
242
245
246
+ if timeout :
247
+ resolver .lifetime = timeout
248
+
243
249
try :
244
250
# Try resolving for MX records and get them in sorted priority order.
245
251
response = dns .resolver .query (domain , "MX" )
@@ -260,7 +266,7 @@ def validate_email_deliverability(domain, domain_i18n):
260
266
mtas = [(0 , str (r )) for r in response ]
261
267
mx_fallback = "AAAA"
262
268
except (dns .resolver .NoNameservers , dns .resolver .NXDOMAIN , dns .resolver .NoAnswer ):
263
-
269
+
264
270
# If there was no MX, A, or AAAA record, then mail to
265
271
# this domain is not deliverable.
266
272
raise EmailUndeliverableError ("The domain name %s does not exist." % domain_i18n )
0 commit comments