Search code examples
djangoemailschedulingsendgrid

Delaying the sending emails with Sendgrid and Django, SMTP api and send_at header


I've spent a lot of time figuring out how to send email at a specified time in Django, so I am posting it with answer here to save others some time.

My use case is sending email during working hours. Using celery for that is a bad idea. But Sendgrid can send emails with a delay of up to 3 days. That's what we need.


Solution

  • That what I made:

    from django.core.mail import EmailMultiAlternatives
    from django.template.context import Context
    from django.template.loader import get_template
    from smtpapi import SMTPAPIHeader
    def send_email(subject, template_name, context, to, bcc=None, from_email=settings.DEFAULT_FROM_EMAIL, send_at=None):
        header = SMTPAPIHeader()
        body = get_template(template_name).render(Context(context))
        if send_at:
            send_at = {"send_at": send_at}
            header.set_send_at(send_at)
        email = EmailMultiAlternatives(
            subject=subject,
            body=body,
            from_email=from_email,
            to=to,
            bcc=bcc,
            headers={'X-SMTPAPI': header.json_string()}
    
        )
        email.attach_alternative(body, 'text/html')
        email.send()
    

    Don't forget to set it in header X-SMTPAPI cause I couldn't find it anywhere.. And send_at should be a timestamp

    Also here you could see how to add headers or anything but with sendgrid.SendGridClient: https://sendgrid.com/docs/Utilities/code_workshop.html/scheduling_parameters.html

    import sendgrid
    ...
    sg = sendgrid.SendGridClient('apiKey')
    message = sendgrid.Mail()
    message.add_to('John Doe <example@mailinator.com>')
    message.set_subject('Example')
    message.set_html('Body')
    message.set_text('Body')
    message.set_from('Doe John <example@example.com>')
    message.smtpapi.set_send_at(timestamp)
    sg.send(message)