mirror of
https://github.com/pacnpal/django-anymail.git
synced 2025-12-20 03:41:05 -05:00
@@ -18,7 +18,7 @@ from anymail.exceptions import (
|
||||
AnymailSerializationError,
|
||||
AnymailUnsupportedFeature,
|
||||
)
|
||||
from anymail.message import attach_inline_image_file
|
||||
from anymail.message import AnymailMessage, attach_inline_image_file
|
||||
|
||||
from .mock_requests_backend import (
|
||||
RequestsBackendMockAPITestCase,
|
||||
@@ -478,13 +478,60 @@ class SendinBlueBackendAnymailFeatureTests(SendinBlueBackendMockAPITestCase):
|
||||
self.assertEqual(data["subject"], "My Subject")
|
||||
self.assertEqual(data["to"], [{"email": "to@example.com", "name": "Recipient"}])
|
||||
|
||||
_mock_batch_response = {
|
||||
"messageIds": [
|
||||
"<202403182259.64789700810.1@smtp-relay.mailin.fr>",
|
||||
"<202403182259.64789700810.2@smtp-relay.mailin.fr>",
|
||||
]
|
||||
}
|
||||
|
||||
def test_merge_data(self):
|
||||
self.message.merge_data = {
|
||||
"alice@example.com": {":name": "Alice", ":group": "Developers"},
|
||||
"bob@example.com": {":name": "Bob"}, # and leave :group undefined
|
||||
}
|
||||
with self.assertRaises(AnymailUnsupportedFeature):
|
||||
self.message.send()
|
||||
self.set_mock_response(json_data=self._mock_batch_response)
|
||||
message = AnymailMessage(
|
||||
from_email="from@example.com",
|
||||
template_id=1234567,
|
||||
to=["alice@example.com", "Bob <bob@example.com>"],
|
||||
merge_data={
|
||||
"alice@example.com": {"name": "Alice", "group": "Developers"},
|
||||
"bob@example.com": {"name": "Bob"}, # and leave group undefined
|
||||
"nobody@example.com": {"name": "Not a recipient for this message"},
|
||||
},
|
||||
merge_global_data={"group": "Users", "site": "ExampleCo"},
|
||||
)
|
||||
message.send()
|
||||
|
||||
# batch send uses same API endpoint as regular send:
|
||||
self.assert_esp_called("/v3/smtp/email")
|
||||
data = self.get_api_call_json()
|
||||
versions = data["messageVersions"]
|
||||
self.assertEqual(len(versions), 2)
|
||||
self.assertEqual(
|
||||
versions[0],
|
||||
{
|
||||
"to": [{"email": "alice@example.com"}],
|
||||
"params": {"name": "Alice", "group": "Developers"},
|
||||
},
|
||||
)
|
||||
self.assertEqual(
|
||||
versions[1],
|
||||
{
|
||||
"to": [{"email": "bob@example.com", "name": "Bob"}],
|
||||
"params": {"name": "Bob"},
|
||||
},
|
||||
)
|
||||
self.assertEqual(data["params"], {"group": "Users", "site": "ExampleCo"})
|
||||
|
||||
recipients = message.anymail_status.recipients
|
||||
self.assertEqual(recipients["alice@example.com"].status, "queued")
|
||||
self.assertEqual(
|
||||
recipients["alice@example.com"].message_id,
|
||||
"<202403182259.64789700810.1@smtp-relay.mailin.fr>",
|
||||
)
|
||||
self.assertEqual(recipients["bob@example.com"].status, "queued")
|
||||
self.assertEqual(
|
||||
recipients["bob@example.com"].message_id,
|
||||
"<202403182259.64789700810.2@smtp-relay.mailin.fr>",
|
||||
)
|
||||
|
||||
def test_merge_global_data(self):
|
||||
self.message.merge_global_data = {"a": "b"}
|
||||
@@ -492,6 +539,38 @@ class SendinBlueBackendAnymailFeatureTests(SendinBlueBackendMockAPITestCase):
|
||||
data = self.get_api_call_json()
|
||||
self.assertEqual(data["params"], {"a": "b"})
|
||||
|
||||
def test_merge_metadata(self):
|
||||
self.set_mock_response(json_data=self._mock_batch_response)
|
||||
self.message.to = ["alice@example.com", "Bob <bob@example.com>"]
|
||||
self.message.merge_metadata = {
|
||||
"alice@example.com": {"order_id": 123, "tier": "premium"},
|
||||
"bob@example.com": {"order_id": 678},
|
||||
}
|
||||
self.message.metadata = {"notification_batch": "zx912"}
|
||||
self.message.send()
|
||||
|
||||
data = self.get_api_call_json()
|
||||
versions = data["messageVersions"]
|
||||
self.assertEqual(len(versions), 2)
|
||||
self.assertEqual(versions[0]["to"], [{"email": "alice@example.com"}])
|
||||
# metadata and merge_metadata[recipient] are combined:
|
||||
self.assertEqual(
|
||||
json.loads(versions[0]["headers"]["X-Mailin-custom"]),
|
||||
{"order_id": 123, "tier": "premium", "notification_batch": "zx912"},
|
||||
)
|
||||
self.assertEqual(
|
||||
versions[1]["to"], [{"name": "Bob", "email": "bob@example.com"}]
|
||||
)
|
||||
self.assertEqual(
|
||||
json.loads(versions[1]["headers"]["X-Mailin-custom"]),
|
||||
{"order_id": 678, "notification_batch": "zx912"},
|
||||
)
|
||||
# default metadata still sent in base headers:
|
||||
self.assertEqual(
|
||||
json.loads(data["headers"]["X-Mailin-custom"]),
|
||||
{"notification_batch": "zx912"},
|
||||
)
|
||||
|
||||
def test_default_omits_options(self):
|
||||
"""Make sure by default we don't send any ESP-specific options.
|
||||
|
||||
@@ -502,35 +581,24 @@ class SendinBlueBackendAnymailFeatureTests(SendinBlueBackendMockAPITestCase):
|
||||
self.message.send()
|
||||
data = self.get_api_call_json()
|
||||
self.assertNotIn("attachment", data)
|
||||
self.assertNotIn("tag", data)
|
||||
self.assertNotIn("bcc", data)
|
||||
self.assertNotIn("cc", data)
|
||||
self.assertNotIn("headers", data)
|
||||
self.assertNotIn("messageVersions", data)
|
||||
self.assertNotIn("params", data)
|
||||
self.assertNotIn("replyTo", data)
|
||||
self.assertNotIn("atributes", data)
|
||||
self.assertNotIn("schedule", data)
|
||||
self.assertNotIn("tags", data)
|
||||
self.assertNotIn("templateId", data)
|
||||
|
||||
def test_esp_extra(self):
|
||||
# SendinBlue doesn't offer any esp-extra but we will test
|
||||
# with some extra of SendGrid to see if it's work in the future
|
||||
self.message.esp_extra = {
|
||||
"ip_pool_name": "transactional",
|
||||
"asm": { # subscription management
|
||||
"group_id": 1,
|
||||
},
|
||||
"tracking_settings": {
|
||||
"subscription_tracking": {
|
||||
"enable": True,
|
||||
"substitution_tag": "[unsubscribe_url]",
|
||||
},
|
||||
},
|
||||
"batchId": "5c6cfa04-eed9-42c2-8b5c-6d470d978e9d",
|
||||
}
|
||||
self.message.send()
|
||||
data = self.get_api_call_json()
|
||||
# merged from esp_extra:
|
||||
self.assertEqual(data["ip_pool_name"], "transactional")
|
||||
self.assertEqual(data["asm"], {"group_id": 1})
|
||||
self.assertEqual(
|
||||
data["tracking_settings"]["subscription_tracking"],
|
||||
{"enable": True, "substitution_tag": "[unsubscribe_url]"},
|
||||
)
|
||||
self.assertEqual(data["batchId"], "5c6cfa04-eed9-42c2-8b5c-6d470d978e9d")
|
||||
|
||||
# noinspection PyUnresolvedReferences
|
||||
def test_send_attaches_anymail_status(self):
|
||||
|
||||
@@ -98,40 +98,42 @@ class SendinBlueBackendIntegrationTests(AnymailTestMixin, SimpleTestCase):
|
||||
template_id=5,
|
||||
# Override template sender:
|
||||
from_email=formataddr(("Sender", self.from_email)),
|
||||
# No batch send (so max one recipient suggested):
|
||||
to=["Recipient <test+to1@anymail.dev>"],
|
||||
to=["Recipient 1 <test+to1@anymail.dev>", "test+to2@anymail.dev"],
|
||||
reply_to=["Do not reply <reply@example.dev>"],
|
||||
tags=["using-template"],
|
||||
headers={"X-Anymail-Test": "group: A, variation: C"},
|
||||
merge_global_data={
|
||||
# The Anymail test template includes `{{ params.SHIP_DATE }}`
|
||||
# and `{{ params.ORDER_ID }}` substitutions
|
||||
"SHIP_DATE": "yesterday",
|
||||
"ORDER_ID": "12345",
|
||||
# The Anymail test template includes `{{ params.SHIP_DATE }}`
|
||||
# and `{{ params.ORDER_ID }}` substitutions
|
||||
merge_data={
|
||||
"test+to1@anymail.dev": {"ORDER_ID": "12345"},
|
||||
"test+to2@anymail.dev": {"ORDER_ID": "23456"},
|
||||
},
|
||||
merge_global_data={"SHIP_DATE": "yesterday"},
|
||||
metadata={"customer-id": "unknown", "meta2": 2},
|
||||
merge_metadata={
|
||||
"test+to1@anymail.dev": {"customer-id": "ZXK9123"},
|
||||
"test+to2@anymail.dev": {"customer-id": "ZZT4192"},
|
||||
},
|
||||
metadata={"customer-id": "ZXK9123", "meta2": 2},
|
||||
)
|
||||
|
||||
# Normal attachments don't work with Brevo templates:
|
||||
# message.attach("attachment1.txt", "Here is some\ntext", "text/plain")
|
||||
# If you can host the attachment content on some publicly-accessible URL,
|
||||
# this *non-portable* alternative allows sending attachments with templates:
|
||||
message.esp_extra = {
|
||||
"attachment": [
|
||||
{
|
||||
"name": "attachment1.txt",
|
||||
# URL where Brevo can download the attachment content while
|
||||
# sending (must be content-type: text/plain):
|
||||
"url": "https://raw.githubusercontent.com/anymail/django-anymail/"
|
||||
"main/docs/_readme/template.txt",
|
||||
}
|
||||
]
|
||||
}
|
||||
message.attach("attachment1.txt", "Here is some\ntext", "text/plain")
|
||||
|
||||
message.send()
|
||||
# SendinBlue always queues:
|
||||
self.assertEqual(message.anymail_status.status, {"queued"})
|
||||
self.assertRegex(message.anymail_status.message_id, r"\<.+@.+\>")
|
||||
recipient_status = message.anymail_status.recipients
|
||||
self.assertEqual(recipient_status["test+to1@anymail.dev"].status, "queued")
|
||||
self.assertEqual(recipient_status["test+to2@anymail.dev"].status, "queued")
|
||||
self.assertRegex(
|
||||
recipient_status["test+to1@anymail.dev"].message_id, r"\<.+@.+\>"
|
||||
)
|
||||
self.assertRegex(
|
||||
recipient_status["test+to2@anymail.dev"].message_id, r"\<.+@.+\>"
|
||||
)
|
||||
# Each recipient gets their own message_id:
|
||||
self.assertNotEqual(
|
||||
recipient_status["test+to1@anymail.dev"].message_id,
|
||||
recipient_status["test+to2@anymail.dev"].message_id,
|
||||
)
|
||||
|
||||
@override_settings(ANYMAIL_SENDINBLUE_API_KEY="Hey, that's not an API key!")
|
||||
def test_invalid_api_key(self):
|
||||
|
||||
Reference in New Issue
Block a user