Skip to content

Commit

Permalink
Brevo: SendinBlue compatibility
Browse files Browse the repository at this point in the history
(See previous commit.)

- Maintain deprecated compatibility
  versions on the old names/URLs.
  (Split into separate commit
  to make renamed files more
  obvious.)
  • Loading branch information
medmunds committed Mar 12, 2024
1 parent c7ee59c commit 948ab2b
Show file tree
Hide file tree
Showing 4 changed files with 191 additions and 0 deletions.
20 changes: 20 additions & 0 deletions anymail/backends/sendinblue.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import warnings

from ..exceptions import AnymailDeprecationWarning
from .brevo import EmailBackend as BrevoEmailBackend


class EmailBackend(BrevoEmailBackend):
"""
Deprecated compatibility backend for old Brevo name "SendinBlue".
"""

esp_name = "SendinBlue"

def __init__(self, **kwargs):
warnings.warn(
"`anymail.backends.sendinblue.EmailBackend` has been renamed"
" `anymail.backends.brevo.EmailBackend`.",
AnymailDeprecationWarning,
)
super().__init__(**kwargs)
16 changes: 16 additions & 0 deletions anymail/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
from .webhooks.postmark import PostmarkInboundWebhookView, PostmarkTrackingWebhookView
from .webhooks.resend import ResendTrackingWebhookView
from .webhooks.sendgrid import SendGridInboundWebhookView, SendGridTrackingWebhookView
from .webhooks.sendinblue import (
SendinBlueInboundWebhookView,
SendinBlueTrackingWebhookView,
)
from .webhooks.sparkpost import (
SparkPostInboundWebhookView,
SparkPostTrackingWebhookView,
Expand Down Expand Up @@ -68,6 +72,12 @@
SendGridInboundWebhookView.as_view(),
name="sendgrid_inbound_webhook",
),
path(
# Compatibility for old SendinBlue esp_name; use Brevo in new code
"sendinblue/inbound/",
SendinBlueInboundWebhookView.as_view(),
name="sendinblue_inbound_webhook",
),
path(
"sparkpost/inbound/",
SparkPostInboundWebhookView.as_view(),
Expand Down Expand Up @@ -118,6 +128,12 @@
SendGridTrackingWebhookView.as_view(),
name="sendgrid_tracking_webhook",
),
path(
# Compatibility for old SendinBlue esp_name; use Brevo in new code
"sendinblue/tracking/",
SendinBlueTrackingWebhookView.as_view(),
name="sendinblue_tracking_webhook",
),
path(
"sparkpost/tracking/",
SparkPostTrackingWebhookView.as_view(),
Expand Down
38 changes: 38 additions & 0 deletions anymail/webhooks/sendinblue.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import warnings

from ..exceptions import AnymailDeprecationWarning
from .brevo import BrevoInboundWebhookView, BrevoTrackingWebhookView


class SendinBlueTrackingWebhookView(BrevoTrackingWebhookView):
"""
Deprecated compatibility tracking webhook for old Brevo name "SendinBlue".
"""

esp_name = "SendinBlue"

def __init__(self, **kwargs):
warnings.warn(
"Anymail's SendinBlue webhook URLs are deprecated."
" Update your Brevo transactional email webhook URL to change"
" 'anymail/sendinblue' to 'anymail/brevo'.",
AnymailDeprecationWarning,
)
super().__init__(**kwargs)


class SendinBlueInboundWebhookView(BrevoInboundWebhookView):
"""
Deprecated compatibility inbound webhook for old Brevo name "SendinBlue".
"""

esp_name = "SendinBlue"

def __init__(self, **kwargs):
warnings.warn(
"Anymail's SendinBlue webhook URLs are deprecated."
" Update your Brevo inbound webhook URL to change"
" 'anymail/sendinblue' to 'anymail/brevo'.",
AnymailDeprecationWarning,
)
super().__init__(**kwargs)
117 changes: 117 additions & 0 deletions tests/test_sendinblue_deprecations.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
from unittest.mock import ANY

from django.core.mail import EmailMessage, send_mail
from django.test import ignore_warnings, override_settings, tag

from anymail.exceptions import AnymailConfigurationError, AnymailDeprecationWarning
from anymail.webhooks.sendinblue import (
SendinBlueInboundWebhookView,
SendinBlueTrackingWebhookView,
)

from .mock_requests_backend import RequestsBackendMockAPITestCase
from .webhook_cases import WebhookTestCase


@tag("brevo", "sendinblue")
@override_settings(
EMAIL_BACKEND="anymail.backends.sendinblue.EmailBackend",
ANYMAIL={"SENDINBLUE_API_KEY": "test_api_key"},
)
@ignore_warnings(category=AnymailDeprecationWarning)
class SendinBlueBackendDeprecationTests(RequestsBackendMockAPITestCase):
DEFAULT_RAW_RESPONSE = (
b'{"messageId":"<[email protected]>"}'
)
DEFAULT_STATUS_CODE = 201 # Brevo v3 uses '201 Created' for success (in most cases)

def test_deprecation_warning(self):
message = EmailMessage(
"Subject", "Body", "[email protected]", ["[email protected]"]
)
with self.assertWarnsMessage(
AnymailDeprecationWarning,
"`anymail.backends.sendinblue.EmailBackend` has been renamed"
" `anymail.backends.brevo.EmailBackend`.",
):
message.send()
self.assert_esp_called("https://api.brevo.com/v3/smtp/email")

@override_settings(ANYMAIL={"BREVO_API_KEY": "test_api_key"})
def test_missing_api_key_error_uses_correct_setting_name(self):
# The sendinblue.EmailBackend requires SENDINBLUE_ settings names
with self.assertRaisesMessage(AnymailConfigurationError, "SENDINBLUE_API_KEY"):
send_mail("Subject", "Body", "[email protected]", ["[email protected]"])


@tag("brevo", "sendinblue")
@ignore_warnings(category=AnymailDeprecationWarning)
class SendinBlueTrackingWebhookDeprecationTests(WebhookTestCase):
def test_deprecation_warning(self):
with self.assertWarnsMessage(
AnymailDeprecationWarning,
"Anymail's SendinBlue webhook URLs are deprecated.",
):
response = self.client.post(
"/anymail/sendinblue/tracking/",
content_type="application/json",
data="{}",
)
self.assertEqual(response.status_code, 200)
# Old url uses old names to preserve compatibility:
self.assert_handler_called_once_with(
self.tracking_handler,
sender=SendinBlueTrackingWebhookView, # *not* BrevoTrackingWebhookView
event=ANY,
esp_name="SendinBlue", # *not* "Brevo"
)

def test_misconfigured_inbound(self):
# Uses old esp_name when called on old URL
errmsg = (
"You seem to have set Brevo's *inbound* webhook URL"
" to Anymail's SendinBlue *tracking* webhook URL."
)
with self.assertRaisesMessage(AnymailConfigurationError, errmsg):
self.client.post(
"/anymail/sendinblue/tracking/",
content_type="application/json",
data={"items": []},
)


@tag("brevo", "sendinblue")
@override_settings(ANYMAIL_SENDINBLUE_API_KEY="test-api-key")
@ignore_warnings(category=AnymailDeprecationWarning)
class SendinBlueInboundWebhookDeprecationTests(WebhookTestCase):
def test_deprecation_warning(self):
with self.assertWarnsMessage(
AnymailDeprecationWarning,
"Anymail's SendinBlue webhook URLs are deprecated.",
):
response = self.client.post(
"/anymail/sendinblue/inbound/",
content_type="application/json",
data='{"items":[{}]}',
)
self.assertEqual(response.status_code, 200)
# Old url uses old names to preserve compatibility:
self.assert_handler_called_once_with(
self.inbound_handler,
sender=SendinBlueInboundWebhookView, # *not* BrevoInboundWebhookView
event=ANY,
esp_name="SendinBlue", # *not* "Brevo"
)

def test_misconfigured_tracking(self):
# Uses old esp_name when called on old URL
errmsg = (
"You seem to have set Brevo's *tracking* webhook URL"
" to Anymail's SendinBlue *inbound* webhook URL."
)
with self.assertRaisesMessage(AnymailConfigurationError, errmsg):
self.client.post(
"/anymail/sendinblue/inbound/",
content_type="application/json",
data={"event": "delivered"},
)

0 comments on commit 948ab2b

Please sign in to comment.