Python使用MIME发送带PDF附件的邮件失败:无报错但邮件未送达
解决带PDF附件的邮件发送问题(无报错但邮件未送达)
你遇到的核心问题是用MIMEText处理二进制PDF文件——这会导致附件内容损坏,要么邮件被服务器拦截,要么对方收到后附件无法正常解析,所以代码没报错但实际发送失败。另外之前的UnicodeDecodeError,本质也是用文本编码方式读取二进制PDF导致的,完全没必要用codecs处理这类文件。
问题根源拆解
- PDF是二进制格式,不能用文本模式读取,必须以二进制方式打开
MIMEText仅适用于纯文本内容,二进制附件得用MIMEApplication(或MIMEBase)来构造,同时要设置正确的MIME类型和编码
修改后的完整代码
import smtplib import os from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText from email.mime.application import MIMEApplication gmail_user = input("Your gmail: ") gmail_password = input("Your password: ") print("sending...") # 假设你已提前定义好 email_reciver、sheet、l、texto 这些变量 example = "email test" msg = MIMEMultipart() msg['Subject'] = sheet.cell_value(l,1) msg['From'] = gmail_user msg['To'] = email_reciver # 添加邮件正文,明确指定utf-8编码避免乱码 body = MIMEText(texto, 'plain', 'utf-8') msg.attach(body) # 处理PDF附件:用二进制模式读取+MIMEApplication构造 pod = os.path.join(os.getcwd(), "doc.pdf") # 用os.path.join替代硬编码路径,更规范 with open(pod, 'rb') as fp: # 指定subtype为pdf,让邮件客户端正确识别附件类型 record = MIMEApplication(fp.read(), _subtype='pdf') record['Content-Disposition'] = 'attachment; filename="doc.pdf"' msg.attach(record) try: server = smtplib.SMTP_SSL('smtp.gmail.com', 465) server.ehlo() server.login(gmail_user, gmail_password) print(l) server.sendmail(gmail_user, email_reciver, msg.as_string()) server.close() print("邮件发送成功!") except Exception as e: # 捕获具体错误信息,方便排查(比如Gmail安全设置问题) print(f"发送失败,错误详情: {str(e)}")
关键改动说明
- 二进制读取PDF:用
open(pod, 'rb')直接读取二进制内容,彻底规避文本编码错误 - 替换附件构造方式:用
MIMEApplication处理PDF,指定_subtype='pdf'确保附件类型被正确识别 - 明确正文编码:给
MIMEText加上utf-8编码参数,避免正文乱码 - 优化路径拼接:用
os.path.join替代硬编码的\\,代码更规范且兼容不同系统 - 捕获具体错误:把模糊的
except:改成捕获具体异常并打印信息,方便排查比如Gmail安全权限、邮箱地址错误等问题
额外注意事项
- 如果你用Gmail,需要确保账号开启了允许低安全性应用访问(开启2FA的话要用应用密码登录),否则会登录失败
- 提前用
print(os.path.exists(pod))验证PDF文件路径是否正确 - 确认
email_reciver是有效的邮箱地址
内容的提问来源于stack exchange,提问作者rafael gf
相关产品推荐
相关产品推荐

