142 lines
4.5 KiB
Python
142 lines
4.5 KiB
Python
# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
|
|
# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
|
|
|
|
from email.mime.text import MIMEText
|
|
from email.mime.multipart import MIMEMultipart
|
|
import smtplib
|
|
import time
|
|
try:
|
|
from socket import sslerror
|
|
except ImportError:
|
|
sslerror = None
|
|
from paste.exceptions import formatter
|
|
|
|
class Reporter(object):
|
|
|
|
def __init__(self, **conf):
|
|
for name, value in conf.items():
|
|
if not hasattr(self, name):
|
|
raise TypeError(
|
|
"The keyword argument %s was not expected"
|
|
% name)
|
|
setattr(self, name, value)
|
|
self.check_params()
|
|
|
|
def check_params(self):
|
|
pass
|
|
|
|
def format_date(self, exc_data):
|
|
return time.strftime('%c', exc_data.date)
|
|
|
|
def format_html(self, exc_data, **kw):
|
|
return formatter.format_html(exc_data, **kw)
|
|
|
|
def format_text(self, exc_data, **kw):
|
|
return formatter.format_text(exc_data, **kw)
|
|
|
|
class EmailReporter(Reporter):
|
|
|
|
to_addresses = None
|
|
from_address = None
|
|
smtp_server = 'localhost'
|
|
smtp_username = None
|
|
smtp_password = None
|
|
smtp_use_tls = False
|
|
subject_prefix = ''
|
|
|
|
def report(self, exc_data):
|
|
msg = self.assemble_email(exc_data)
|
|
server = smtplib.SMTP(self.smtp_server)
|
|
if self.smtp_use_tls:
|
|
server.ehlo()
|
|
server.starttls()
|
|
server.ehlo()
|
|
if self.smtp_username and self.smtp_password:
|
|
server.login(self.smtp_username, self.smtp_password)
|
|
server.sendmail(self.from_address,
|
|
self.to_addresses, msg.as_string())
|
|
try:
|
|
server.quit()
|
|
except sslerror:
|
|
# sslerror is raised in tls connections on closing sometimes
|
|
pass
|
|
|
|
def check_params(self):
|
|
if not self.to_addresses:
|
|
raise ValueError("You must set to_addresses")
|
|
if not self.from_address:
|
|
raise ValueError("You must set from_address")
|
|
if isinstance(self.to_addresses, (str, unicode)):
|
|
self.to_addresses = [self.to_addresses]
|
|
|
|
def assemble_email(self, exc_data):
|
|
short_html_version = self.format_html(
|
|
exc_data, show_hidden_frames=False)
|
|
long_html_version = self.format_html(
|
|
exc_data, show_hidden_frames=True)
|
|
text_version = self.format_text(
|
|
exc_data, show_hidden_frames=False)
|
|
msg = MIMEMultipart()
|
|
msg.set_type('multipart/alternative')
|
|
msg.preamble = msg.epilogue = ''
|
|
text_msg = MIMEText(text_version)
|
|
text_msg.set_type('text/plain')
|
|
text_msg.set_param('charset', 'ASCII')
|
|
msg.attach(text_msg)
|
|
html_msg = MIMEText(short_html_version)
|
|
html_msg.set_type('text/html')
|
|
# @@: Correct character set?
|
|
html_msg.set_param('charset', 'UTF-8')
|
|
html_long = MIMEText(long_html_version)
|
|
html_long.set_type('text/html')
|
|
html_long.set_param('charset', 'UTF-8')
|
|
msg.attach(html_msg)
|
|
msg.attach(html_long)
|
|
subject = '%s: %s' % (exc_data.exception_type,
|
|
formatter.truncate(str(exc_data.exception_value)))
|
|
msg['Subject'] = self.subject_prefix + subject
|
|
msg['From'] = self.from_address
|
|
msg['To'] = ', '.join(self.to_addresses)
|
|
return msg
|
|
|
|
class LogReporter(Reporter):
|
|
|
|
filename = None
|
|
show_hidden_frames = True
|
|
|
|
def check_params(self):
|
|
assert self.filename is not None, (
|
|
"You must give a filename")
|
|
|
|
def report(self, exc_data):
|
|
text = self.format_text(
|
|
exc_data, show_hidden_frames=self.show_hidden_frames)
|
|
f = open(self.filename, 'a')
|
|
try:
|
|
f.write(text + '\n' + '-'*60 + '\n')
|
|
finally:
|
|
f.close()
|
|
|
|
class FileReporter(Reporter):
|
|
|
|
file = None
|
|
show_hidden_frames = True
|
|
|
|
def check_params(self):
|
|
assert self.file is not None, (
|
|
"You must give a file object")
|
|
|
|
def report(self, exc_data):
|
|
text = self.format_text(
|
|
exc_data, show_hidden_frames=self.show_hidden_frames)
|
|
self.file.write(text + '\n' + '-'*60 + '\n')
|
|
|
|
class WSGIAppReporter(Reporter):
|
|
|
|
def __init__(self, exc_data):
|
|
self.exc_data = exc_data
|
|
|
|
def __call__(self, environ, start_response):
|
|
start_response('500 Server Error', [('Content-type', 'text/html')])
|
|
return [formatter.format_html(self.exc_data)]
|