使用Python发送带docx附件的邮件,收信无附件且无报错如何解决
问题原因及修复方案
核心错误点
- 附件头配置错误:
add_header中给filename参数传入了文件对象attach_file,而非你定义的文件名变量attach_file_name,导致邮件客户端无法识别合法的附件文件名,直接忽略了该附件。 - MIME多部分类型错误:初始化
MIMEMultipart时使用了alternative子类型,该类型仅用于存放多版本正文(如纯文本、HTML正文互为备选),附件不属于正文备选内容,需要改为mixed子类型才能被邮件协议正确识别。
优化点
- 打开的附件文件读取后未关闭,可使用
with语句自动管理文件句柄避免资源泄漏。 - docx格式有标准MIME类型,替换默认的
octet-stream后不同邮件客户端的兼容性更好。 - 若需要同时兼容纯文本和HTML正文,可嵌套MIME结构:外层用
MIMEMultipart("mixed")作为根容器,内层创建MIMEMultipart("alternative")存放两类正文,最后把正文容器和附件都挂载到根容器即可。
修正后的核心代码
import smtplib, ssl from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart from email.mime.base import MIMEBase from email import encoders sender_email = email receiver_email = toemail password = password # 调整multipart类型为mixed message = MIMEMultipart("mixed") message["Subject"] = Subject message["From"] = sender_email message["To"] = receiver_email message.attach(htmlmessage) # 用with语句管理文件打开关闭,设置docx标准MIME类型 with open(attach_file_name, 'rb') as attach_file: payload = MIMEBase('application', 'vnd.openxmlformats-officedocument.wordprocessingml.document') payload.set_payload(attach_file.read()) encoders.encode_base64(payload) # 传入正确的文件名变量,拆分参数避免特殊字符异常 payload.add_header('Content-Disposition', "attachment", filename=attach_file_name) message.attach(payload) context = ssl.create_default_context() with smtplib.SMTP_SSL("smtp.gmail.com", 465, context=context) as server: server.login(sender_email, password) server.sendmail( sender_email, receiver_email, message.as_string() )
内容的提问来源于stack exchange,提问作者oneclick
相关产品推荐
相关产品推荐

