Skip to content

Commit

Permalink
[OSIS-8748] Better manage the errors when sending the emails
Browse files Browse the repository at this point in the history
  • Loading branch information
jcougnaud committed Dec 8, 2023
1 parent cf89da6 commit 0e3ac11
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 12 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ from osis_notification.contrib.handlers import EmailNotificationHandler
recipient = Person.objects.get(user__username="jmr")
language = recipient.language
tokens = {"username": person.user.username}
email_message = generate_email(your_mail_template_id, language, tokens, recipients=[recipient])
email_message = generate_email(your_mail_template_id, language, tokens, recipients=[recipient.email])
email_notification = EmailNotificationHandler.create(email_message)
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,13 @@ class Command(BaseCommand):
help = "Send all the email notifications."

def handle(self, *args, **options):
errors = []

for notification in EmailNotification.objects.pending():
EmailNotificationHandler.process(notification)
try:
EmailNotificationHandler.process(notification)
except Exception as e:
errors.append(e)

if errors:
raise errors[0]
45 changes: 35 additions & 10 deletions osis_notification/tests/test_commands.py
Original file line number Diff line number Diff line change
@@ -1,28 +1,30 @@
from datetime import timedelta
from unittest.mock import patch

from django.conf import settings
from django.core.management import call_command
from django.test import override_settings, TestCase
from django.test import override_settings
from django.utils.timezone import now

from base.tests.factories.person import PersonFactory
from osis_notification.contrib.handlers import EmailNotificationHandler
from osis_notification.contrib.notification import (
EmailNotification as EmailNotificationType,
)
from osis_notification.models import EmailNotification, WebNotification
from osis_notification.models import EmailNotification, WebNotification, Notification
from osis_notification.models.enums import NotificationStates
from osis_notification.tests import TestCase
from osis_notification.tests.factories import (
EmailNotificationFactory,
WebNotificationFactory,
)

from osis_common.messaging.mail_sender_classes import MessageHistorySender


class SendNotificationsTest(TestCase):
@classmethod
def setUpTestData(cls):
cls.web_notification = WebNotificationFactory()
def setUp(self):
self.web_notification = WebNotificationFactory()
# It's seems a bit more complicated to create the email message payload in a
# factory so I leave it like this for the moment
email_notification_data = {
Expand All @@ -33,35 +35,58 @@ def setUpTestData(cls):
}
email_notification = EmailNotificationType(**email_notification_data)
email_message = EmailNotificationHandler.build(email_notification)
cls.email_notification = EmailNotificationFactory(
self.email_notification = EmailNotificationFactory(
payload=email_message.as_string(),
person=email_notification_data["recipient"],
)

def test_send_email_notifications(self):
# ensure email notification is in pending state after creation
self.assertEqual(
self.email_notification.state, NotificationStates.PENDING_STATE.name
self.email_notification.state,
NotificationStates.PENDING_STATE.name,
)
with self.assertNumQueriesLessThan(6):
call_command("send_email_notifications")
self.email_notification.refresh_from_db()
# now email notification should be in sent state
self.assertEqual(
self.email_notification.state, NotificationStates.SENT_STATE.name
self.email_notification.state,
NotificationStates.SENT_STATE.name,
)

def test_send_email_notifications_with_failure(self):
second_email_notification = EmailNotificationFactory(
payload=self.email_notification.payload,
person=self.email_notification.person,
)

original_send_mail = Notification.save
with patch.object(Notification, 'save') as sender_mock:
sender_mock.side_effect = [original_send_mail, ValueError('Invalid value')]

with self.assertRaises(ValueError):
call_command("send_email_notifications")

self.email_notification.refresh_from_db()
self.assertEqual(self.email_notification.state, NotificationStates.SENT_STATE.name)

second_email_notification.refresh_from_db()
self.assertEqual(second_email_notification.state, NotificationStates.PENDING_STATE.name)

def test_send_web_notifications(self):
# ensure web notification is in pending state after creation
self.assertEqual(
self.web_notification.state, NotificationStates.PENDING_STATE.name
self.web_notification.state,
NotificationStates.PENDING_STATE.name,
)
with self.assertNumQueriesLessThan(3):
call_command("send_web_notifications")
self.web_notification.refresh_from_db()
# now web notification should be in sent state
self.assertEqual(
self.web_notification.state, NotificationStates.SENT_STATE.name
self.web_notification.state,
NotificationStates.SENT_STATE.name,
)


Expand Down

0 comments on commit 0e3ac11

Please sign in to comment.