mirror of
https://github.com/pacnpal/django-anymail.git
synced 2025-12-20 03:41:05 -05:00
SendGrid: add merge_metadata
Add support in SendGrid backend for per-recipient metadata.
This commit is contained in:
committed by
Mike Edmunds
parent
412a1b78c6
commit
85dce5fd6a
@@ -245,6 +245,7 @@ class BasePayload(object):
|
||||
('template_id', last, force_non_lazy),
|
||||
('merge_data', combine, force_non_lazy_dict),
|
||||
('merge_global_data', combine, force_non_lazy_dict),
|
||||
('merge_metadata', combine, force_non_lazy_dict),
|
||||
('esp_extra', combine, force_non_lazy_dict),
|
||||
)
|
||||
esp_message_attrs = () # subclasses can override
|
||||
@@ -495,6 +496,9 @@ class BasePayload(object):
|
||||
def set_merge_global_data(self, merge_global_data):
|
||||
self.unsupported_feature("merge_global_data")
|
||||
|
||||
def set_merge_metadata(self, merge_metadata):
|
||||
self.unsupported_feature("merge_metadata")
|
||||
|
||||
# ESP-specific payload construction
|
||||
def set_esp_extra(self, extra):
|
||||
self.unsupported_feature("esp_extra")
|
||||
|
||||
@@ -77,6 +77,7 @@ class SendGridPayload(RequestsPayload):
|
||||
self.merge_field_format = backend.merge_field_format
|
||||
self.merge_data = None # late-bound per-recipient data
|
||||
self.merge_global_data = None
|
||||
self.merge_metadata = None
|
||||
|
||||
http_headers = kwargs.pop('headers', {})
|
||||
http_headers['Authorization'] = 'Bearer %s' % backend.api_key
|
||||
@@ -101,6 +102,7 @@ class SendGridPayload(RequestsPayload):
|
||||
if self.generate_message_id:
|
||||
self.set_anymail_id()
|
||||
self.build_merge_data()
|
||||
self.build_merge_metadata()
|
||||
|
||||
if not self.data["headers"]:
|
||||
del self.data["headers"] # don't send empty headers
|
||||
@@ -204,6 +206,28 @@ class SendGridPayload(RequestsPayload):
|
||||
"Search SENDGRID_MERGE_FIELD_FORMAT in the Anymail docs for more info.",
|
||||
AnymailWarning)
|
||||
|
||||
def build_merge_metadata(self):
|
||||
if self.merge_metadata is None:
|
||||
return
|
||||
|
||||
if self.merge_data is None:
|
||||
# Burst apart each to-email in personalizations[0] into a separate
|
||||
# personalization, and add merge_metadata for that recipient
|
||||
assert len(self.data["personalizations"]) == 1
|
||||
base_personalizations = self.data["personalizations"].pop()
|
||||
to_list = base_personalizations.pop("to") # {email, name?} for each message.to
|
||||
for recipient in to_list:
|
||||
personalization = base_personalizations.copy() # captures cc, bcc, and any esp_extra
|
||||
personalization["to"] = [recipient]
|
||||
self.data["personalizations"].append(personalization)
|
||||
|
||||
for personalization in self.data["personalizations"]:
|
||||
recipient_email = personalization["to"][0]["email"]
|
||||
recipient_metadata = self.merge_metadata.get(recipient_email)
|
||||
if recipient_metadata:
|
||||
recipient_custom_args = self.transform_metadata(recipient_metadata)
|
||||
personalization["custom_args"] = recipient_custom_args
|
||||
|
||||
#
|
||||
# Payload construction
|
||||
#
|
||||
@@ -296,11 +320,14 @@ class SendGridPayload(RequestsPayload):
|
||||
self.data.setdefault("attachments", []).append(att)
|
||||
|
||||
def set_metadata(self, metadata):
|
||||
self.data["custom_args"] = self.transform_metadata(metadata)
|
||||
|
||||
def transform_metadata(self, metadata):
|
||||
# SendGrid requires custom_args values to be strings -- not integers.
|
||||
# (And issues the cryptic error {"field": null, "message": "Bad Request", "help": null}
|
||||
# if they're not.)
|
||||
# We'll stringify ints and floats; anything else is the caller's responsibility.
|
||||
self.data["custom_args"] = {
|
||||
return {
|
||||
k: str(v) if isinstance(v, BASIC_NUMERIC_TYPES) else v
|
||||
for k, v in metadata.items()
|
||||
}
|
||||
@@ -344,6 +371,12 @@ class SendGridPayload(RequestsPayload):
|
||||
# template type and merge_field_format.
|
||||
self.merge_global_data = merge_global_data
|
||||
|
||||
def set_merge_metadata(self, merge_metadata):
|
||||
# Becomes personalizations[...]['custom_args'] in
|
||||
# build_merge_data, after we know recipients, template type,
|
||||
# and merge_field_format.
|
||||
self.merge_metadata = merge_metadata
|
||||
|
||||
def set_esp_extra(self, extra):
|
||||
self.merge_field_format = extra.pop("merge_field_format", self.merge_field_format)
|
||||
self.use_dynamic_template = extra.pop("use_dynamic_template", self.use_dynamic_template)
|
||||
|
||||
Reference in New Issue
Block a user