Python如何正确设置邮件MIME 确保csv附件不被误识别为htm格式
问题现象
使用smtplib+email模块发送csv格式附件,邮件内容可正常读取,但从邮箱下载附件时文件被自动识别为.htm格式,异常效果如下:
原实现代码如下:
def new_email(df): message = MIMEMultipart() message['Subject'] = "New data" message['From'] = "someGenericMail@outlook.com" message['To'] = "someOthergGenericMail@gmail.com" bio = io.BytesIO() df.to_csv(bio,mode="wb") bio.seek(0) attachement = MIMEApplication(bio.read(),"csv") bio.close() attachement.add_header("Content-Disposition", "attachement", filename="Results.csv") body = MIMEText("Here is your data", 'plain') message.attach(body) message.attach(attachement) with smtplib.SMTP("smtp.office365.com", 587) as server: server.starttls() server.login("someGenericMail@outlook.com","password") server.sendmail("someGenericMail@outlook.com","someOthergGenericMail@gmail.com", message.as_string())
问题根因
三个配置错误触发邮箱的文件类型自动嗅探机制,导致类型误判:
- MIME类型不符合标准:CSV的IANA标准注册MIME类型为
text/csv,原代码传入"csv"作为MIMEApplication的子类型,会生成非标准的application/csv类型头,主流邮箱服务无法识别该类型,会自动扫描内容猜测文件类型。 - 关键字段拼写错误:
Content-Disposition的合法属性值为attachment(表示该部分是附件),原代码拼写为attachement,邮箱无法识别该声明,不会把对应内容作为独立附件处理,直接触发内容解析逻辑。 - 编码未显式声明:生成CSV和构造MIME部分时均未指定字符编码,特殊字符可能打乱邮箱的类型判断逻辑。
修正代码
按以下逻辑调整即可保证附件被正确识别为CSV格式:
- 用标准
text/csv类型构造附件MIME部分,显式指定utf-8编码 - 修正
Content-Disposition字段的拼写错误 - 生成CSV文件时显式指定编码,避免乱码和类型误判
import io import smtplib from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText def new_email(df): message = MIMEMultipart() message['Subject'] = "New data" message['From'] = "someGenericMail@outlook.com" message['To'] = "someOthergGenericMail@gmail.com" bio = io.BytesIO() # 显式指定utf-8编码,不需要传wb模式,BytesIO默认支持二进制写入 df.to_csv(bio, encoding='utf-8', index=False) bio.seek(0) # 使用标准text/csv MIME类型,指定编码 attachment = MIMEText(bio.read(), 'csv', 'utf-8') bio.close() # 修正attachment拼写错误 attachment.add_header("Content-Disposition", "attachment", filename="Results.csv") body = MIMEText("Here is your data", 'plain', 'utf-8') message.attach(body) message.attach(attachment) with smtplib.SMTP("smtp.office365.com", 587) as server: server.starttls() server.login("someGenericMail@outlook.com","password") server.sendmail("someGenericMail@outlook.com","someOthergGenericMail@gmail.com", message.as_string())
调整后附件的Content-Type头为标准的
text/csv; charset="utf-8",Content-Disposition声明合法,所有主流邮箱、客户端都会正确识别为CSV格式附件,不会再出现自动改后缀为htm的问题。
内容的提问来源于stack exchange,提问作者Haggerman Swaggerman
相关产品推荐
相关产品推荐

