Python发送带附件的HTML/纯文本邮件在IOS客户端附件不显示的解决方法
问题分析与解决方案
你的问题出在MIME消息的结构设计上:你用MIMEMultipart('alternative')作为顶级容器,但这个类型的作用是提供同一内容的不同格式备选版本(比如纯文本和HTML正文),并不适合直接添加附件。iOS邮件客户端对这种不符合标准的结构解析存在兼容性问题,导致附件无法显示。
正确的MIME结构逻辑
要同时支持多格式正文和附件,需要采用双层嵌套结构:
- 顶级容器用
MIMEMultipart('mixed'):用于组合独立的不同类型内容(正文组 + 附件) - 正文组用
MIMEMultipart('alternative'):专门存放纯文本和HTML两种正文版本,供客户端选择显示
修正后的完整代码
import smtplib import ssl from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText from email.mime.application import MIMEApplication # 邮件服务器配置 MAIL_SMTP_SERVER = "smtp.gmail.com" MAIL_PORT = 465 MAIL_USERNAME = '***' MAIL_PASSWORD = '***' email_to = '*@***.com' email_from = '#@###.com' email_subject = 'Email test' email_body_html = ''' <html> <body> <h1>Email Body</h1> <p>Here is some text</p> </body> </html> ''' email_body_plaintext = 'This is the plain text body' path='./test_doc.pdf' name='doc.pdf' # 1. 创建顶级mixed类型消息(容纳正文组和附件) mime_message = MIMEMultipart('mixed') mime_message["From"] = email_from mime_message["To"] = email_to mime_message["Subject"] = email_subject # 2. 创建alternative子消息,专门存放两种格式的正文 body_container = MIMEMultipart('alternative') body_container.attach(MIMEText(email_body_plaintext, "plain")) body_container.attach(MIMEText(email_body_html, "html")) # 3. 将正文组附加到顶级消息 mime_message.attach(body_container) # 4. 添加附件 with open(path, "rb") as file_to_read: file_attachment = MIMEApplication(file_to_read.read()) file_attachment.add_header("Content-Disposition", f"attachment; filename={name}") mime_message.attach(file_attachment) # 发送邮件 email_string = mime_message.as_string() context = ssl.create_default_context() with smtplib.SMTP_SSL(MAIL_SMTP_SERVER, MAIL_PORT, context=context) as server: server.login(MAIL_USERNAME, MAIL_PASSWORD) server.sendmail(email_from, email_to, email_string)
关键改动说明
- 顶级消息类型从
alternative改为mixed,符合MIME标准中“混合独立内容”的场景 - 用单独的
alternative容器包裹两种格式的正文,让客户端能正确识别这是同一内容的备选版本 - 附件直接附加到顶级
mixed消息中,作为独立内容部分,iOS邮件客户端可正常识别
内容的提问来源于stack exchange,提问作者Bill
相关产品推荐
相关产品推荐

