launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #19018
[Merge] lp:~cjwatson/launchpad/basemailer-oops into lp:launchpad
Colin Watson has proposed merging lp:~cjwatson/launchpad/basemailer-oops into lp:launchpad.
Commit message:
Improve OOPS logging when BaseMailer fails to send a message.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/basemailer-oops/+merge/264856
Improve OOPS logging when BaseMailer fails to send a message.
Future scripts using BaseMailer will need to pass in a request argument. At the moment, all uses of BaseMailer are in jobs or in the buildmaster, and I think in both those cases it's OK just to not bother passing in a request.
--
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~cjwatson/launchpad/basemailer-oops into lp:launchpad.
=== modified file 'lib/lp/services/mail/basemailer.py'
--- lib/lp/services/mail/basemailer.py 2012-06-29 08:40:05 +0000
+++ lib/lp/services/mail/basemailer.py 2015-07-15 14:35:40 +0000
@@ -1,4 +1,4 @@
-# Copyright 2009-2011 Canonical Ltd. This software is licensed under the
+# Copyright 2009-2015 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
"""Base class for sending out emails."""
@@ -9,6 +9,10 @@
import logging
from smtplib import SMTPException
+import sys
+
+from zope.component import getUtility
+from zope.error.interfaces import IErrorReportingUtility
from lp.services.mail.helpers import get_email_template
from lp.services.mail.notificationrecipientset import NotificationRecipientSet
@@ -34,7 +38,7 @@
def __init__(self, subject, template_name, recipients, from_address,
delta=None, message_id=None, notification_type=None,
- mail_controller_class=None):
+ mail_controller_class=None, request=None):
"""Constructor.
:param subject: A Python dict-replacement template for the subject
@@ -48,6 +52,7 @@
not supplied, random message-ids will be used.
:param mail_controller_class: The class of the mail controller to
use to send the mails. Defaults to `MailController`.
+ :param request: An `IErrorReportRequest` to use when logging OOPSes.
"""
self._subject_template = subject
self._template_name = template_name
@@ -62,6 +67,7 @@
if mail_controller_class is None:
mail_controller_class = MailController
self._mail_controller_class = mail_controller_class
+ self.request = request
def _getToAddresses(self, recipient, email):
return [format_address(recipient.displayname, email)]
@@ -153,17 +159,25 @@
try:
ctrl = self.generateEmail(email, recipient)
ctrl.send()
- except SMTPException as e:
+ except SMTPException:
# If the initial sending failed, try again without
# attachments.
try:
ctrl = self.generateEmail(
email, recipient, force_no_attachments=True)
ctrl.send()
- except SMTPException as e:
- # Don't want an entire stack trace, just some details.
- self.logger.warning(
- 'send failed for %s, %s' % (email, e))
+ except SMTPException:
+ error_utility = getUtility(IErrorReportingUtility)
+ oops_vars = {
+ "message_id": self.message_id,
+ "notification_type": self.notification_type,
+ "recipient": recipient.id,
+ }
+ with error_utility.oopsMessage(oops_vars):
+ oops = error_utility.raising(
+ sys.exc_info(), self.request)
+ self.logger.info(
+ "Mail resulted in OOPS: %s" % oops.get("id"))
class RecipientReason:
=== modified file 'lib/lp/services/mail/tests/test_basemailer.py'
--- lib/lp/services/mail/tests/test_basemailer.py 2012-01-01 02:58:52 +0000
+++ lib/lp/services/mail/tests/test_basemailer.py 2015-07-15 14:35:40 +0000
@@ -1,4 +1,4 @@
-# Copyright 2009 Canonical Ltd. This software is licensed under the
+# Copyright 2009-2015 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
"""Tests for the BaseMailer class."""
@@ -150,6 +150,9 @@
notifications = pop_notifications()
self.assertEqual(1, len(notifications))
self.assertEqual('Good <good@xxxxxxxxxxx>', notifications[0]['To'])
+ # And an OOPS is logged.
+ self.assertEqual(1, len(self.oopses))
+ self.assertIn("SMTPException: boom", self.oopses[0]["tb_text"])
def test_sendall_first_failure_strips_attachments(self):
# If sending an email fails, we try again without the (almost
@@ -184,3 +187,5 @@
self.assertEqual(
'Excessively large attachments removed.',
bad_parts[1].get_payload(decode=True))
+ # And no OOPS is logged.
+ self.assertEqual(0, len(self.oopses))
Follow ups