mirror of
https://github.com/aljazceru/validate_email.git
synced 2025-12-19 23:14:20 +01:00
Merge pull request #6 from scardine/master
Suggestions for #4 and #2, general code janitoring.
This commit is contained in:
@@ -19,14 +19,18 @@
|
|||||||
|
|
||||||
import re
|
import re
|
||||||
import smtplib
|
import smtplib
|
||||||
|
import logging
|
||||||
import socket
|
import socket
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import DNS
|
import DNS
|
||||||
ServerError = DNS.ServerError
|
ServerError = DNS.ServerError
|
||||||
except:
|
except ImportError:
|
||||||
DNS = None
|
DNS = None
|
||||||
class ServerError(Exception): pass
|
|
||||||
|
class ServerError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
# All we are really doing is comparing the input string to one
|
# All we are really doing is comparing the input string to one
|
||||||
# gigantic regular expression. But building that regexp, and
|
# gigantic regular expression. But building that regexp, and
|
||||||
# ensuring its correctness, is made much easier by assembling it
|
# ensuring its correctness, is made much easier by assembling it
|
||||||
@@ -50,7 +54,7 @@ CTEXT = r'[' + NO_WS_CTL + \
|
|||||||
r'\x21-\x27\x2a-\x5b\x5d-\x7e]' # see 3.2.3
|
r'\x21-\x27\x2a-\x5b\x5d-\x7e]' # see 3.2.3
|
||||||
CCONTENT = r'(?:' + CTEXT + r'|' + \
|
CCONTENT = r'(?:' + CTEXT + r'|' + \
|
||||||
QUOTED_PAIR + r')' # see 3.2.3 (NB: The RFC includes COMMENT here
|
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 + \
|
COMMENT = r'\((?:' + FWS + r'?' + CCONTENT + \
|
||||||
r')*' + FWS + r'?\)' # see 3.2.3
|
r')*' + FWS + r'?\)' # see 3.2.3
|
||||||
CFWS = r'(?:' + FWS + r'?' + COMMENT + ')*(?:' + \
|
CFWS = r'(?:' + FWS + r'?' + COMMENT + ')*(?:' + \
|
||||||
@@ -81,8 +85,8 @@ ADDR_SPEC = LOCAL_PART + r'@' + DOMAIN # see 3.4.1
|
|||||||
# A valid address will match exactly the 3.4.1 addr-spec.
|
# A valid address will match exactly the 3.4.1 addr-spec.
|
||||||
VALID_ADDRESS_REGEXP = '^' + 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
|
"""Indicate whether the given string is a valid email address
|
||||||
according to the 'addr-spec' portion of RFC 2822 (see section
|
according to the 'addr-spec' portion of RFC 2822 (see section
|
||||||
3.4.1). Parts of the spec that are marked obsolete are *not*
|
3.4.1). Parts of the spec that are marked obsolete are *not*
|
||||||
@@ -90,13 +94,21 @@ def validate_email(email, check_mx=False,verify=False):
|
|||||||
depend on circular definitions in the spec may not pass, but in
|
depend on circular definitions in the spec may not pass, but in
|
||||||
general this should correctly identify any email address likely
|
general this should correctly identify any email address likely
|
||||||
to be in use as of 2011."""
|
to be in use as of 2011."""
|
||||||
|
if debug:
|
||||||
|
logger = logging.getLogger('validate_email')
|
||||||
|
logger.setLevel(logging.DEBUG)
|
||||||
|
else:
|
||||||
|
logger = None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
assert re.match(VALID_ADDRESS_REGEXP, email) is not None
|
assert re.match(VALID_ADDRESS_REGEXP, email) is not None
|
||||||
check_mx |= verify
|
check_mx |= verify
|
||||||
if check_mx:
|
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()
|
DNS.DiscoverNameServers()
|
||||||
hostname = email[email.find('@')+1:]
|
hostname = email[email.find('@') + 1:]
|
||||||
mx_hosts = DNS.mxlookup(hostname)
|
mx_hosts = DNS.mxlookup(hostname)
|
||||||
for mx in mx_hosts:
|
for mx in mx_hosts:
|
||||||
try:
|
try:
|
||||||
@@ -108,21 +120,61 @@ def validate_email(email, check_mx=False,verify=False):
|
|||||||
status, _ = smtp.helo()
|
status, _ = smtp.helo()
|
||||||
if status != 250:
|
if status != 250:
|
||||||
smtp.quit()
|
smtp.quit()
|
||||||
|
if debug:
|
||||||
|
logger.debug(u'%s answer: %s - %s', mx[1], status, _)
|
||||||
continue
|
continue
|
||||||
smtp.mail('')
|
smtp.mail('')
|
||||||
status, _ = smtp.rcpt(email)
|
status, _ = smtp.rcpt(email)
|
||||||
if status != 250:
|
if status == 250:
|
||||||
smtp.quit()
|
smtp.quit()
|
||||||
return False
|
|
||||||
smtp.quit()
|
|
||||||
break
|
|
||||||
except smtplib.SMTPServerDisconnected: #Server not permits verify user
|
|
||||||
break
|
|
||||||
except smtplib.SMTPConnectError:
|
|
||||||
continue
|
|
||||||
except (AssertionError, ServerError):
|
|
||||||
return False
|
|
||||||
return True
|
return True
|
||||||
|
if debug:
|
||||||
|
logger.debug(u'%s answer: %s - %s', mx[1], status, _)
|
||||||
|
smtp.quit()
|
||||||
|
except smtplib.SMTPServerDisconnected: # Server not permits verify user
|
||||||
|
if debug:
|
||||||
|
logger.debug(u'%s disconected.', mx[1])
|
||||||
|
except smtplib.SMTPConnectError:
|
||||||
|
if debug:
|
||||||
|
logger.debug(u'Unable to connect to %s.', mx[1])
|
||||||
|
return None
|
||||||
|
except AssertionError:
|
||||||
|
return False
|
||||||
|
except (ServerError, socket.error) as e:
|
||||||
|
if debug:
|
||||||
|
logger.debug('ServerError or socket.error exception raised (%s).', e)
|
||||||
|
return None
|
||||||
|
return True
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import time
|
||||||
|
while True:
|
||||||
|
email = raw_input('Enter email for validation: ')
|
||||||
|
|
||||||
|
mx = raw_input('Validate MX record? [yN] ')
|
||||||
|
if mx.strip().lower() == 'y':
|
||||||
|
mx = True
|
||||||
|
else:
|
||||||
|
mx = False
|
||||||
|
|
||||||
|
validate = raw_input('Try to contact server for address validation? [yN] ')
|
||||||
|
if validate.strip().lower() == 'y':
|
||||||
|
validate = True
|
||||||
|
else:
|
||||||
|
validate = False
|
||||||
|
|
||||||
|
logging.basicConfig()
|
||||||
|
|
||||||
|
result = validate_email(email, mx, validate, debug=True)
|
||||||
|
if result:
|
||||||
|
print "Valid!"
|
||||||
|
elif result is None:
|
||||||
|
print "I'm not sure."
|
||||||
|
else:
|
||||||
|
print "Invalid!"
|
||||||
|
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
|
||||||
# import sys
|
# import sys
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user