Reputation: 952
I am attempting to convert a Google Doc to a PDF (using the Drive API) and then attaching the file to an email (using the Gmail API).
The script runs, coverts the Google Doc to a PDF, sends an email with the attachment, but the PDF attachment is blank / corrupt.
I suspect the issue is with line: msg.set_payload(fh.read())
The relevant documentation: set_payload and io.Bytes()
Any guidance is greatly appreciated.
import base64
import io
from apiclient.http import MediaIoBaseDownload
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
fileId = '1234'
content_type = 'application/pdf'
response = drive.files().export_media(fileId=fileId, mimeType=content_type)
fh = io.BytesIO()
downloader = MediaIoBaseDownload(fh, response)
done = False
while done is False:
status, done = downloader.next_chunk()
logging.info("Download %d%%." % int(status.progress() * 100))
message = MIMEMultipart()
message['to'] = '[email protected]'
message['from'] = '[email protected]'
message['subject'] = 'test subject'
msg = MIMEText('test body')
message.attach(msg)
main_type, sub_type = content_type.split('/', 1)
msg = MIMEBase(main_type, sub_type)
msg.set_payload(fh.read()) # i suspect the issue is here
msg.add_header('Content-Disposition', 'attachment', filename='an example file name.pdf')
message.attach(msg)
message_obj = {'raw': base64.urlsafe_b64encode(message.as_string())}
service.users().messages().send(userId="me", body=message_obj).execute()
Upvotes: 1
Views: 282
Reputation: 201338
How about this modification? I think that about the download from Google Drive, your script is correct. So I would like to propose to modify the script for sending an email with the attachment file.
I thought that msg.set_payload(fh.read())
is one of the modification points as you say. So the data retrieved by getvalue()
was converted by email.encoders.encode_base64()
. And also I modified message_obj
.
Please modify as follows.
msg = MIMEText('test body')
message.attach(msg)
main_type, sub_type = content_type.split('/', 1)
msg = MIMEBase(main_type, sub_type)
msg.set_payload(fh.read()) # i suspect the issue is here
msg.add_header('Content-Disposition', 'attachment', filename='an example file name.pdf')
message.attach(msg)
message_obj = {'raw': base64.urlsafe_b64encode(message.as_string())}
service.users().messages().send(userId="me", body=message_obj).execute()
from email import encoders # Please add this.
msg = MIMEText('test body')
message.attach(msg)
main_type, sub_type = content_type.split('/', 1)
msg = MIMEBase(main_type, sub_type)
msg.set_payload(fh.getvalue()) # Modified
encoders.encode_base64(msg) # Added
msg.add_header('Content-Disposition', 'attachment', filename='an example file name.pdf')
message.attach(msg)
message_obj = {'raw': base64.urlsafe_b64encode(message.as_bytes()).decode()} # Modified
service.users().messages().send(userId="me", body=message_obj).execute()
In my environment, I could confirm that the modified script worked. But if this didn't work in your environment, I apologize.
Upvotes: 1