django-anymail icon indicating copy to clipboard operation
django-anymail copied to clipboard

New feature: per-recipient merge_headers

Open medmunds opened this issue 1 year ago • 0 comments

Several ESPs' batch send APIs allow specifying different email headers for individual recipients. Anymail should add a new merge_headers message option providing normalized support for this feature:

message = AnymailMessage(
    to=["[email protected]", "Bob <[email protected]>"],
    ...,
    # Common headers for all recipients:
    headers={
        "List-Unsubscribe-Post": "List-Unsubscribe=One-Click",
    },
    # Recipient-specific headers:
    merge_headers={
        "[email protected]": {
            "List-Unsubscribe": "<https://example.com/unsubscribe/98765abc>",
        },
        "[email protected]": {
            "List-Unsubscribe": "<https://example.com/unsubscribe/12345xyz>", 
        },
    },
)

As the example shows, this is particularly useful for List-Unsubscribe headers that include a token identifying the recipient. The new merge_headers property is meant to parallel Anymail's existing merge_metadata and merge_data.

Tasks:

  • [x] Base implementation
  • [x] Amazon SES (only works with template)
    • [ ] Add integration test
  • [ ] Brevo
  • [ ] MailerSend ??? (can MailerSend "personalizations" substitutions be used in headers?)
  • [ ] Mailgun ??? (do Mailgun "replacement values" work in headers?)
  • ~~Mandrill~~ (batch API doesn't seem to support per-recipient headers)
  • ~~Postal~~ (no batch send API)
  • [ ] Mailjet
  • [ ] Postmark
  • [ ] Resend
  • [ ] Sendgrid
  • ~~Sparkpost~~ (batch API doesn't seem to support per-recipient headers)
  • [ ] Unisender Go ("substitutions" is documented for List-Unsubscribe header only)
  • [ ] Documentation
    • [ ] Add note to "Limitations" section for each unsupported ESP

In addition to providing the idea, @carrerasrodrigo has already implemented the base and Amazon SES support in #371. (Thanks!)

medmunds avatar May 21 '24 19:05 medmunds