Я пытаюсь использовать GMail API для отправки писем с вложениями (.pdf). Я начал с примера кода Googles и обновил его (с помощью этого сообщества) до Python 3. Пока код работает, вложение приходит с повреждением. Я пробовал все, что мог придумать, но я не могу понять это.
Вот что у меня есть:
from __future__ import print_function
import pickle
import os.path
import base64
from lxml.html import fromstring
from lxml.etree import tostring
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from apiclient import errors
# If modifying these scopes, delete the file token.pickle.
SCOPES = ['https://www.googleapis.com/auth/gmail.send']
def auth():
creds = None
# The file token.pickle stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists('token.pickle'):
with open('token.pickle', 'rb') as token:
creds = pickle.load(token)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file('credentials.json', SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.pickle', 'wb') as token:
pickle.dump(creds, token)
service = build('gmail', 'v1', credentials=creds)
return service
def SendMessage(service, user_id, message):
try:
message = (service.users().messages().send(userId=user_id, body=message).execute())
print('Message Id: {}'.format(message['id']))
return message
except (errors.HttpError, error):
print('An error occurred: {}'.format(error))
def CreateMessage(sender, to, subject, message_text):
message = MIMEText(message_text,'html')
message['to'] = to
message['from'] = sender
message['subject'] = subject
return {'raw': base64.urlsafe_b64encode(message.as_bytes()).decode()}
def CreateMessageWithAttachment(sender, to, subject, message_text, file_dir, filename):
message = MIMEMultipart()
message['to'] = to
message['from'] = sender
message['subject'] = subject
msg = MIMEText(message_text,'html')
message.attach(msg)
path = os.path.join(file_dir, filename)
msg = MIMEBase('application','octet-stream')
msg.set_payload(open(path, 'rb').read())
msg.add_header('Content-Disposition', 'attachment', filename=filename)
message.attach(msg)
return {'raw': base64.urlsafe_b64encode(message.as_bytes()).decode()}
if __name__ == '__main__':
service = auth()
#import html from a pre-generated file
text = open('message.html','r').read()
text = fromstring(text)
text = tostring(text).decode('utf-8')
msg = CreateMessageWithAttachment('from.address@gmail.com','to.address@gmail.com','This weeks report',text,'e:/Reports/','20200229.pdf')
SendMessage(service,'me',msg)
Я пытался использовать email.encoders
вместо base64
, но вложение по-прежнему повреждено (и примерно в два раза больше, чем должно быть). Код не должен быть слишком умным, когда дело доходит до MIME-типа. Тип файла всегда будет одинаковым. Любая помощь будет принята с благодарностью.