Python smtplib.sendmail 的多部分 Mime 邮件在 iPhone 上不显示
这是我的代码:
FROM = ''
TO = ''
SMTPSERVER = ''
MYEMAILPASSWORD = ""
import smtplib
from email.MIMEMultipart import MIMEMultipart
from email.MIMEText import MIMEText
from email.mime.base import MIMEBase
from email import encoders
def physicallySend(listOfAttachments):
msg = MIMEMultipart('alternative')
msg['Subject'] = "Testing"
msg['From'] = FROM
msg['To'] = TO
textPart = MIMEText("Hello. I should be able to see this body.", 'plain')
msg.attach(textPart)
for attachmentFilename in listOfAttachments:
fp = open(attachmentFilename, 'rb')
file1 = MIMEBase('application','csv')
file1.set_payload(fp.read())
fp.close()
encoders.encode_base64(file1)
file1.add_header('Content-Disposition','attachment;filename=%s' % attachmentFilename)
msg.attach(file1)
server = smtplib.SMTP(SMTPSERVER)
server.ehlo()
server.starttls()
server.login(FROM, MYEMAILPASSWORD)
server.sendmail(FROM, to, msg.as_string())
server.quit()
return True
physicallySend(["testfile.csv"])
虽然我在Gmail和Outlook上能正常看到邮件的正文,但在我的iPhone(6.1.3)上,我只看到附件,正文却看不到。
2 个回答
2
对于那些想要找到完整解决方案的人,这个可以在所有邮件客户端上正常工作,包括iOS默认邮件应用。
什么时候使用 multipart/mixed
来自RFC的说明
主要的子类型“mixed”是用来处理那些各部分内容相互独立并且需要依次显示的情况。任何实现不认识的多部分子类型都应该被视为“mixed”类型。
所以,当消息的所有部分(text/html
、text/plain
、image/png
等)都是同样重要,并且都应该展示给用户时,就应该使用multipart/mixed
类型。
这意味着,如果你在消息中附加了text/html
,同时又附加了text/plain
作为HTML的备用格式,那么这两者会一个接一个地展示给用户,这样做是没有意义的。
什么时候使用 multipart/alternative
来自RFC的说明
特别是,每个部分都是相同信息的“替代”版本。用户代理应该识别这些部分的内容是可以互换的。用户代理应该根据用户的环境和偏好选择“最佳”类型,或者提供可用的替代选项。一般来说,选择最佳类型意味着只显示最后一个可以展示的部分。这可以用来发送邮件,以一种华丽的文本格式,使其可以在任何地方轻松显示。
这意味着你附加到multipart/alternative
消息中的任何内容都可以被视为相同的值,只是表现形式不同。
这为什么重要?
如果在文本部分之后,你在multipart/alternative
消息中附加了一张图片(image/png
、image/jpeg
),那么这张图片会被视为和消息本身同样重要,因此用户看到的只有图片,而不会看到text/html
或text/plain
部分。
不过,这在现在的大多数客户端中并不成立——它们足够聪明,知道你的意思,但仍然这样做的客户端是iOS默认邮件应用——你不想让这些用户感到困惑。
那么正确的做法是什么呢?
经过这些解释,现在会更容易理解了。
# keeps the textual and attachment parts separately
root_msg = MIMEMultipart('mixed')
root_msg['Subject'] = email.subject
root_msg['From'] = self._format_from_header()
root_msg['To'] = self._format_addrs(recipients=email.recipients)
alter_msg = MIMEMultipart('alternative')
plain_text = MIMEText('some text', 'plain', 'UTF-8')
html = MIMEText('<strong>some text</strong>', 'html')
alter_msg.attach(plain_text)
alter_msg.attach(html)
# now the alternative message (textual)
# is just a part of the root mixed message
root_msg.attach(alter_msg)
img_path = '...'
filename = os.path.basename(img_path)
with open(img_path, 'rb') as f:
attachment = MIMEImage(f.read(), filename=filename)
attachment.add_header('Content-Disposition', 'attachment', filename=filename)
# now the images (attachments) will be shown alongside
# either plain or html message and not instead of them
root_msg.attach(attachment)
6