Отправка электронной почты с вложениями с помощью Gmail API - PullRequest
0 голосов
/ 03 марта 2020

Я пытаюсь использовать 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-типа. Тип файла всегда будет одинаковым. Любая помощь будет принята с благодарностью.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...