Allow no-auth SMTP connection for email notifications (#759)
* DEFAULT_FROM_EMAIL -> EMAIL_FROM * add EMAIL_FROM live setting * EMAIL_FROM -> EMAIL_FROM_ADDRESS * merge dev * add test for get_from_email * allow live settings to be null on internal API * remove redundant tests
This commit is contained in:
parent
e9df5ab5c9
commit
e2456315af
7 changed files with 41 additions and 66 deletions
|
|
@ -195,6 +195,7 @@ Grafana OnCall is capable of sending emails using SMTP as a user notification st
|
|||
- `EMAIL_HOST_USER` - SMTP server user
|
||||
- `EMAIL_HOST_PASSWORD` - SMTP server password
|
||||
- `EMAIL_PORT` (default is `587`) - SMTP server port
|
||||
- `EMAIL_USE_TLS` (default is `True`) - to enable/disable TLS
|
||||
- `EMAIL_USE_TLS` (default is `True`) - To enable/disable TLS
|
||||
- `EMAIL_FROM_ADDRESS` (optional) - Email address used to send emails. If not specified, `EMAIL_HOST_USER` will be used.
|
||||
|
||||
After enabling the email integration, it will be possible to use the `Notify by email` notification step in user settings.
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ from apps.base.models import LiveSetting
|
|||
|
||||
class LiveSettingSerializer(serializers.ModelSerializer):
|
||||
id = serializers.CharField(read_only=True, source="public_primary_key")
|
||||
value = serializers.JSONField(allow_null=False)
|
||||
value = serializers.JSONField(allow_null=True)
|
||||
|
||||
class Meta:
|
||||
model = LiveSetting
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ class LiveSetting(models.Model):
|
|||
"EMAIL_HOST_USER",
|
||||
"EMAIL_HOST_PASSWORD",
|
||||
"EMAIL_USE_TLS",
|
||||
"EMAIL_FROM_ADDRESS",
|
||||
"TWILIO_ACCOUNT_SID",
|
||||
"TWILIO_AUTH_TOKEN",
|
||||
"TWILIO_NUMBER",
|
||||
|
|
@ -61,6 +62,7 @@ class LiveSetting(models.Model):
|
|||
"EMAIL_HOST_USER": "SMTP server user",
|
||||
"EMAIL_HOST_PASSWORD": "SMTP server password",
|
||||
"EMAIL_USE_TLS": "SMTP enable/disable TLS",
|
||||
"EMAIL_FROM_ADDRESS": "Email address used to send emails. If not specified, EMAIL_HOST_USER will be used.",
|
||||
"SLACK_SIGNING_SECRET": (
|
||||
"Check <a href='"
|
||||
"https://grafana.com/docs/grafana-cloud/oncall/open-source/#slack-setup"
|
||||
|
|
|
|||
|
|
@ -16,6 +16,16 @@ MAX_RETRIES = 1 if settings.DEBUG else 10
|
|||
logger = get_task_logger(__name__)
|
||||
|
||||
|
||||
def get_from_email(user):
|
||||
if live_settings.EMAIL_FROM_ADDRESS:
|
||||
return live_settings.EMAIL_FROM_ADDRESS
|
||||
|
||||
if settings.LICENSE == settings.CLOUD_LICENSE_NAME:
|
||||
return "oncall@{}.grafana.net".format(user.organization.stack_slug)
|
||||
|
||||
return live_settings.EMAIL_HOST_USER
|
||||
|
||||
|
||||
@shared_dedicated_queue_retry_task(autoretry_for=(Exception,), retry_backoff=True, max_retries=MAX_RETRIES)
|
||||
def notify_user_async(user_pk, alert_group_pk, notification_policy_pk):
|
||||
# imported here to avoid circular import error
|
||||
|
|
@ -76,13 +86,9 @@ def notify_user_async(user_pk, alert_group_pk, notification_policy_pk):
|
|||
subject, html_message = build_subject_and_message(alert_group, emails_left)
|
||||
|
||||
message = strip_tags(html_message)
|
||||
from_email = get_from_email(user)
|
||||
recipient_list = [user.email]
|
||||
|
||||
if settings.LICENSE == settings.CLOUD_LICENSE_NAME:
|
||||
email_from = "oncall@{}.grafana.net".format(user.organization.stack_slug)
|
||||
else:
|
||||
email_from = live_settings.EMAIL_HOST_USER
|
||||
|
||||
connection = get_connection(
|
||||
host=live_settings.EMAIL_HOST,
|
||||
port=live_settings.EMAIL_PORT,
|
||||
|
|
@ -94,7 +100,7 @@ def notify_user_async(user_pk, alert_group_pk, notification_policy_pk):
|
|||
)
|
||||
|
||||
try:
|
||||
send_mail(subject, message, email_from, recipient_list, html_message=html_message, connection=connection)
|
||||
send_mail(subject, message, from_email, recipient_list, html_message=html_message, connection=connection)
|
||||
EmailMessage.objects.create(
|
||||
represents_alert_group=alert_group,
|
||||
notification_policy=notification_policy,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ from django.core import mail
|
|||
from django.core.mail.backends.locmem import EmailBackend
|
||||
|
||||
from apps.base.models import UserNotificationPolicy, UserNotificationPolicyLogRecord
|
||||
from apps.email.tasks import notify_user_async
|
||||
from apps.email.tasks import get_from_email, notify_user_async
|
||||
from apps.user_management.subscription_strategy.free_public_beta_subscription_strategy import (
|
||||
FreePublicBetaSubscriptionStrategy,
|
||||
)
|
||||
|
|
@ -158,69 +158,35 @@ def test_notify_user_no_emails_left(
|
|||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_notify_user_from_email_oss(
|
||||
@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,
|
||||
make_token_for_organization,
|
||||
make_alert_receive_channel,
|
||||
make_alert_group,
|
||||
make_alert,
|
||||
make_user_notification_policy,
|
||||
license_name,
|
||||
email_host_user,
|
||||
email_from_address,
|
||||
expected,
|
||||
):
|
||||
settings.LICENSE = settings.OPEN_SOURCE_LICENSE_NAME
|
||||
settings.EMAIL_BACKEND = "django.core.mail.backends.locmem.EmailBackend"
|
||||
settings.EMAIL_HOST = "test"
|
||||
settings.EMAIL_HOST_USER = "test@test.com"
|
||||
settings.EMAIL_HOST_PASSWORD = "password"
|
||||
|
||||
organization = make_organization(stack_slug="example")
|
||||
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 mail.outbox[0].from_email == "test@test.com"
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_notify_user_from_email_cloud(
|
||||
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.LICENSE = settings.CLOUD_LICENSE_NAME
|
||||
settings.EMAIL_BACKEND = "django.core.mail.backends.locmem.EmailBackend"
|
||||
settings.EMAIL_HOST = "test"
|
||||
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)
|
||||
|
||||
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 mail.outbox[0].from_email == "oncall@slug.grafana.net"
|
||||
assert get_from_email(user) == expected
|
||||
|
|
|
|||
|
|
@ -568,7 +568,7 @@ EMAIL_HOST_USER = os.getenv("EMAIL_HOST_USER")
|
|||
EMAIL_HOST_PASSWORD = os.getenv("EMAIL_HOST_PASSWORD")
|
||||
EMAIL_PORT = getenv_integer("EMAIL_PORT", 587)
|
||||
EMAIL_USE_TLS = getenv_boolean("EMAIL_USE_TLS", True)
|
||||
DEFAULT_FROM_EMAIL = os.getenv("DEFAULT_FROM_EMAIL")
|
||||
EMAIL_FROM_ADDRESS = os.getenv("EMAIL_FROM_ADDRESS")
|
||||
|
||||
if FEATURE_EMAIL_INTEGRATION_ENABLED:
|
||||
EXTRA_MESSAGING_BACKENDS = [("apps.email.backend.EmailBackend", 8)]
|
||||
|
|
|
|||
|
|
@ -366,7 +366,7 @@ rabbitmq-password
|
|||
key: smtp-password
|
||||
- name: EMAIL_USE_TLS
|
||||
value: {{ .Values.oncall.smtp.tls | toString | title | quote }}
|
||||
- name: DEFAULT_FROM_EMAIL
|
||||
- name: EMAIL_FROM_ADDRESS
|
||||
value: {{ .Values.oncall.smtp.fromEmail | quote }}
|
||||
{{- else -}}
|
||||
- name: FEATURE_EMAIL_INTEGRATION_ENABLED
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue