mailtb.py
changeset 4 bc4d326e5a46
parent 3 7062c52d3999
child 5 610fe1138532
equal deleted inserted replaced
3:7062c52d3999 4:bc4d326e5a46
    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 error_page = """<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
       
    22   "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
       
    23 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de">
       
    24   <head>
       
    25     <title>Internal Server Error</title>
       
    26     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
       
    27   </head>
       
    28   <body>
       
    29     <h1>Internal Server Error</h1>
       
    30     <p>So wie es aussieht, ging bei der Bearbeitung Ihrer Anfrage etwas
       
    31     schief.</p>
       
    32     <p>Sofern Sie den Fehler verursacht haben, dürfen Sie jetzt ein schlechtes
       
    33     Gewissen haben.<br />
       
    34     Die Administration wird sich bei nächster Gelegenheit um das Problem
       
    35     kümmern. Bitte haben Sie dafür etwas Verständnis.</p>
       
    36     <h2>Error 500</h2>
       
    37     <p>Sorry</p>
       
    38   </body>
       
    39 </html>"""
       
    40 msg_body = """Hi,
       
    41 
       
    42 an uncaught exception has occurred. The details are as follows:
       
    43 
       
    44   Type:    %(extype)s
       
    45   Message: %(message)s
       
    46 
       
    47 Traceback (most recent call last):
       
    48 %(traceback)s
       
    49 
       
    50 Additional information:
       
    51   Date:     %(date)s
       
    52   Request:  %(method)s %(uri)s %(protocol)s
       
    53   Referrer: %(referer)s
       
    54   Client:   %(addr)s/%(port)s
       
    55   U-Agent:  %(agent)s
       
    56 """
       
    57 msg_header = """Date: %(date)s
       
    58 From: "%(from_name)s" <%(from_addr)s>
       
    59 To: "%(rcpt_name)s" <%(rcpt_addr)s>
       
    60 Subject: %(subject)s
       
    61 Message-ID: <%(now)f.%(now)X@mailtb.%(host)s>
       
    62 Auto-Submitted: auto-generated
       
    63 MIME-Version: 1.0
       
    64 Content-Type: text/plain; charset=utf-8
       
    65 Content-Transfer-Encoding: 8bit
       
    66 """
    21 config = {# sender information
    67 config = {# sender information
    22           'from_addr': '',
    68           'from_addr': '',
    23           'from_name': '',
    69           'from_name': '',
    24           # smtp auth information (if necessary, else leave blank)
    70           # smtp auth information (if necessary, else leave blank)
    25           'auth_user': '',
    71           'auth_user': '',
    34           # subject of the email
    80           # subject of the email
    35           'subject': 'Exception Notification',
    81           'subject': 'Exception Notification',
    36           # make sure that the web server can write to this file
    82           # make sure that the web server can write to this file
    37           'error_log': '/tmp/mailtb_error.log'
    83           'error_log': '/tmp/mailtb_error.log'
    38          }
    84          }
    39 
       
    40 http_status = {200: 'OK',
    85 http_status = {200: 'OK',
    41                500: 'Internal Server Error'}
    86                500: 'Internal Server Error'}
    42 
    87 
    43 def log_mail_error(error, timestamp):
    88 def log_mail_error(error, timestamp):
    44     try:
    89     try:
    59         for k in ('auth_pass', 'auth_user', 'error_log', 'from_addr',
   104         for k in ('auth_pass', 'auth_user', 'error_log', 'from_addr',
    60                 'from_name', 'rcpt_addr', 'rcpt_name', 'smtp_host', 'subject'):
   105                 'from_name', 'rcpt_addr', 'rcpt_name', 'smtp_host', 'subject'):
    61             config[k] = get('mailtb', k)
   106             config[k] = get('mailtb', k)
    62         config['smtp_port'] = cp.getint('mailtb', 'smtp_port')
   107         config['smtp_port'] = cp.getint('mailtb', 'smtp_port')
    63         config['smtp_tls'] = cp.getboolean('mailtb', 'smtp_tls')
   108         config['smtp_tls'] = cp.getboolean('mailtb', 'smtp_tls')
    64     del(cp)
       
    65 
   109 
    66 def send_header(status=500, xhtml=False):
   110 def send_header(status=500, xhtml=False):
    67     s = status if status in http_status else 500
   111     s = status if status in http_status else 500
    68     write = sys.stdout.write
   112     write = sys.stdout.write
    69     if not xhtml:
   113     if not xhtml:
    73     write('Status: %d %s\r\n\r\n' % (s, http_status[s]))
   117     write('Status: %d %s\r\n\r\n' % (s, http_status[s]))
    74     sys.stdout.flush()
   118     sys.stdout.flush()
    75 
   119 
    76 def send_error_page():
   120 def send_error_page():
    77     send_header(500, True)
   121     send_header(500, True)
    78     print """<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
   122     print error_page
    79   "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
       
    80 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de">
       
    81   <head>
       
    82     <title>Internal Server Error</title>
       
    83     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
       
    84   </head>
       
    85   <body>
       
    86     <h1>Internal Server Error</h1>
       
    87     <p>So wie es aussieht, ging bei der Bearbeitung Ihrer Anfrage etwas
       
    88     schief.</p>
       
    89     <p>Sofern Sie den Fehler verursacht haben, dürfen Sie jetzt ein schlechtes
       
    90     Gewissen haben.<br />
       
    91     Die Administration wird sich bei nächster Gelegenheit um das Problem
       
    92     kümmern. Bitte haben Sie dafür etwas Verständnis.</p>
       
    93     <h2>Error 500</h2>
       
    94     <p>Sorry</p>
       
    95   </body>
       
    96 </html>"""
       
    97 
   123 
    98 def send_mail(info):
   124 def send_mail(info):
    99     global config
   125     global config
   100     config['now'] = time()
   126     config['now'] = time()
   101     config['host'] = info['host'] if info['host'] != 'n/a' else 'localhost'
   127     config['host'] = info['host'] if info['host'] != 'n/a' else 'localhost'
   102     config['date'] = strftime('%a, %d %b %Y %H:%M:%S +0000',
   128     config['date'] = strftime('%a, %d %b %Y %H:%M:%S +0000',
   103             gmtime(config['now']))
   129             gmtime(config['now']))
   104     body = """Hi,
       
   105 
       
   106 an uncaught exception has occurred. The details are as follows:
       
   107 
       
   108   Type:    %(extype)s
       
   109   Message: %(message)s
       
   110 
       
   111 Traceback (most recent call last):
       
   112 %(traceback)s
       
   113 
       
   114 Additional information:
       
   115   Date:     %(date)s
       
   116   Request:  %(method)s %(uri)s %(protocol)s
       
   117   Referrer: %(referer)s
       
   118   Client:   %(addr)s/%(port)s
       
   119   U-Agent:  %(agent)s
       
   120 """ % info
       
   121     header = """Date: %(date)s
       
   122 From: "%(from_name)s" <%(from_addr)s>
       
   123 To: "%(rcpt_name)s" <%(rcpt_addr)s>
       
   124 Subject: %(subject)s
       
   125 Message-ID: <%(now)f.%(now)X@mailtb.%(host)s>
       
   126 Auto-Submitted: auto-generated
       
   127 MIME-Version: 1.0
       
   128 Content-Type: text/plain; charset=utf-8
       
   129 Content-Transfer-Encoding: 8bit
       
   130 """ % config
       
   131     
   130     
   132     try:
   131     try:
   133         if config['smtp_port'] != 465:
   132         if config['smtp_port'] != 465:
   134             smtp = smtplib.SMTP(config['smtp_host'], config['smtp_port'])
   133             smtp = smtplib.SMTP(config['smtp_host'], config['smtp_port'])
   135             if config['smtp_tls']:
   134             if config['smtp_tls']:
   137         else:
   136         else:
   138             smtp = smtplib.SMTP_SSL(config['smtp_host'], config['smtp_port'])
   137             smtp = smtplib.SMTP_SSL(config['smtp_host'], config['smtp_port'])
   139         if len(config['auth_user']) and len(config['auth_pass']):
   138         if len(config['auth_user']) and len(config['auth_pass']):
   140             smtp.login(config['auth_user'], config['auth_pass'])
   139             smtp.login(config['auth_user'], config['auth_pass'])
   141         smtp.sendmail(config['from_addr'], config['rcpt_addr'],
   140         smtp.sendmail(config['from_addr'], config['rcpt_addr'],
   142                 '\n'.join((header, body)))
   141                 '\n'.join((msg_header %config, msg_body %info)))
   143     except Exception, e:
   142     except Exception, e:
   144         # try to log it (fire and forget)
   143         # try to log it (fire and forget)
   145         log_mail_error(e, config['now'])
   144         log_mail_error(e, config['now'])
   146     finally:
   145     finally:
   147         smtp.quit()
   146         smtp.quit()
   161     info['date'] = ctime()
   160     info['date'] = ctime()
   162     for k in ('HTTP_HOST', 'HTTP_REFERER', 'HTTP_USER_AGENT', 'REMOTE_ADDR',
   161     for k in ('HTTP_HOST', 'HTTP_REFERER', 'HTTP_USER_AGENT', 'REMOTE_ADDR',
   163              'REMOTE_PORT', 'REQUEST_METHOD', 'REQUEST_URI', 'SERVER_PROTOCOL'):
   162              'REMOTE_PORT', 'REQUEST_METHOD', 'REQUEST_URI', 'SERVER_PROTOCOL'):
   164         info[k.split('_')[-1].lower()] = env[k] if env.has_key(k) else 'n/a'
   163         info[k.split('_')[-1].lower()] = env[k] if env.has_key(k) else 'n/a'
   165 
   164 
       
   165     send_error_page()
   166     send_mail(info)
   166     send_mail(info)
   167     send_error_page()
       
   168 
   167 
   169 def enable(filename=None):
   168 def enable(filename=None):
   170     if filename is not None:
   169     if filename is not None:
   171         load_config(filename)
   170         load_config(filename)
   172     sys.excepthook = mailtbhook
   171     sys.excepthook = mailtbhook