Add merge_headers option for Amazon SES

Add new `merge_headers` message option 
for per-recipient headers with template sends. 

* Support in base backend
* Implement in Amazon SES backend
  (Requires boto3 >= 1.34.98.)

---------

Co-authored-by: Mike Edmunds <medmunds@gmail.com>
This commit is contained in:
Rodrigo Nicolas Carreras
2024-05-21 15:55:29 -03:00
committed by GitHub
parent 4c62f7bee0
commit 33f680686b
6 changed files with 118 additions and 5 deletions

View File

@@ -560,6 +560,64 @@ class AmazonSESBackendAnymailFeatureTests(AmazonSESBackendMockAPITestCase):
):
self.message.send()
def test_merge_headers(self):
# Amazon SES only supports merging when using templates (see below)
self.message.merge_headers = {}
with self.assertRaisesMessage(
AnymailUnsupportedFeature, "merge_headers without template_id"
):
self.message.send()
@override_settings(
# only way to use tags with template_id:
ANYMAIL_AMAZON_SES_MESSAGE_TAG_NAME="Campaign"
)
def test_template_dont_add_merge_headers(self):
"""With template_id, Anymail switches to SESv2 SendBulkEmail"""
# SendBulkEmail uses a completely different API call and payload
# structure, so this re-tests a bunch of Anymail features that were handled
# differently above. (See test_amazon_ses_integration for a more realistic
# template example.)
raw_response = {
"BulkEmailEntryResults": [
{
"Status": "SUCCESS",
"MessageId": "1111111111111111-bbbbbbbb-3333-7777",
},
{
"Status": "ACCOUNT_DAILY_QUOTA_EXCEEDED",
"Error": "Daily message quota exceeded",
},
],
"ResponseMetadata": self.DEFAULT_SEND_RESPONSE["ResponseMetadata"],
}
self.set_mock_response(raw_response, operation_name="send_bulk_email")
message = AnymailMessage(
template_id="welcome_template",
from_email='"Example, Inc." <from@example.com>',
to=["alice@example.com", "罗伯特 <bob@example.com>"],
cc=["cc@example.com"],
reply_to=["reply1@example.com", "Reply 2 <reply2@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"},
# (only works with AMAZON_SES_MESSAGE_TAG_NAME when using template):
tags=["WelcomeVariantA"],
envelope_sender="bounce@example.com",
esp_extra={
"FromEmailAddressIdentityArn": (
"arn:aws:ses:us-east-1:123456789012:identity/example.com"
)
},
)
message.send()
params = self.get_send_params(operation_name="send_bulk_email")
self.assertNotIn("ReplacementHeaders", params["BulkEmailEntries"][0])
@override_settings(
# only way to use tags with template_id:
ANYMAIL_AMAZON_SES_MESSAGE_TAG_NAME="Campaign"
@@ -595,6 +653,16 @@ class AmazonSESBackendAnymailFeatureTests(AmazonSESBackendMockAPITestCase):
"bob@example.com": {"name": "Bob"}, # and leave group undefined
"nobody@example.com": {"name": "Not a recipient for this message"},
},
merge_headers={
"alice@example.com": {
"List-Unsubscribe": "<https://example.com/a/>",
"List-Unsubscribe-Post": "List-Unsubscribe=One-Click",
},
"nobody@example.com": {
"List-Unsubscribe": "<mailto:unsubscribe@example.com>",
"List-Unsubscribe-Post": "List-Unsubscribe=One-Click",
},
},
merge_global_data={"group": "Users", "site": "ExampleCo"},
# (only works with AMAZON_SES_MESSAGE_TAG_NAME when using template):
tags=["WelcomeVariantA"],
@@ -646,6 +714,21 @@ class AmazonSESBackendAnymailFeatureTests(AmazonSESBackendMockAPITestCase):
),
{"name": "Bob"},
)
self.assertEqual(
bulk_entries[0]["ReplacementHeaders"],
[
{"Name": "List-Unsubscribe", "Value": "<https://example.com/a/>"},
{
"Name": "List-Unsubscribe-Post",
"Value": "List-Unsubscribe=One-Click",
},
],
)
self.assertEqual(
bulk_entries[1]["ReplacementHeaders"],
[],
)
self.assertEqual(
json.loads(params["DefaultContent"]["Template"]["TemplateData"]),
{"group": "Users", "site": "ExampleCo"},