def _getAndCheckSentNotifications(self, notifications_to_send): """Return the notifications that were successfully sent. It calls get_email_notifications() with the supplied notifications and return the ones that were actually sent. It also checks that the notifications got sent to the correct addresses. """ email_notifications = get_email_notifications(notifications_to_send) to_addresses = set() sent_notifications = [] for notifications, omitted, messages in email_notifications: for message in messages: to_addresses.add(message['to']) recipients = {} for notification in notifications: for recipient in notification.recipients: for address in get_contact_email_addresses( recipient.person): recipients[address] = recipient expected_to_addresses = recipients.keys() self.assertEqual( sorted(expected_to_addresses), sorted(to_addresses)) sent_notifications += notifications return sent_notifications
def main(self): notifications_sent = False bug_notification_set = getUtility(IBugNotificationSet) deferred_notifications = \ bug_notification_set.getDeferredNotifications() process_deferred_notifications(deferred_notifications) pending_notifications = get_email_notifications( bug_notification_set.getNotificationsToSend()) for (bug_notifications, omitted_notifications, messages) in pending_notifications: for message in messages: self.logger.info("Notifying %s about bug %d." % ( message['To'], bug_notifications[0].bug.id)) sendmail(message) self.logger.debug(message.as_string()) for notification in bug_notifications: notification.date_emailed = UTC_NOW notification.status = BugNotificationStatus.SENT for notification in omitted_notifications: notification.date_emailed = UTC_NOW notification.status = BugNotificationStatus.OMITTED notifications_sent = True # Commit after each batch of email sent, so that we won't # re-mail the notifications in case of something going wrong # in the middle. self.txn.commit() if not notifications_sent: self.logger.debug("No notifications are pending to be sent.")
def get_messages(self): notifications = self.notification_set.getNotificationsToSend() email_notifications = get_email_notifications(notifications) for (bug_notifications, omitted_notifications, messages) in email_notifications: for message in messages: yield message, message.get_payload(decode=True)
def test_early_exit(self): # When not-yet-exhausted generators need to be deallocated Python # raises a GeneratorExit exception at the point of their last yield. # The get_email_notifications generator was catching that exception in # a try/except and logging it, leading to bug 994694. This test # verifies that the fix for that bug (re-raising the exception) stays # in place. # Set up logging so we can later assert that no exceptions are logged. log_output = StringIO.StringIO() logger = logging.getLogger() log_handler = logging.StreamHandler(log_output) logger.addHandler(logging.StreamHandler(log_output)) self.addCleanup(logger.removeHandler, log_handler) # Make some data to feed to get_email_notifications. person = getUtility(IPersonSet).getByEmail('*****@*****.**') msg = getUtility(IMessageSet).fromText('', '', owner=person) bug = MockBug(1, person) # We need more than one notification because we want the generator to # stay around after being started. Consuming the first starts it but # since the second exists, the generator stays active. notifications = [ MockBugNotification( message=msg, bug=bug, is_comment=True, date_emailed=None), MockBugNotification( message=msg, bug=bug, is_comment=True, date_emailed=None), ] # Now we create the generator, start it, and then close it, triggering # a GeneratorExit exception inside the generator. email_notifications = get_email_notifications(notifications) email_notifications.next() email_notifications.close() # Verify that no "Error while building email notifications." is logged. self.assertEqual('', log_output.getvalue())