pythondjangoemaildjango-anymail

How can I send a batch email using postmark in Anymail for Django?


I am trying to use the Anymail API for postmark in my Django application. This is not the same as putting a list of emails in the cc, but I am trying to send a separate email to each individual email address (the email content is the same though). Right now, I have the following to send transactional (one-time) emails. I need this to work with html contents as well!

from anymail.message import AnymailMessage
email = AnymailMessage(
    subject=subject, 
    body=body,
    from_email=from_email,
    to=to,
)
email.attach_alternative(html_content, "text/html")
email.esp_extra = {
    'MessageStream': message_stream,  # Specify the message stream
}

I initially tried using a for loop to send a separate email to each email address, but that consumed too much time and the page couldn't load long enough. How can I then achieve this batch email send in Django using Anymail?

Please leave a comment if you have any questions.


Solution

  • For ESPs that support it, Anymail uses batch sending if you set the merge_data, merge_metadata or merge_headers properties on the message.

    From Batch sending/merge and ESP templates on Anymail's Postmark documentation page:

    When you supply per-recipient merge_data, Anymail automatically switches to Postmark’s batch send API, so that each “to” recipient sees only their own email address. (Any cc’s or bcc’s will be duplicated for every to-recipient.)

    If you want to use batch sending with a regular message (without a template), set merge data to an empty dict: message.merge_data = {}.

    However, if there are any errors, batch sending can make it difficult to tell which recipients did or didn't get sent an email. It's often better to loop over the addresses and send separate messages, as you had been doing. If this is timing out, a good option is to move actual sending to a separate thread or process, using something like django-mailer or django-celery-email. See Anymail's Handling transient errors docs for more info.