From cae902a37373719896d15beccbed2f71597362ef Mon Sep 17 00:00:00 2001 From: Bill Fenner Date: Mon, 4 Jun 2007 13:52:34 +0000 Subject: [PATCH] Add two middleware classes: - SQLLogMiddleware. This logs any INSERT or UPDATE performed by a request. - SMTPExceptionMiddleware. This renders a "please try again" (template email_failed.html) message when an attempt to send email failed. This uses a bit of a hack, in that the middleware looks explicitly for smtplib.SMTPException, and smtplib can raise other exceptions (particularly socket errors). utils/mail/send_smtp catches all exceptions and reraises non-smtplib exceptions as fake smtplib exceptions, and the middleware undoes the wrapping. - Legacy-Id: 224 --- ietf/middleware.py | 51 ++++++++++++++++++++++++++++++++++++++-------- ietf/settings.py | 2 ++ ietf/utils/mail.py | 11 +++++++--- 3 files changed, 53 insertions(+), 11 deletions(-) diff --git a/ietf/middleware.py b/ietf/middleware.py index 0c1c3bda9..bd7af951e 100644 --- a/ietf/middleware.py +++ b/ietf/middleware.py @@ -1,9 +1,16 @@ - -# From http://www.djangosnippets.org/snippets/172/ -# Uses python-utidylib, http://utidylib.berlios.de/, -# which uses HTML Tidy, http://tidy.sourceforge.net/ - -import tidy +try: + import tidy + tidyavail = True +except ImportError: + tidyavail = False +from django.db import connection +from django.shortcuts import render_to_response +from django.template import RequestContext +from ietf.utils import log +import re +import smtplib +import sys +import traceback options = dict( output_xhtml=True, @@ -16,11 +23,39 @@ options = dict( class PrettifyMiddleware(object): - """Prettify middleware""" + """Prettify middleware + From http://www.djangosnippets.org/snippets/172/ + Uses python-utidylib, http://utidylib.berlios.de/, + which uses HTML Tidy, http://tidy.sourceforge.net/ + """ def process_response(self, request, response): - if response.headers['Content-Type'].split(';', 1)[0] in ['text/html']: + if tidyavail and response.headers['Content-Type'].split(';', 1)[0] in ['text/html']: content = response.content content = str(tidy.parseString(content, **options)) response.content = content return response + +class SQLLogMiddleware(object): + def process_response(self, request, response): + for q in connection.queries: + if re.match('(update|insert)', q['sql'], re.IGNORECASE): + log(q['sql']) + return response + +class SMTPExceptionMiddleware(object): + def process_exception(self, request, exception): + if isinstance(exception, smtplib.SMTPException): + type = sys.exc_info()[0] + value = sys.exc_info()[1] + # See if it's a non-smtplib exception that we faked + if type == smtplib.SMTPException and len(value.args) == 1 and isinstance(value.args[0], dict) and value.args[0].has_key('really'): + orig = value.args[0] + type = orig['really'] + tb = traceback.format_tb(orig['tb']) + value = orig['value'] + else: + tb = traceback.format_tb(sys.exc_info()[2]) + return render_to_response('email_failed.html', {'exception': type, 'args': value, 'traceback': "".join(tb)}, + context_instance=RequestContext(request)) + return None diff --git a/ietf/settings.py b/ietf/settings.py index c0f898caf..1e97c20d8 100644 --- a/ietf/settings.py +++ b/ietf/settings.py @@ -81,6 +81,8 @@ MIDDLEWARE_CLASSES = ( 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.middleware.doc.XViewMiddleware', # 'ietf.middleware.PrettifyMiddleware', + 'ietf.middleware.SQLLogMiddleware', + 'ietf.middleware.SMTPExceptionMiddleware', 'django.middleware.transaction.TransactionMiddleware', ) diff --git a/ietf/utils/mail.py b/ietf/utils/mail.py index 4b85fd88d..a50655f76 100644 --- a/ietf/utils/mail.py +++ b/ietf/utils/mail.py @@ -28,6 +28,7 @@ def send_smtp(msg): add_headers(msg) (fname, frm) = parseaddr(msg.get('From')) to = [addr for name, addr in getaddresses(msg.get_all('To') + msg.get_all('Cc', []))] + server = None try: server = smtplib.SMTP(settings.EMAIL_HOST, settings.EMAIL_PORT) if settings.DEBUG: @@ -37,11 +38,15 @@ def send_smtp(msg): server.sendmail(frm, to, msg.as_string()) # note: should pay attention to the return code, as it may # indicate that someone didn't get the email. - except smtplib.SMTPException: - server.quit() + except: + if server: + server.quit() # need to improve log message log("got exception '%s' (%s) trying to send email from '%s' to %s subject '%s'" % (sys.exc_info()[0], sys.exc_info()[1], frm, to, msg.get('Subject', '[no subject]'))) - raise + if isinstance(sys.exc_info()[0], smtplib.SMTPException): + raise + else: + raise smtplib.SMTPException({'really': sys.exc_info()[0], 'value': sys.exc_info()[1], 'tb': sys.exc_info()[2]}) server.quit() log("sent email from '%s' to %s subject '%s'" % (frm, to, msg.get('Subject', '[no subject]')))