Skip to content

Commit

Permalink
Change in method name
Browse files Browse the repository at this point in the history
- Change in the name of the method that sets the template headers
- Change in SES backend, made template headers optional for backward compatibility.
  • Loading branch information
carrerasrodrigo committed May 18, 2024
1 parent 453d755 commit 6cc3187
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 22 deletions.
24 changes: 13 additions & 11 deletions anymail/backends/amazon_ses.py
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,9 @@ def set_metadata(self, metadata):
# metadata.
self.mime_message["X-Metadata"] = self.serialize_json(metadata)

def set_merge_headers(self, merge_headers):
self.unsupported_feature("merge_headers without template_id")

def set_tags(self, tags):
# See note about Amazon SES Message Tags and custom headers in set_metadata
# above. To support reliable retrieval in webhooks, use custom headers for tags.
Expand Down Expand Up @@ -328,9 +331,6 @@ def set_template_id(self, template_id):
def set_merge_data(self, merge_data):
self.unsupported_feature("merge_data without template_id")

def set_merge_header_data(self, merge_data):
self.unsupported_feature("merge_header_data without template_id")

def set_merge_global_data(self, merge_global_data):
self.unsupported_feature("global_merge_data without template_id")

Expand All @@ -343,7 +343,7 @@ def init_payload(self):
# late-bind recipients and merge_data in finalize_payload
self.recipients = {"to": [], "cc": [], "bcc": []}
self.merge_data = {}
self.merge_header_data = {}
self.merge_headers = {}

def finalize_payload(self):
# Build BulkEmailEntries from recipients and merge_data.
Expand All @@ -360,8 +360,9 @@ def finalize_payload(self):
]

# Construct an entry with merge data for each "to" recipient:
self.params["BulkEmailEntries"] = [
{
self.params["BulkEmailEntries"] = []
for to in self.recipients["to"]:
entry = {
"Destination": dict(ToAddresses=[to.address], **cc_and_bcc_addresses),
"ReplacementEmailContent": {
"ReplacementTemplate": {
Expand All @@ -370,10 +371,11 @@ def finalize_payload(self):
),
}
},
"ReplacementHeaders": self.merge_header_data.get(to.addr_spec, []),
}
for to in self.recipients["to"]
]

if len(self.merge_headers) > 0:
entry["ReplacementHeaders"] = self.merge_headers.get(to.addr_spec, [])
self.params["BulkEmailEntries"].append(entry)

def parse_recipient_status(self, response):
try:
Expand Down Expand Up @@ -496,9 +498,9 @@ def set_merge_data(self, merge_data):
# late-bound in finalize_payload
self.merge_data = merge_data

def set_merge_header_data(self, merge_data):
def set_merge_headers(self, merge_headers):
# late-bound in finalize_payload
self.merge_header_data = merge_data
self.merge_headers = merge_headers

def set_merge_global_data(self, merge_global_data):
# DefaultContent.Template.TemplateData
Expand Down
8 changes: 4 additions & 4 deletions anymail/backends/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -285,16 +285,16 @@ class BasePayload:
("track_opens", last, None),
("template_id", last, force_non_lazy),
("merge_data", merge_dicts_one_level, force_non_lazy_dict),
("merge_header_data", None, None),
("merge_global_data", merge_dicts_shallow, force_non_lazy_dict),
("merge_headers", None, None),
("merge_metadata", merge_dicts_one_level, force_non_lazy_dict),
("esp_extra", merge_dicts_deep, force_non_lazy_dict),
)
esp_message_attrs = () # subclasses can override

# If any of these attrs are set on a message, treat the message
# as a batch send (separate message for each `to` recipient):
batch_attrs = ("merge_data", "merge_header_data", "merge_metadata")
batch_attrs = ("merge_data", "merge_headers", "merge_metadata")

def __init__(self, message, defaults, backend):
self.message = message
Expand Down Expand Up @@ -618,8 +618,8 @@ def set_template_id(self, template_id):
def set_merge_data(self, merge_data):
self.unsupported_feature("merge_data")

def set_merge_header_data(self, merge_data):
self.unsupported_feature("set_merge_header_data")
def set_merge_headers(self, merge_headers):
self.unsupported_feature("merge_headers")

def set_merge_global_data(self, merge_global_data):
self.unsupported_feature("merge_global_data")
Expand Down
4 changes: 2 additions & 2 deletions anymail/backends/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,8 @@ def set_template_id(self, template_id):
def set_merge_data(self, merge_data):
self.params["merge_data"] = merge_data

def set_merge_header_data(self, merge_data):
self.params["merge_header_data"] = merge_data
def set_merge_headers(self, merge_headers):
self.params["merge_headers"] = merge_headers

def set_merge_metadata(self, merge_metadata):
self.params["merge_metadata"] = merge_metadata
Expand Down
2 changes: 1 addition & 1 deletion anymail/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ def __init__(self, *args, **kwargs):
self.track_opens = kwargs.pop("track_opens", UNSET)
self.template_id = kwargs.pop("template_id", UNSET)
self.merge_data = kwargs.pop("merge_data", UNSET)
self.merge_header_data = kwargs.pop("merge_header_data", UNSET)
self.merge_global_data = kwargs.pop("merge_global_data", UNSET)
self.merge_headers = kwargs.pop("merge_headers", UNSET)
self.merge_metadata = kwargs.pop("merge_metadata", UNSET)
self.anymail_status = AnymailStatus()

Expand Down
58 changes: 54 additions & 4 deletions tests/test_amazon_ses_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -560,14 +560,64 @@ def test_merge_data(self):
):
self.message.send()

def test_merge_header_data(self):
def test_merge_headers(self):
# Amazon SES only supports merging when using templates (see below)
self.message.merge_header_data = {}
self.message.merge_headers = {}
with self.assertRaisesMessage(
AnymailUnsupportedFeature, "merge_header_data without template_id"
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"
Expand Down Expand Up @@ -603,7 +653,7 @@ def test_template(self):
"bob@example.com": {"name": "Bob"}, # and leave group undefined
"nobody@example.com": {"name": "Not a recipient for this message"},
},
merge_header_data={
merge_headers={
"alice@example.com": [
{"Name": "List-Unsubscribe-Post", "Value": "https://xyz.com/a/"}
],
Expand Down

0 comments on commit 6cc3187

Please sign in to comment.