Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django, ReportLab PDF Generation attached to an email

What's the best way to use Django and ReportLab to generate PDFs and attach them to an email message?

I'm using a SimpleDocTemplate and can attach the generated PDF to my HttpResponse - which is great, but I'm having trouble finding out how to exactly add that same attachment to an email:

    # Create the HttpResponse object with the appropriate PDF headers.
    response = HttpResponse(mimetype='application/pdf')
    response['Content-Disposition'] = 'attachment; filename=invoice.pdf'
    doc = SimpleDocTemplate(response, pagesize=letter)
    Document = []

... make my pdf by appending tables to the Document...

  doc.build(Document)
  email = EmailMessage('Hello', 'Body', '[email protected]', ['[email protected]'])
  email.attach('invoice.pdf', ???, 'application/pdf')
  email.send()

I'm just not sure how to translate my pdfdocument as a blob so that email.attach can accept it and email.send can send it.

Any ideas?

like image 209
Daniel D Avatar asked Dec 07 '10 16:12

Daniel D


3 Answers

Using ReportLab


try:
    from cStringIO import StringIO
except ImportError:
    from StringIO import StringIO
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter, A4
from reportlab.lib.units import inch

def createPDF(request):
 x=100
 y=100
 buffer=StringIO()
 p=canvas.Canvas(buffer,pagesize=letter)
 p.drawString(x,y,"HELLOWORLD")
 p.showPage()
 p.save() 
 pdf=buffer.getvalue()
 buffer.close() 
 return pdf

def someView(request):
 EmailMsg=mail.EmailMessage(YourSubject,YourEmailBodyCopy,'[email protected]',["[email protected]"],headers={'Reply-To':'[email protected]'})
 pdf=createPDF(request)
 EmailMsg.attach('yourChoosenFileName.pdf',pdf,'application/pdf')
 EmailMsg.send()

Works perfectly!!

like image 119
magicTuscan Avatar answered Nov 10 '22 13:11

magicTuscan


OK - I figured it out based on piecing a few things together -

First off - my requirements: - I only wanted to create the PDFs in memory - I don't want the files hanging around, as they take up space, and I don't want what might be sensitive data hanging around unprotected on the server.

So - I picked ReportLab and Platypus functionality for generating my documents. I've invested enough time into it now, that's it's easy. So here's my approach that lets me use the DocTempates in ReportLab, allows me to use Django's email capabilities to send emails.

Here's how I'm doing it:

 # Create the PDF object, using the buffer object as its "file."
  buffer = StringIO()
  doc = SimpleDocTemplate(buffer, pagesize=letter)
  Document = []

  # CRUFT PDF Data

  doc.build(Document)
  pdf = buffer.getvalue()
  buffer.close()

  email = EmailMessage('Hello', 'Body', '[email protected]', ['[email protected]'])
  email.attach('invoicex.pdf', pdf , 'application/pdf')
  email.send()

My issue from moving from web generation to email generation was getting the right object that could be "attached" to an email. Creating a buffer, then grabbing the data off the buffer did it for me...

like image 30
Daniel D Avatar answered Nov 10 '22 14:11

Daniel D


I don't see where your blob is rendered, so I can't advise you on how to import it. I've gotten great results using Pisa and StringIO:

import ho.pisa as pisa
import StringIO
from django.template.loader import render_to_string
from django.core.mail import EmailMessage

render = render_to_string("books/agreement/agreement_base.html",
                              { "title": book.title,
                                "distribution": book.distribution_region })
out = StringIO.StringIO()
pdf = pisa.CreatePDF(StringIO.StringIO(render), out)
email = EmailMessage('Hello', 'Body', '[email protected]', ['[email protected]'])
email.attach('agreement.pdf', out.getvalue(), 'application/pdf')
email.send()

That said, if your PDF exists as an independent and persistent document on your filesystem, couldn't you just:

email.attach('agreement.pdf', open('agreement.pdf', 'rb').read(), 'application/pdf')
like image 3
Elf Sternberg Avatar answered Nov 10 '22 14:11

Elf Sternberg