Suggestions for #4 (returning None) and #2 (logging server responses)

* removed unused "import socket"
* changed broad "except" clause to more specific "except ImportError"
* general PEP8 reformat
* added "debug" option for logging server responses/errors
* return None instead of True/False on several errors that may be temporary
This commit is contained in:
Paulo Scardine
2013-06-01 16:54:39 -03:00
parent e843df23c7
commit 9679958340

View File

@@ -19,14 +19,17 @@
import re
import smtplib
import socket
import logging
try:
import DNS
ServerError = DNS.ServerError
except:
except ImportError:
DNS = None
class ServerError(Exception): pass
class ServerError(Exception):
pass
# All we are really doing is comparing the input string to one
# gigantic regular expression. But building that regexp, and
# ensuring its correctness, is made much easier by assembling it
@@ -50,7 +53,7 @@ CTEXT = r'[' + NO_WS_CTL + \
r'\x21-\x27\x2a-\x5b\x5d-\x7e]' # see 3.2.3
CCONTENT = r'(?:' + CTEXT + r'|' + \
QUOTED_PAIR + r')' # see 3.2.3 (NB: The RFC includes COMMENT here
# as well, but that would be circular.)
# as well, but that would be circular.)
COMMENT = r'\((?:' + FWS + r'?' + CCONTENT + \
r')*' + FWS + r'?\)' # see 3.2.3
CFWS = r'(?:' + FWS + r'?' + COMMENT + ')*(?:' + \
@@ -81,8 +84,8 @@ ADDR_SPEC = LOCAL_PART + r'@' + DOMAIN # see 3.4.1
# A valid address will match exactly the 3.4.1 addr-spec.
VALID_ADDRESS_REGEXP = '^' + ADDR_SPEC + '$'
def validate_email(email, check_mx=False,verify=False):
def validate_email(email, check_mx=False, verify=False, debug=False):
"""Indicate whether the given string is a valid email address
according to the 'addr-spec' portion of RFC 2822 (see section
3.4.1). Parts of the spec that are marked obsolete are *not*
@@ -90,13 +93,20 @@ def validate_email(email, check_mx=False,verify=False):
depend on circular definitions in the spec may not pass, but in
general this should correctly identify any email address likely
to be in use as of 2011."""
if debug:
logger = logging.getLogger('validate_email')
else:
logger = None
try:
assert re.match(VALID_ADDRESS_REGEXP, email) is not None
check_mx |= verify
if check_mx:
if not DNS: raise Exception('For check the mx records or check if the email exists you must have installed pyDNS python package')
if not DNS:
raise Exception('For check the mx records or check if the email exists you must '
'have installed pyDNS python package')
DNS.DiscoverNameServers()
hostname = email[email.find('@')+1:]
hostname = email[email.find('@') + 1:]
mx_hosts = DNS.mxlookup(hostname)
for mx in mx_hosts:
try:
@@ -108,20 +118,30 @@ def validate_email(email, check_mx=False,verify=False):
status, _ = smtp.helo()
if status != 250:
smtp.quit()
if debug:
logger.debug(u'%s answer: %s - %s', mx[1], status, _)
continue
smtp.mail('')
status, _ = smtp.rcpt(email)
if status != 250:
if status == 250:
smtp.quit()
return False
return True
if debug:
logger.debug(u'%s answer: %s - %s', mx[1], status, _)
smtp.quit()
break
except smtplib.SMTPServerDisconnected: #Server not permits verify user
break
except smtplib.SMTPServerDisconnected: # Server not permits verify user
if debug:
logger.debug(u'%s disconected.', mx[1])
except smtplib.SMTPConnectError:
continue
except (AssertionError, ServerError):
if debug:
logger.debug(u'Unable to connect to %s.', mx[1])
return None
except AssertionError:
return False
except ServerError:
if debug:
logger.debug(u'ServerError exception raised.')
return None
return True
# import sys