使用python发送html gmail时不显示文本

问题描述

我正在尝试使用 python 发送 gmail 电子邮件。电子邮件包括纯文本和要在电子邮件显示的 html 图像。但是,当我尝试发送电子邮件时,没有显示文本(仅显示图像)。

代码如下:

import smtplib
from email.mime.multipart  import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.image import MIMEImage

host='smtp.gmail.com'
port=587
username='sender@gmail.com'
password='mypassword'
from_email=username
to_list=['recipient@gmail.com']

email_conn=smtplib.SMTP(host,port)
email_conn.ehlo()
email_conn.starttls()
email_conn.login(username,password)



msg=MIMEMultipart('Alternative')
temp=MIMEMultipart('Alternative2')

msg['Subject']='Hello'
msg['From']=username



txt='Welcome home'

part1=MIMEText(txt,'plain')




msgText = MIMEText('<img src="cid:image1">','html')
temp.attach(msgText)


fp = open('/home/user/Pictures/image.jpg','rb')
msgimage = MIMEImage(fp.read())
fp.close()

# Define the image's ID as referenced above
msgimage.add_header('Content-ID','<image1>')
temp.attach(msgimage)


msg.attach(part1)
msg.attach(temp)


email_conn.sendmail(from_email,to_list,msg.as_string())
email_conn.quit()

解决方法

直接错误是您正在创建类型为 multipart/Alternative2 的无效 MIME 部分。您似乎将类型(应该是 IANA 批准的一组有限标签中的一个)与唯一标识符混淆了。

更根本的是,您似乎遵循了一些过时的 email 准则。在 Python 3.6+ 中创建新消息的正确方法是使用(不再是)新的 EmailMessage API。

此外,您还需要重构代码,以便消息创建不会与消息发送混合在一起。在下面,我简单地删除了所有 smtplib 代码;这也使您可以轻松地使用 print(msg.as_string()) 进行本地故障排除,而不是发送消息。

from email.message import EmailMessage
from email.utils import make_msgid


username = 'sender@gmail.com'
to_list = ['recipient@gmail.com']

msg = EmailMessage()
msg['Subject'] = 'Hello'
msg['From'] = username
# Need recipient!
msg['To'] = ','.join(to_list)

msg.set_content('Welcome home')

image_id = make_msgid()

# Notice closing slash at the end of <img ... />
msg.add_alternative('<img src="%s" />' % image_id.strip('<>'),subtype='html')

with open('/home/user/Pictures/image.jpg','rb') as fp:
    msg.get_payload()[1].add_related(
        fp.read(),'image','jpeg',cid=image_id)

这与 email examples in the documentation.

中的“芦笋”示例非常相似

然后,您将继续创建 SMTP 会话和 smtp.send_message(msg),而不是绕道而行,分别将消息显式转换为可以传递给遗留 sendmail 方法的字符串;这是新 API 的众多改进之一。