Skip to content

Instantly share code, notes, and snippets.

@etes
Forked from blinks/smtpcheck.py
Last active March 18, 2020 12:44
Show Gist options
  • Select an option

  • Save etes/5ee3b9b51a2e1c3b0208 to your computer and use it in GitHub Desktop.

Select an option

Save etes/5ee3b9b51a2e1c3b0208 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
# Check that a particular email address exists.
# Adam Blinkinsop <[email protected]>
usage = 'usage: %prog [options] email1 [email2 [...]]'
import logging
import os
import re
import smtplib
# Match the mail exchanger line in nslookup output.
MX = re.compile(r'^.*\s+mail exchanger = (?P<priority>\d+) (?P<host>\S+)\s*$')
def verify(addr, local_addr='[email protected]'):
"""Verify the existance of a single email address."""
logging.debug('Verifying existance of %r', addr)
# Find mail exchanger of this address.
host = addr.rsplit('@', 2)[1]
p = os.popen('nslookup -q=mx %s' % host, 'r')
mxes = list()
for line in p:
m = MX.match(line)
if m is not None:
mxes.append(m.group('host'))
logging.debug('Found %d mail exchangers for %s.', len(mxes), host)
if len(mxes) == 0:
return False
else:
host = mxes[0]
# Connect to the mail server and check.
logging.debug('Checking address with %s.', host)
server = smtplib.SMTP(host)
server.ehlo_or_helo_if_needed()
code, response = server.docmd('mail from:', '[email protected]')
logging.debug('MAIL FROM command returned %d: %r', code, response)
code, response = server.docmd('rcpt to:', addr)
logging.debug('RCPT TO command returned %d: %r', code, response)
server.quit()
return (code // 100 == 2)
def main(*args, **opts):
"""Handle execution from the command line."""
for addr in args:
if verify(addr, local_addr=opts['local_addr']):
print '%r exists.' % addr
else:
print '%s DOES NOT exist.' % addr
def flags():
"""Parse options from the command line."""
from optparse import OptionParser
parser = OptionParser(usage=usage)
parser.add_option('-f', '--from',
dest='local_addr', default='[email protected]',
help='email address to appear to be from')
parser.add_option('-d', '--debug',
action='store_const', const=logging.DEBUG, dest='log_level',
help='log everything')
parser.add_option('-v', '--verbose',
action='store_const', const=logging.INFO, dest='log_level',
help='log everything but debugging messages')
parser.add_option('-q', '--quiet',
action='store_const', const=logging.ERROR, dest='log_level',
help='only log errors')
opts, args = parser.parse_args()
logging.basicConfig(level=opts.log_level)
return opts, args
if __name__ == '__main__':
opts, args = flags()
main(*args, **opts.__dict__)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment