mailtb.py
changeset 3 7062c52d3999
parent 2 731c43b63c9d
child 4 bc4d326e5a46
equal deleted inserted replaced
2:731c43b63c9d 3:7062c52d3999
    16 import smtplib
    16 import smtplib
    17 import traceback
    17 import traceback
    18 from os import environ as env
    18 from os import environ as env
    19 from time import ctime, gmtime, localtime, strftime, time
    19 from time import ctime, gmtime, localtime, strftime, time
    20 
    20 
    21 mail_config = {# sender information
    21 config = {# sender information
    22                'from_addr': '',
    22           'from_addr': '',
    23                'from_name': '',
    23           'from_name': '',
    24                # smtp auth information (if necessary, else leave blank)
    24           # smtp auth information (if necessary, else leave blank)
    25                'auth_user': '',
    25           'auth_user': '',
    26                'auth_pass': '',
    26           'auth_pass': '',
    27                # recipient information
    27           # recipient information
    28                'rcpt_addr': '',
    28           'rcpt_addr': '',
    29                'rcpt_name': '',
    29           'rcpt_name': '',
    30                # smtp server information
    30           # smtp server information
    31                'smtp_host': 'localhost',
    31           'smtp_host': 'localhost',
    32                'smtp_port': 25, # 25 smtp, 587 submission, 465 ssmtp (obsolete)
    32           'smtp_port': 25, # 25 smtp, 587 submission, 465 ssmtp (obsolete)
    33                'smtp_tls':  False, # True or False (use starttls on port 25/587)
    33           'smtp_tls':  False, # True or False (use starttls on port 25/587)
    34                # subject of the email
    34           # subject of the email
    35                'subject': 'Exception Notification',
    35           'subject': 'Exception Notification',
    36                # make sure that the web server can write to this file
    36           # make sure that the web server can write to this file
    37                'error_log': '/tmp/mailtb_error.log'
    37           'error_log': '/tmp/mailtb_error.log'
    38               }
    38          }
    39 
    39 
    40 http_status = {200: 'OK',
    40 http_status = {200: 'OK',
    41                500: 'Internal Server Error'}
    41                500: 'Internal Server Error'}
    42 
    42 
    43 def log_mail_error(error, timestamp):
    43 def log_mail_error(error, timestamp):
    44     try:
    44     try:
    45         prefix = strftime('%b %d %H:%M:%S', localtime(timestamp))
    45         prefix = strftime('%b %d %H:%M:%S', localtime(timestamp))
    46         line = error.message if len(error.message) else error.args
    46         line = error.message if len(error.message) else error.args
    47         logfile = open(mail_config['error_log'], 'a')
    47         logfile = open(config['error_log'], 'a')
    48         logfile.write('%s %s: %s\n' % (prefix, error.__class__.__name__, line))
    48         logfile.write('%s %s: %s\n' % (prefix, error.__class__.__name__, line))
    49         logfile.close()
    49         logfile.close()
    50     except:
    50     except:
    51         pass
    51         pass
       
    52 
       
    53 def load_config(filename):
       
    54     from ConfigParser import ConfigParser
       
    55     cp = ConfigParser()
       
    56     if len(cp.read(filename)):
       
    57         global config
       
    58         get = cp.get
       
    59         for k in ('auth_pass', 'auth_user', 'error_log', 'from_addr',
       
    60                 'from_name', 'rcpt_addr', 'rcpt_name', 'smtp_host', 'subject'):
       
    61             config[k] = get('mailtb', k)
       
    62         config['smtp_port'] = cp.getint('mailtb', 'smtp_port')
       
    63         config['smtp_tls'] = cp.getboolean('mailtb', 'smtp_tls')
       
    64     del(cp)
    52 
    65 
    53 def send_header(status=500, xhtml=False):
    66 def send_header(status=500, xhtml=False):
    54     s = status if status in http_status else 500
    67     s = status if status in http_status else 500
    55     write = sys.stdout.write
    68     write = sys.stdout.write
    56     if not xhtml:
    69     if not xhtml:
    81     <p>Sorry</p>
    94     <p>Sorry</p>
    82   </body>
    95   </body>
    83 </html>"""
    96 </html>"""
    84 
    97 
    85 def send_mail(info):
    98 def send_mail(info):
    86     global mail_config
    99     global config
    87     mail_config['now'] = time()
   100     config['now'] = time()
    88     mail_config['host'] = info['host'] if info['host'] != 'n/a' else 'localhost'
   101     config['host'] = info['host'] if info['host'] != 'n/a' else 'localhost'
    89     mail_config['date'] = strftime('%a, %d %b %Y %H:%M:%S +0000',
   102     config['date'] = strftime('%a, %d %b %Y %H:%M:%S +0000',
    90             gmtime(mail_config['now']))
   103             gmtime(config['now']))
    91     body = """Hi,
   104     body = """Hi,
    92 
   105 
    93 an uncaught exception has occurred. The details are as follows:
   106 an uncaught exception has occurred. The details are as follows:
    94 
   107 
    95   Type:    %(extype)s
   108   Type:    %(extype)s
   112 Message-ID: <%(now)f.%(now)X@mailtb.%(host)s>
   125 Message-ID: <%(now)f.%(now)X@mailtb.%(host)s>
   113 Auto-Submitted: auto-generated
   126 Auto-Submitted: auto-generated
   114 MIME-Version: 1.0
   127 MIME-Version: 1.0
   115 Content-Type: text/plain; charset=utf-8
   128 Content-Type: text/plain; charset=utf-8
   116 Content-Transfer-Encoding: 8bit
   129 Content-Transfer-Encoding: 8bit
   117 """ % mail_config
   130 """ % config
   118     
   131     
   119     try:
   132     try:
   120         if mail_config['smtp_port'] != 465:
   133         if config['smtp_port'] != 465:
   121             smtp = smtplib.SMTP(mail_config['smtp_host'],
   134             smtp = smtplib.SMTP(config['smtp_host'], config['smtp_port'])
   122                     mail_config['smtp_port'])
   135             if config['smtp_tls']:
   123             if mail_config['smtp_tls']:
       
   124                 smtp.starttls()
   136                 smtp.starttls()
   125         else:
   137         else:
   126             smtp = smtplib.SMTP_SSL(mail_config['smtp_host'],
   138             smtp = smtplib.SMTP_SSL(config['smtp_host'], config['smtp_port'])
   127                     mail_config['smtp_port'])
   139         if len(config['auth_user']) and len(config['auth_pass']):
   128         if len(mail_config['auth_user']) and len(mail_config['auth_pass']):
   140             smtp.login(config['auth_user'], config['auth_pass'])
   129             smtp.login(mail_config['auth_user'], mail_config['auth_pass'])
   141         smtp.sendmail(config['from_addr'], config['rcpt_addr'],
   130         smtp.sendmail(mail_config['from_addr'], mail_config['rcpt_addr'],
       
   131                 '\n'.join((header, body)))
   142                 '\n'.join((header, body)))
   132     except Exception, e:
   143     except Exception, e:
   133         # try to log it (fire and forget)
   144         # try to log it (fire and forget)
   134         log_mail_error(e, mail_config['now'])
   145         log_mail_error(e, config['now'])
   135     finally:
   146     finally:
   136         smtp.quit()
   147         smtp.quit()
   137 
   148 
   138 def mailtbhook(extype, exval, extb):
   149 def mailtbhook(extype, exval, extb):
   139     info = {}
   150     info = {}
   153         info[k.split('_')[-1].lower()] = env[k] if env.has_key(k) else 'n/a'
   164         info[k.split('_')[-1].lower()] = env[k] if env.has_key(k) else 'n/a'
   154 
   165 
   155     send_mail(info)
   166     send_mail(info)
   156     send_error_page()
   167     send_error_page()
   157 
   168 
   158 def enable():
   169 def enable(filename=None):
       
   170     if filename is not None:
       
   171         load_config(filename)
   159     sys.excepthook = mailtbhook
   172     sys.excepthook = mailtbhook