ETRN client utility

This is a small utility that uses Python’s SMTP module to send RFC1985 ETRN requests to one or more mail servers. This would normally be used to tell the backup mail servers for a domain to attempt delivery after the primary MX comes back online. I wrote it, because after much searching, the best I could find were scripts using telnet or nc, and with no error handling. This program should speak SMTP correctly, and will return error codes and messages in the case of failure.

   1 #!/usr/bin/python
   2 
   3 # Andrew Baumann andrewb@cse.unsw.edu.au, 2007/04/29
   4 
   5 import sys, smtplib, socket
   6 from optparse import OptionParser
   7 
   8 def parse_args():
   9     mydomain = socket.getfqdn()
  10     p = OptionParser(usage='%prog [option] host...',
  11                      description=sends an ETRN request (RFC1985) to one or more mail servers)
  12     p.add_option('-d', dest='domain',
  13                  help='domain to request mail for, default: %s' % mydomain)
  14     p.add_option('-v', action='store_const', dest='verbose', const=True,
  15                  help='verbose/debug output')
  16     p.set_defaults(domain=mydomain, verbose=False)
  17     options, args = p.parse_args()
  18     if len(args) == 0:
  19         p.error('no host specified')
  20     return options, args
  21 
  22 def do_etrn(host, domain, smtpobj=None):
  23     if smtpobj is None:
  24         smtpobj = smtplib.SMTP()
  25     smtpobj.connect(host)
  26     smtpobj.ehlo()
  27     (retcode, retmsg) = smtpobj.docmd('ETRN', domain)
  28     if retcode / 10 != 25:
  29         raise smtplib.SMTPResponseException(retcode, retmsg)
  30     smtpobj.quit()
  31 
  32 def main():
  33     options, hosts = parse_args()
  34     errorflag = False
  35     smtpobj = smtplib.SMTP()
  36     smtpobj.set_debuglevel(options.verbose)
  37 
  38     for host in hosts:
  39         def error(msg):
  40             sys.stderr.write('Error: %s: %s\n' % (host, msg))
  41 
  42         try:
  43             do_etrn(host, options.domain, smtpobj)
  44         except socket.error, (errnum, errmsg):
  45             error(errmsg)
  46             errorflag = True
  47         except smtplib.SMTPResponseException, e:
  48             error('%d %s' % (e.smtp_code, e.smtp_error))
  49             errorflag = True
  50         except smtplib.SMTPException:
  51             error('Generic SMTP error')
  52             errorflag = True
  53 
  54     return errorflag
  55 
  56 if __name__ == __main__:
  57     if main():
  58         sys.exit(1)

etrn.py

Published by

ab

Well, AB's just this guy, you know?