繁体   English   中英

python 3.6 gmail api——发送带有附件的电子邮件

[英]python 3.6 gmail api ― send email with attachement

这个python 3脚本假设创建一个电子邮件,将一个文件(使用它的url)附加到它并发送它。 它发送电子邮件,但create_message_with_attachment()

类型错误:附加对具有非多部分有效负载的消息无效

我确实阅读了谷歌文档。 讨论它的堆栈线程专注于花哨的附件样式,同时混合了 Python 版本的不同语法。

下面的代码是几个来源的拼凑而成。 我很难在create_message_with_attachment()中将它们连接在一起。

例如,我不知道我是否应该包括这个(它来自 create_message_without_attachment() ,它适用于这个代码。参见底部)

raw = base64.urlsafe_b64encode(msg.as_bytes())
raw = raw.decode()
body = {'raw': raw}
return body

带有附件代码的创建消息:

import httplib2
import os
import oauth2client
from oauth2client import client, tools
import base64
from email import encoders

#needed for attachment
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

#needed for gmail service
from apiclient import errors, discovery  

#The scope URL for read/write access to the gmail api 
SCOPES = 'https://www.googleapis.com/auth/gmail.send'

CLIENT_SECRET_FILE = 'client_secret.json'
APPLICATION_NAME = 'Gmail API Python Send Email'


def get_credentials():
    # If needed create folder for credential
    home_dir = os.path.expanduser('~') #>> C:\Users\me
    credential_dir = os.path.join(home_dir, '.credentials') # >>C:\Users\me\.credentials   (it's a folder)
    if not os.path.exists(credential_dir):
        os.makedirs(credential_dir)  #create folder if doesnt exist
    credential_path = os.path.join(credential_dir, 'gmail-python-email-send.json')

    #Store the credential
    store = oauth2client.file.Storage(credential_path)
    credentials = store.get()

    if not credentials or credentials.invalid:
    # Create a flow object. (it assists with OAuth 2.0 steps to get user authorization + credentials)
        flow = client.flow_from_clientsecrets(CLIENT_SECRET_FILE, SCOPES)
        flow.user_agent = APPLICATION_NAME
        credentials = tools.run_flow(flow, store)
        print('Storing credentials to ' + credential_path)

    return credentials



def SendMessage(sender, to, subject, msgHtml, msgPlain):
    credentials = get_credentials() 

    http = httplib2.Http()  # Create an httplib2.Http object to handle our HTTP requests, and authorize it using credentials.authorize()

    # http is the authorized httplib2.Http() 
    http = credentials.authorize(http)

    service = discovery.build('gmail', 'v1', http=http)

    message_with_attach = create_message_without_attachment(sender, to, subject, msgHtml, msgPlain)
    SendMessageInternal(service, "me", message_with_attach)


def SendMessageInternal(service, user_id, message): 
    try:
        message = (service.users().messages().send(userId=user_id, body=message).execute())  ####need  to get user_id before

        message_ID = message['id']
        print(f'Message Id: {message_ID}')
        return [message, message_ID] #return value as list
    except errors.HttpError as error:
        print(f'An error occurred: {error}')    

def create_message_with_attachment(sender, to, subject, msgHtml, msgPlain):

    # multipart container can contain other MIME parts.  (attachment will be independent of the multipart/alternative)
    msg = MIMEMultipart('alternative')
    msg['To'] = to
    msg['From'] = sender
    msg['Subject'] = subject

    # convert both part to a MIME compatible string
    part1 = MIMEText(msgPlain, 'plain') 
    part2 = MIMEText(msgHtml, 'html')

    # create .txt attachment
    filePath=r"C:\Users\me\Desktop\test_Attachment.txt"
    myFile=open(filePath, "rb")
    attachment= MIMEApplication(myFile.read())
    msg.set_payload(myFile) # 
    myFile.close()
    msg.set_payload(myFile) # 
    myFile.close()

    #This will add a header that looks like: "Content-Disposition: attachment; filename="test_Attachment.txt" "
    attachment.add_header('content-disposition', 'attachment', filename = ('utf-8', '', 'test_Attachment.txt'))

    # Attach parts into message container.
    msg.attach(attachment)
    msg.attach(part1)
    msg.attach(part2)

    # Encode the payload using Base64.
    raw = encoders.encode_base64(msg)
    return raw


def main():
    to = "youremail@gmail.com"
    sender = "myemail@gmail.com"
    subject = "subject test1"
    msgHtml = r'Hi<br/>Html <b>hello</b>'
    msgPlain = "Hi\nPlain Email"
    message_text= "this is message text"
    SendMessage(sender, to, subject, msgHtml, msgPlain)


if __name__ == '__main__':
    main()

此功能在此代码中成功发送无附件的电子邮件:

def create_message_without_attachment (sender, to, subject, msgHtml, msgPlain):
    msg = MIMEMultipart('alternative')
    msg['Subject'] = subject
    msg['From'] = sender
    msg['To'] = to
    msg.attach(MIMEText(msgPlain, 'plain'))
    msg.attach(MIMEText(msgHtml, 'html'))

    raw = base64.urlsafe_b64encode(msg.as_bytes())
    raw = raw.decode()
    body = {'raw': raw}
    return body

Edit1(避免重复相同的答案):您将在答案中找到发送带有(或不带有)附件的电子邮件所需的代码(和解释)。

Edit2:由于 randomfigure 改进了代码

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM