1、问题描述
在使用 Python
内置的模块 smtplib
发送带中文名的附件邮件时,数据可以正常传输,但是但收件人收到的附件格式是bin
,附件名也不是发送时的名称。
附注:smtp,Simple Mail Transfer Protocol,
即简单邮件发送协议
import smtplib # 负责发送邮件
import string
from smtplib import SMTP_SSL
from email.mime.text import MIMEText # 构造文本
from email.mime.multipart import MIMEMultipart # 将多个集合对象集合起来
from email.header import Header
from email.mime.application import MIMEApplication # 用于添加附件
from email.mime.image import MIMEImage # 构造图片
import warnings
warnings.filterwarnings("ignore")
# 1、基础设置
host_server = 'smtp.xhqh.net.cn' #qq邮箱smtp服务器
sender_qq = '22***328@qq.com' #发件人邮箱
pwd = '******' # 发件人邮箱授权码
receiver = '2191003715@qq.com' # 收件人邮箱
mail_title = '净留存手续费' #邮件标题
# 2、邮件正文内容
mail_content = f"这是使用python登录QQ邮箱发送的邮件"
# 3、创建带附件的邮件对象
msg = MIMEMultipart() # 生成一个空的带附件的邮件实例
msg["Subject"] = Header(mail_title,'utf-8') # 生成邮件主题
msg["From"] = sender_qq # 生成发件人名称
msg["To"] = Header(receiver,"utf-8") # 生成收件人名称
msg.attach(MIMEText(mail_content,'html')) # 将正文插入邮件中,以html的形式呈现
# 4、添加附件
# 4.1 读取附件内容
attachment = MIMEApplication(open(r'C:\Users\liujieru\Desktop\test.xlsx','rb').read()) # 获取附件内容
attachment["Content-Type"] = 'application/octet-stream' # 指定附件为任何未知形式的二进制文件
# 4.2 给附件重命名
basename = "测试.xlsx"
attachment.add_header('Content-Dispositon', 'attachment', filename=('gbk', '', basename)) # 注意:此处basename要转换为gbk编码,否则中文会有乱码。
# 4.3将附件内容插入邮件中
msg.attach(attachment)
# 5、开始发送
try:
smtp = SMTP_SSL(host_server) # ssl登录连接到邮件服务器
smtp.set_debuglevel(0) # 0是关闭,1是开启debug
connect = smtp.ehlo(host_server) # 跟服务器打招呼,告诉它我们准备连接,最好加上这行代码
login = smtp.login(sender_qq,pwd)
send = smtp.sendmail(sender_qq, receiver, msg.as_string())
quit = smtp.quit()
print("邮件发送成功!")
except smtplib.SMTPException:
print("无法发送邮件!")
2、原因分析:
附件带有中文名
3、解决方案:
使用 yagmail
模块
在网上找了很多相关的解决办法,如:
方法一:
将 attachment['Content-Disposition'] = 'attachment;filename = "测试.xlsx"'
替换成 attachment.add_header('Content-Dispositon', 'attachment', filename=('gbk', '', basename))
但我的原始代码本来就是这么写的,仍然收到bin格式的附件,该方法 Pass
方法二:
写成attachment.add_header('Content-Disposition', 'attachment', filename=Header(basename, 'utf-8').encode())
这种形式,中、英文名称都可以支持
测试过,无效,Pass
网上能搜到的几乎都是针对附件重命名语法的调整,测试后无一例外的都无效
但天无绝人之路,既然都不行,那就另寻新欢、另辟蹊径,使用更简易的模块
解决方案之终极大 boss —— yagmail
模块,上代码:
yagmail
不是内置模块,需要先安装:pip install yagmail
import yagmail
from pathlib import Path
import pandas as pd
import numpy as np
# 1、基础设置
host_server = 'smtp.xhqh.net.cn' #qq邮箱smtp服务器
sender_qq = '22***328@qq.com' #发件人邮箱
pwd = '******' # 发件人邮箱授权码
receiver = '21***715@qq.com' # 收件人邮箱
# 2、创建带附件的邮件对象
yag = yagmail.SMTP(user=sender_qq, password=pwd, host=host_server)
# 3、邮件内容
contents = ["正文",] # 可以是一个列表
subject = "一般法人客户名单"
attachment = [f"{file_path/i}.xlsx"]
# 4、发送邮件
try:
# yag.send(收件人, 邮件主题, 邮件内容, 附件)
ret = yag.send(receiver, subject, contents, attachment)
print("邮件发送成功!")
except Exception as e:
print(e)
print("无法发送邮件!")
yag.close() # 关闭