Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Confusion with sending email in Django

Tags:

django

My Django app needs to send emails in HTML format. As per the official documention:

It can be useful to include multiple versions of the content in an email; the classic example is to send both text and HTML versions of a message. With Django's email library, you can do this using the EmailMultiAlternatives class. This subclass of EmailMessage has an attach_alternative() method for including extra versions of the message body in the email. All the other methods (including the class initialization) are inherited directly from EmailMessage.

...I came up with the following code:

from django.core.mail import EmailMultiAlternatives
msg = EmailMultiAlternatives()
msg.sender = "[email protected]"
msg.subject = subject
msg.to = [target,]
msg.attach_alternative(content, "text/html")
msg.send()

This work as expected. However, in some situations I need to include PDF attachments, for which I added the following code just before msg.send():

if attachments is not None:
    for attachment in attachments:
        content = open(attachment.path, 'rb')
        msg.attach(attachment.name,content.read(),'application/pdf')

Although this works - all PDF documents are properly attached to the email - the unwanted side effect is that the HTML content of the email now has disappeared and I'm left with an empty email body with PDF documents attached to it.

What am I doing wrong here?

like image 292
Roger Avatar asked Jan 14 '23 09:01

Roger


2 Answers

I figured it out.

If you use EmailMultiAlternatives you apparently MUST supply both the text format and the HTML format of the body of the email for situations where your email has additional attachments. I only supplied the HTML format which was ok for an email without attachments but somehow was confusing when other attachments were added like PDF documents.

The final working code:

text_content = strip_tags(content)
msg = EmailMultiAlternatives()
msg.sender = "[email protected]"
msg.subject = subject
msg.to = [target]
msg.body = text_content
msg.attach_alternative(content, "text/html")
if attachments is not None:
    for attachment in attachments:
        content = open(attachment.path, 'rb')
        msg.attach(attachment.name,content.read(),'application/pdf')
msg.send()
like image 190
Roger Avatar answered Jan 25 '23 17:01

Roger


The EmailMultiAlternatives is to be used, if you want to provide both plain text and text/html version. Than its up to the email client of the recipient to decide which version to display. What you need is simply:

from django.core import mail

....

msg = mail.EmailMessage(subject, content,
                        to=[target], from_email='[email protected]')
if attachments is not None:
    for attachment in attachments:
        msg.attach_file(attachment, 'application/zip')
like image 41
Marek Kowalski Avatar answered Jan 25 '23 17:01

Marek Kowalski