Handle inbound email integration alert getting multiple recipients (#4655)
Related to https://github.com/grafana/oncall-private/issues/2683 (when using mailgun backend, you can get multiple recipients, keep the first one matching the domain; other backends seem to just return the first one)
This commit is contained in:
parent
997167fcbe
commit
e583d5fc52
2 changed files with 88 additions and 15 deletions
|
|
@ -86,15 +86,18 @@ class InboundEmailWebhookView(AlertChannelDefiningMixin, APIView):
|
|||
# First try envelope_recipient field.
|
||||
# According to AnymailInboundMessage it's provided not by all ESPs.
|
||||
if message.envelope_recipient:
|
||||
try:
|
||||
token, domain = message.envelope_recipient.split("@")
|
||||
except ValueError:
|
||||
logger.error(
|
||||
f"get_integration_token_from_request: envelope_recipient field has unexpected format: {message.envelope_recipient}"
|
||||
)
|
||||
return None
|
||||
if domain == live_settings.INBOUND_EMAIL_DOMAIN:
|
||||
return token
|
||||
recipients = message.envelope_recipient.split(",")
|
||||
for recipient in recipients:
|
||||
# if there is more than one recipient, the first matching the expected domain will be used
|
||||
try:
|
||||
token, domain = recipient.strip().split("@")
|
||||
except ValueError:
|
||||
logger.error(
|
||||
f"get_integration_token_from_request: envelope_recipient field has unexpected format: {message.envelope_recipient}"
|
||||
)
|
||||
continue
|
||||
if domain == live_settings.INBOUND_EMAIL_DOMAIN:
|
||||
return token
|
||||
else:
|
||||
logger.info("get_integration_token_from_request: message.envelope_recipient is not present")
|
||||
"""
|
||||
|
|
@ -152,7 +155,10 @@ class InboundEmailWebhookView(AlertChannelDefiningMixin, APIView):
|
|||
|
||||
def get_sender_from_email_message(self, email: AnymailInboundMessage) -> str:
|
||||
try:
|
||||
sender = email.from_email.addr_spec
|
||||
if isinstance(email.from_email, list):
|
||||
sender = email.from_email[0].addr_spec
|
||||
else:
|
||||
sender = email.from_email.addr_spec
|
||||
except AnymailInvalidAddress as e:
|
||||
# wasn't able to parse email address from message, return raw value from "From" header
|
||||
logger.warning(
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import json
|
||||
from textwrap import dedent
|
||||
|
||||
import pytest
|
||||
from anymail.inbound import AnymailInboundMessage
|
||||
|
|
@ -9,8 +10,19 @@ from rest_framework.test import APIClient
|
|||
from apps.email.inbound import InboundEmailWebhookView
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"recipients,expected",
|
||||
[
|
||||
("{token}@example.com", status.HTTP_200_OK),
|
||||
("{token}@example.com, another@example.com", status.HTTP_200_OK),
|
||||
("{token}@example.com, another@example.com", status.HTTP_200_OK),
|
||||
("{token}@other.com, {token}@example.com", status.HTTP_400_BAD_REQUEST),
|
||||
],
|
||||
)
|
||||
@pytest.mark.django_db
|
||||
def test_amazon_ses_provider_load(settings, make_organization_and_user_with_token, make_alert_receive_channel):
|
||||
def test_amazon_ses_provider_load(
|
||||
settings, make_organization_and_user_with_token, make_alert_receive_channel, recipients, expected
|
||||
):
|
||||
settings.INBOUND_EMAIL_ESP = "amazon_ses"
|
||||
settings.INBOUND_EMAIL_DOMAIN = "example.com"
|
||||
|
||||
|
|
@ -19,10 +31,10 @@ def test_amazon_ses_provider_load(settings, make_organization_and_user_with_toke
|
|||
organization, _, token = make_organization_and_user_with_token()
|
||||
_ = make_alert_receive_channel(organization, token=dummy_channel_token)
|
||||
|
||||
recipient = f"{dummy_channel_token}@example.com"
|
||||
recipients = recipients.format(token=dummy_channel_token)
|
||||
mime = f"""From: sender@example.com
|
||||
Subject: Dummy email message
|
||||
To: {recipient}
|
||||
To: {recipients}
|
||||
Content-Type: text/plain
|
||||
|
||||
Hello!
|
||||
|
|
@ -30,7 +42,7 @@ def test_amazon_ses_provider_load(settings, make_organization_and_user_with_toke
|
|||
|
||||
message = {
|
||||
"notificationType": "Received",
|
||||
"receipt": {"action": {"type": "SNS"}, "recipients": [recipient]},
|
||||
"receipt": {"action": {"type": "SNS"}, "recipients": recipients.split(",")},
|
||||
"content": mime,
|
||||
}
|
||||
|
||||
|
|
@ -54,7 +66,62 @@ def test_amazon_ses_provider_load(settings, make_organization_and_user_with_toke
|
|||
HTTP_X_AMZ_SNS_MESSAGE_ID=dummy_sns_message_id,
|
||||
)
|
||||
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
assert response.status_code == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"recipients,expected",
|
||||
[
|
||||
("{token}@example.com", status.HTTP_200_OK),
|
||||
("{token}@example.com, another@example.com", status.HTTP_200_OK),
|
||||
("{token}@example.com, another@example.com", status.HTTP_200_OK),
|
||||
("{token}@other.com, {token}@example.com", status.HTTP_200_OK),
|
||||
("{token}@other.com, {token}@another.com", status.HTTP_400_BAD_REQUEST),
|
||||
],
|
||||
)
|
||||
@pytest.mark.django_db
|
||||
def test_mailgun_provider_load(
|
||||
settings, make_organization_and_user_with_token, make_alert_receive_channel, recipients, expected
|
||||
):
|
||||
settings.INBOUND_EMAIL_ESP = "mailgun"
|
||||
settings.INBOUND_EMAIL_DOMAIN = "example.com"
|
||||
settings.INBOUND_EMAIL_WEBHOOK_SECRET = "secret"
|
||||
|
||||
dummy_channel_token = "dummy-channel-token"
|
||||
|
||||
organization, _, token = make_organization_and_user_with_token()
|
||||
_ = make_alert_receive_channel(organization, token=dummy_channel_token)
|
||||
|
||||
recipients = recipients.format(token=dummy_channel_token)
|
||||
raw_event = {
|
||||
"token": "06c96bafc3f42a66b9edd546347a2fe18dc23461fe80dc52f0",
|
||||
"timestamp": "1461261330",
|
||||
"signature": "dbb05e62be402448b36ffb81f6abfb888273c95617aa077b4da355b25bab3670",
|
||||
"recipient": "{recipients}".format(recipients=recipients),
|
||||
"sender": "envelope-from@example.org",
|
||||
"body-mime": dedent(
|
||||
"""\
|
||||
From: sender@example.com
|
||||
Subject: Dummy email message
|
||||
To: {recipients}
|
||||
Content-Type: text/plain
|
||||
|
||||
Hello!
|
||||
--94eb2c05e174adb140055b6339c5--
|
||||
""".format(
|
||||
recipients=recipients
|
||||
)
|
||||
),
|
||||
}
|
||||
|
||||
client = APIClient()
|
||||
response = client.post(
|
||||
reverse("integrations:inbound_email_webhook"),
|
||||
data=raw_event,
|
||||
HTTP_AUTHORIZATION=token,
|
||||
)
|
||||
|
||||
assert response.status_code == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue