Python smtplib.sendmail发送的Mime Multipart正文在iPhone上不显示

9

这是我的代码:

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)上,我只能看到附件,而无法看到正文。


我遇到了完全相同的问题,只不过我是附加图像而不是CSV文件。我注意到,如果我不包括图像/添加标题,正文就会正常显示。如果您能够解决此问题,请告诉我。谢谢! - Atul Bhatia
2个回答

6

我在这条评论中找到了解决方法:如何使用SMTP发送附件?

我的第一行应该是:

msg = MIMEMultipart('mixed')

而不是“替代品”。

2
对于那些寻求完整解决方案的人,应该使用 在包括iOS默认邮件应用在内的所有电子邮件客户端中都能正常工作的方式

何时使用multipart/mixed

来自RFC

多部分的主要子类型“mixed”旨在在身体部位是独立的且预计按顺序显示的情况下使用。任何实现不识别的多部分子类型都应视为子类型“mixed”。

因此,当消息的所有部分(text/htmltext/plainimage/png等)同等重要且所有部分都应向用户显示时,应使用multipart/mixed类型。

这意味着如果您将text/html附加到消息中,并将text/plain作为html的回退,那么两者都将以一个覆盖另一个的方式显示给用户,这没有任何意义

何时使用multipart/alternative

来自RFC

特别地,每个部分都是相同信息的“替代”版本。用户代理应该认识到各个部分的内容是可交换的。用户代理应该根据用户的环境和偏好选择“最佳”类型,或者提供可用的替代方案。一般来说,选择最佳类型意味着仅显示可以显示的最后一部分。例如,可以使用此方法以花哨的文本格式发送邮件,以便可以轻松地在任何地方显示它

这意味着您附加到multipart/alternative消息的任何内容都可以视为相同的值但以不同的形式呈现。

为什么这很重要?

如果在文本部分之后,您将图像(image/pngimage/jpeg)附加到multipart/alternative消息中,则它可以被视为与消息本身同等重要,因此用户将看到的唯一内容是该图像 - 没有text/htmltext/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)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接