Question

I have been trying to create a templated Google Drive Document with Jinja2 and eventually email the document as an attached PDF document.

So far I have managed to do the most of it but now am stuck on the attachment part. I get the error "InvalidAttachmentTypeError: Invalid attachment type".

And is there a way to improve on this so that its a bit more efficient.

class Upload(webapp2.RequestHandler):
  @decorator.oauth_required
  def get(self):
    if decorator.has_credentials():
      try:
          body = {'title': 'My New Text Document',
                  'description': 'Hello World'}

          template = JINJA_ENVIRONMENT.get_template('document.html')
          template_values = {'name': 'Simon'}
          fh = StringIO.StringIO(template.render(template_values))

          media_body = MediaIoBaseUpload(fh,
                                         mimetype='text/html',
                                         resumable=False)

          http = httplib2.Http(memcache)
          http = decorator.http()

          service = discovery.build('drive', 'v2', http=http)

          file = service.files().insert(body=body,
                                        media_body=media_body,
                                        convert=True).execute(http=http)

          m = mail.EmailMessage()
          m.sender = 'myfromemailaaddress@gmail.com'
          m.to = 'mytoemailaddress@gmail.com'
          m.subject = 'My Subject'
          m.html = '<p>My body.</p>'
          m.attachments = [(file['title'],
                            file['exportLinks']['application/pdf'])]
          m.send()

          self.redirect('/')

        except client.AccessTokenRefreshError:
          self.redirect('/')

    else:
      self.redirect(decorator.authorize_url())
Was it helpful?

Solution 2

After a lot of experimenting I have finally figured out how its done. So here it is for anyone in the same position as I.

class Upload(webapp2.RequestHandler):
@decorator.oauth_required
def get(self):
  if decorator.has_credentials():
    try:
      body = {'title': 'My New Text Document',
              'description': 'Hello World'}

      template = JINJA_ENVIRONMENT.get_template('document.html')
      template_values = {'name': 'Simon'}
      fh = StringIO.StringIO(template.render(template_values))

      media_body = MediaIoBaseUpload(fh,
                                     mimetype='text/html',
                                     resumable=False)

      http = httplib2.Http(memcache)
      http = decorator.http()

      service = discovery.build('drive', 'v2', http=http)

      file = service.files().insert(body=body,
                                    media_body=media_body,
                                    convert=True).execute(http=http)

      download_url = file['exportLinks']['application/pdf']
      resp, content = service._http.request(download_url)

      m = mail.EmailMessage()
      m.sender = 'myfromemailaaddress@gmail.com'
      m.to = 'mytoemailaddress@gmail.com'
      m.subject = 'My Subject'
      m.html = '<p>My body.</p>'
      m.attachments = [('myfile.pdf', str(content))]
      m.send()

      self.redirect('/')

    except client.AccessTokenRefreshError:
      self.redirect('/')

  else:
    self.redirect(decorator.authorize_url())

OTHER TIPS

Well in the m.attachments property you should have as you did a tuple for each attachment, the first element being the document title, and the second one the document data itself.

In your case, your document data is just a string, it's not a file, so here is your issue. You should retrieve the pdf file from Drive first, then put it as your attachment.

You can check here how to download a file content using the downloadURL property (or in your case the exportLinks.

Also, please make sure you set the proper extension for your file. Files without extension or with certain specific extensions are blacklisted and cannot be sent as attachments. Check this

Hope this helps.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top