anymail / django-anymail

Django email backends and webhooks for Amazon SES, Brevo (Sendinblue), MailerSend, Mailgun, Mailjet, Postmark, Postal, Resend, SendGrid, SparkPost, Unisender Go and more
https://anymail.dev
BSD 3-Clause "New" or "Revised" License
1.65k stars 125 forks source link

New feature: per-recipient merge_headers #374

Closed medmunds closed 2 months ago

medmunds commented 3 months ago

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=["alice@example.com", "Bob <bob@example.com>"],
    ...,
    # Common headers for all recipients:
    headers={
        "List-Unsubscribe-Post": "List-Unsubscribe=One-Click",
    },
    # Recipient-specific headers:
    merge_headers={
        "alice@example.com": {
            "List-Unsubscribe": "<https://example.com/unsubscribe/98765abc>",
        },
        "bob@example.com": {
            "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.

[Edit: updated info on supported ESPs]

Can support merge_headers:

Cannot support merge_headers:

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