diff --git a/src/backend/mailbox_manager/models.py b/src/backend/mailbox_manager/models.py index 77ba8e5db..4f9dd78f5 100644 --- a/src/backend/mailbox_manager/models.py +++ b/src/backend/mailbox_manager/models.py @@ -73,6 +73,17 @@ def get_abilities(self, user): "manage_accesses": is_owner_or_admin, } + def send_notification(self, subject, message): + """ + Notify owners and admins of the domain + """ + for access in self.accesses.filter( + role__in=[MailDomainRoleChoices.OWNER, MailDomainRoleChoices.ADMIN] + ).all(): + access.user.email_user( + subject=subject, message=message, from_email=settings.DEFAULT_FROM_EMAIL + ) + class MailDomainAccess(BaseModel): """Allow to manage users' accesses to mail domains.""" diff --git a/src/backend/mailbox_manager/tasks.py b/src/backend/mailbox_manager/tasks.py index 4b39fcea6..595402da1 100644 --- a/src/backend/mailbox_manager/tasks.py +++ b/src/backend/mailbox_manager/tasks.py @@ -31,6 +31,16 @@ def fetch_domains_status(): else: if old_status != domain.status: update_count += 1 + # Send notification to owners and admins of the domain + # when its status changes to failed or enabled + if domain.status == MailDomainStatusChoices.FAILED: + domain.send_notification( + subject='Domain status changed', message='Domain is down', + ) + elif domain.status == MailDomainStatusChoices.ENABLED: + domain.send_notification( + subject='Domain status changed', message='Domain is up', + ) else: check_count += 1 return "Domains processed: %s updated, %s checked" % (update_count, check_count) diff --git a/src/backend/mailbox_manager/tests/test_tasks.py b/src/backend/mailbox_manager/tests/test_tasks.py index 82438c3ac..627f1860c 100644 --- a/src/backend/mailbox_manager/tests/test_tasks.py +++ b/src/backend/mailbox_manager/tests/test_tasks.py @@ -4,6 +4,9 @@ import json import re +from unittest import mock + +from django.conf import settings import pytest import responses @@ -16,19 +19,30 @@ @responses.activate -def test_fetch_domain_status_task_success(caplog): +def test_fetch_domain_status_task_success(caplog): # pylint: disable=too-many-locals """Test fetch domain status from dimail task""" caplog.set_level("INFO") domain_enabled1 = factories.MailDomainEnabledFactory() domain_enabled2 = factories.MailDomainEnabledFactory() + owner_domain_enabled2 = factories.MailDomainAccessFactory( + domain=domain_enabled2, role=enums.MailDomainRoleChoices.OWNER + ).user + admin_domain_enabled2 = factories.MailDomainAccessFactory( + domain=domain_enabled2, role=enums.MailDomainRoleChoices.ADMIN + ).user domain_disabled = factories.MailDomainFactory( status=enums.MailDomainStatusChoices.DISABLED ) domain_failed = factories.MailDomainFactory( status=enums.MailDomainStatusChoices.FAILED ) - + owner_domain_failed = factories.MailDomainAccessFactory( + domain=domain_failed, role=enums.MailDomainRoleChoices.OWNER + ).user + admin_domain_failed = factories.MailDomainAccessFactory( + domain=domain_failed, role=enums.MailDomainRoleChoices.ADMIN + ).user body_content_ok1 = CHECK_DOMAIN_OK.copy() body_content_ok1["name"] = domain_enabled1.name @@ -53,7 +67,8 @@ def test_fetch_domain_status_task_success(caplog): status=200, content_type="application/json", ) - tasks.fetch_domains_status() + with mock.patch("django.core.mail.send_mail") as mock_send: + tasks.fetch_domains_status() domain_enabled1.refresh_from_db() domain_enabled2.refresh_from_db() domain_disabled.refresh_from_db() @@ -64,6 +79,35 @@ def test_fetch_domain_status_task_success(caplog): assert domain_enabled2.status == enums.MailDomainStatusChoices.FAILED # Status of the failed domain has changed to enabled assert domain_failed.status == enums.MailDomainStatusChoices.ENABLED + # Check notification was sent to owners and admins + assert mock_send.call_count == 4 + calls = [ + mock.call( + "Domain status changed", + "Domain is down", + settings.DEFAULT_FROM_EMAIL, + [owner_domain_enabled2.email], + ), + mock.call( + "Domain status changed", + "Domain is down", + settings.DEFAULT_FROM_EMAIL, + [admin_domain_enabled2.email], + ), + mock.call( + "Domain status changed", + "Domain is up", + settings.DEFAULT_FROM_EMAIL, + [owner_domain_failed.email], + ), + mock.call( + "Domain status changed", + "Domain is up", + settings.DEFAULT_FROM_EMAIL, + [admin_domain_failed.email], + ), + ] + mock_send.assert_has_calls(calls, any_order=True) # Disabled domain was excluded assert domain_disabled.status == enums.MailDomainStatusChoices.DISABLED # Check that the task logged the correct messages