Django - Attach PDF generated by a view to an email

Viewed 4574

This question has some elements here, but no final answer.

There is view generating a PDF with easy_pdf

from easy_pdf.views import PDFTemplateResponseMixin

class PostPDFDetailView(PDFTemplateResponseMixin,DetailView):
    model = models.Post
    template_name = 'post/post_pdf.html'

Then, I want to attach this generated PDF to the following email :

@receiver(post_save, sender=Post)
def first_mail(sender, instance, **kwargs):
    if kwargs['created']:
        user_email = instance.client.email
        subject, from_email, to = 'New account', 'contact@example.com', user_email
        post_id = str(instance.id)
        domain = Site.objects.get_current().domain
        post_pdf = domain + '/post/' + post_id + '.pdf'

        text_content = render_to_string('post/mail_post.txt')
        html_content = render_to_string('post/mail_post.html')

        # create the email, and attach the HTML version as well.
        msg = EmailMultiAlternatives(subject, text_content, from_email, [to])
        msg.attach_alternative(html_content, "text/html")
        msg.attach_file(post_pdf, 'application/pdf')
        msg.send()

I also have tried this one:

   msg.attach_file(domain + '/post/' + post_id + '.pdf', 'application/pdf')
2 Answers

I was looking for a way to attach an easy_pdf generated PDF without saving a temp file as well. Since I couldn't find a solution elsewhere, I suggest a short and working proposal using easy_pdf.rendering.render_to_pdf:

from easy_pdf.rendering import render_to_pdf
...
post_pdf = render_to_pdf(
        'post/post_pdf.html',
        {'any_context_item_to_pass_to_the_template': context_value,},
)
...
msg.attach('file.pdf', post_pdf, 'application/pdf')

I hope it'll help if you are still interested by a way to do this.

Not sure if it helps, but I used EmailMessage built-in to attach PDFs I created for reporting to emails I sent out:

from django.core.mail import send_mail, EmailMessage

draft_email = EmailMessage(
            #subject,
            #body,
            #from_email,
            #to_email,
)

Option 1:

# attach a file you have saved to the system... expects the path
draft_email.attach_file(report_pdf.name)

Option 2:

# expects the name of the file object
draft_email.attach("Report.pdf") 

Then, sends like you already have:

draft_email.send()

Some initial thoughts: it seems like you are trying to use attach_file to attach a file from the system, but it isn't on the system. I would try using attach instead of attach_file, if I am reading your code correctly, since the pdf is in your memory, not in LTS on the system.

Related