oncall-engine/engine/apps/email/tests/test_notify_user.py
Michael Derynck aebd98b8f9
Change email templating to not wrap user defined templates (#3862)
# What this PR does
Change email notification templates to not wrap the user template in a
fixed body. Info has been moved to a footer. The title now also matches
the template from the user exactly and will only get a default message
if the user template result is empty.
Example:

![Screenshot from 2024-02-08
12-16-38](https://github.com/grafana/oncall/assets/28077050/bb59b7a7-7ec8-4d9d-8aef-8aff012c74f7)

## Which issue(s) this PR fixes
#3857 

## Checklist

- [x] Unit, integration, and e2e (if applicable) tests updated
- [x] Documentation added (or `pr:no public docs` PR label added if not
required)
- [x] `CHANGELOG.md` updated (or `pr:no changelog` PR label added if not
required)
2024-02-09 19:03:25 +00:00

214 lines
6.8 KiB
Python

import socket
from unittest.mock import patch
import pytest
from django.core import mail
from django.core.mail.backends.locmem import EmailBackend
from apps.base.models import UserNotificationPolicy, UserNotificationPolicyLogRecord
from apps.email.alert_rendering import build_subject_and_message
from apps.email.tasks import get_from_email, notify_user_async
from apps.user_management.subscription_strategy.free_public_beta_subscription_strategy import (
FreePublicBetaSubscriptionStrategy,
)
@pytest.mark.django_db
def test_notify_user(
settings,
make_organization,
make_user_for_organization,
make_token_for_organization,
make_alert_receive_channel,
make_alert_group,
make_alert,
make_user_notification_policy,
):
settings.EMAIL_BACKEND = "django.core.mail.backends.locmem.EmailBackend"
settings.EMAIL_HOST = "test"
organization = make_organization()
user = make_user_for_organization(organization)
alert_receive_channel = make_alert_receive_channel(organization)
alert_group = make_alert_group(alert_receive_channel)
make_alert(alert_group=alert_group, raw_request_data=alert_receive_channel.config.example_payload)
notification_policy = make_user_notification_policy(
user,
UserNotificationPolicy.Step.NOTIFY,
notify_by=8,
important=False,
)
notify_user_async(user.pk, alert_group.pk, notification_policy.pk)
assert len(mail.outbox) == 1
log_record = notification_policy.personal_log_records.last()
assert log_record.type == UserNotificationPolicyLogRecord.TYPE_PERSONAL_NOTIFICATION_SUCCESS
@pytest.mark.django_db
def test_notify_empty_email_host(
settings,
make_organization,
make_user_for_organization,
make_token_for_organization,
make_alert_receive_channel,
make_alert_group,
make_alert,
make_user_notification_policy,
):
settings.EMAIL_BACKEND = "django.core.mail.backends.locmem.EmailBackend"
settings.EMAIL_HOST = None
organization = make_organization()
user = make_user_for_organization(organization)
alert_receive_channel = make_alert_receive_channel(organization)
alert_group = make_alert_group(alert_receive_channel)
make_alert(alert_group=alert_group, raw_request_data=alert_receive_channel.config.example_payload)
notification_policy = make_user_notification_policy(
user,
UserNotificationPolicy.Step.NOTIFY,
notify_by=8,
important=False,
)
notify_user_async(user.pk, alert_group.pk, notification_policy.pk)
assert len(mail.outbox) == 0
log_record = notification_policy.personal_log_records.last()
assert log_record.type == UserNotificationPolicyLogRecord.TYPE_PERSONAL_NOTIFICATION_FAILED
@pytest.mark.django_db
def test_notify_user_bad_smtp_host(
settings,
make_organization,
make_user_for_organization,
make_token_for_organization,
make_alert_receive_channel,
make_alert_group,
make_alert,
make_user_notification_policy,
):
settings.EMAIL_BACKEND = "django.core.mail.backends.locmem.EmailBackend"
settings.EMAIL_HOST = "test"
organization = make_organization()
user = make_user_for_organization(organization)
alert_receive_channel = make_alert_receive_channel(organization)
alert_group = make_alert_group(alert_receive_channel)
make_alert(alert_group=alert_group, raw_request_data=alert_receive_channel.config.example_payload)
notification_policy = make_user_notification_policy(
user,
UserNotificationPolicy.Step.NOTIFY,
notify_by=8,
important=False,
)
with patch.object(EmailBackend, "send_messages", side_effect=socket.gaierror):
notify_user_async(user.pk, alert_group.pk, notification_policy.pk)
assert len(mail.outbox) == 0
log_record = notification_policy.personal_log_records.last()
assert log_record.type == UserNotificationPolicyLogRecord.TYPE_PERSONAL_NOTIFICATION_FAILED
@pytest.mark.django_db
def test_notify_user_no_emails_left(
settings,
make_organization,
make_user_for_organization,
make_token_for_organization,
make_alert_receive_channel,
make_alert_group,
make_alert,
make_user_notification_policy,
):
settings.EMAIL_BACKEND = "django.core.mail.backends.locmem.EmailBackend"
settings.EMAIL_HOST = "test"
organization = make_organization()
user = make_user_for_organization(organization)
alert_receive_channel = make_alert_receive_channel(organization)
alert_group = make_alert_group(alert_receive_channel)
make_alert(alert_group=alert_group, raw_request_data=alert_receive_channel.config.example_payload)
notification_policy = make_user_notification_policy(
user,
UserNotificationPolicy.Step.NOTIFY,
notify_by=8,
important=False,
)
with patch.object(FreePublicBetaSubscriptionStrategy, "emails_left", return_value=0):
notify_user_async(user.pk, alert_group.pk, notification_policy.pk)
assert len(mail.outbox) == 0
log_record = notification_policy.personal_log_records.last()
assert log_record.type == UserNotificationPolicyLogRecord.TYPE_PERSONAL_NOTIFICATION_FAILED
assert log_record.notification_error_code == UserNotificationPolicyLogRecord.ERROR_NOTIFICATION_MAIL_LIMIT_EXCEEDED
@pytest.mark.django_db
@pytest.mark.parametrize(
"license_name,email_host_user,email_from_address,expected",
[
("Cloud", "user", "from_address", "from_address"),
("OpenSource", "user", "from_address", "from_address"),
("Cloud", "user", None, "oncall@slug.grafana.net"),
("Cloud", None, None, "oncall@slug.grafana.net"),
("OpenSource", "user", None, "user"),
("OpenSource", None, None, None),
],
)
def test_get_from_email(
settings,
make_organization,
make_user_for_organization,
license_name,
email_host_user,
email_from_address,
expected,
):
settings.EMAIL_BACKEND = "django.core.mail.backends.locmem.EmailBackend"
settings.EMAIL_HOST = "test"
settings.EMAIL_HOST_PASSWORD = "password"
settings.LICENSE = license_name
settings.EMAIL_HOST_USER = email_host_user
settings.EMAIL_FROM_ADDRESS = email_from_address
organization = make_organization(stack_slug="slug")
user = make_user_for_organization(organization)
assert get_from_email(user) == expected
@pytest.mark.django_db
def test_subject_newlines_removed(
make_organization,
make_alert_receive_channel,
make_alert_group,
make_alert,
):
organization = make_organization()
alert_receive_channel = make_alert_receive_channel(
organization, messaging_backends_templates={"EMAIL": {"title": "test\nnewlines"}}
)
alert_group = make_alert_group(alert_receive_channel)
make_alert(alert_group, raw_request_data={})
subject, _ = build_subject_and_message(alert_group, 1)
assert subject == "testnewlines"