目录
前言
这篇文章主要是解决使用python发送邮件时遇到的一些问题
分别是在发送邮件时报了这么个错误
535, b'Login Fail. Please enter your authorization code to login. More information in http://XXX'
第二个是发送带有附件的邮件时,如果附件文件名为中文,则附件文件名"未命名"。
第三个是附件内容中有中文报错
UnicodeDecodeError: 'gbk' codec can't decode byte XXX in position XXX: illegal multibyte sequence
错误重现
先来一个小例子,我就使用QQ邮箱发送邮件到163邮箱
import smtplib
from email.header import Header
from email.mime.text import MIMEText
def QQEmailTo163Email():
# 登录QQ邮箱,发邮件给163邮箱
# ①设置服务器所需信息
# QQ邮箱服务器地址
# 登录QQ邮箱
mail_host = 'smtp.qq.com'
# QQ邮箱用户名(登录)
mail_userName = 'XXX@qq.com'
# QQ邮箱密码
mail_passWord = 'XXX'
# ===========================
# 邮件发送方邮箱
sender = 'XXX@qq.com'
# 邮件接收方邮箱
receivers = 'XXX@163.com'
# ===========================
# ②设置email信息
# 设置邮件内容,三个参数:第一个为文本内容,第二个 plain 设置文本格式,第三个 utf-8 设置编码
message = MIMEText('你好啊,这是一次测试', 'plain', 'utf-8')
# 设置邮件主题
# Header是用来构建邮件头的
subject = 'python发送邮件测试'
message['Subject'] = Header(f'{subject}', 'utf-8')
# 发送方信息
message['From'] = Header(f'{sender}', 'utf-8')
# 接收方信息
message['To'] = Header(f'{receivers}', 'utf-8')
# ===========================
# ③登录并发送邮件
try:
# 创建SMTP对象
smtpObj = smtplib.SMTP()
# 连接到服务器,25为SMTP端口号
smtpObj.connect(mail_host, 25)
# 登录服务器
smtpObj.login(mail_userName, mail_passWord)
# 发送
smtpObj.sendmail(sender, receivers, message.as_string())
# 退出
smtpObj.quit()
print('邮件发送成功')
except smtplib.SMTPException as e:
print(f'QQ向163→邮件发送失败,原因是:{e}')
if __name__ == '__main__':
QQEmailTo163Email()
然后就报了这么个错误,要求我们使用授权码登录
解决错误
那这么获得发送邮箱的授权码呢?由于我是QQ邮箱为发送方,那么就获得QQ邮箱的授权码
登录QQ邮箱→进入设置→账户
接下来应该不用说了,将获得到的授权码替换成密码,再执行一次
成功执行,打开163邮箱查看一下
问题重现
中文附件名"未命名"
先准备好两个的附件,附件内容不能有中文
这两个附件的名字是不是中文不重要,因为在发送附件的时候,可以对附件重命名
import smtplib
from email.header import Header
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
def QQEmailTo163Email_attachment():
# 发送带附件的邮件,首先要创建MIMEMultipart()实例,然后构造附件,如果有多个附件,可依次构造,最后利用smtplib.smtp发送。
# 登录QQ邮箱,发邮件给163邮箱
# ①设置服务器所需信息
# QQ邮箱服务器地址
# 登录QQ邮箱
mail_host = 'smtp.qq.com'
# QQ邮箱用户名(登录)
mail_userName = 'XXX@qq.com'
# QQ邮箱密码
# mail_passWord = 'XXX'
# ===========================
# 邮件发送方邮箱
sender = 'XXX@qq.com'
# 邮件接收方邮箱
receivers = 'XXX@163.com'
# ===========================
# 创建MIMEMultipart实例
message = MIMEMultipart()
# ②设置email信息
# 设置邮件主题
# Header是用来构建邮件头的
subject = 'python发送带附件的邮件测试'
message['Subject'] = Header(f'{subject}', 'utf-8')
# 发送方信息
message['From'] = Header(f'{sender}', 'utf-8')
# 接收方信息
message['To'] = Header(f'{receivers}', 'utf-8')
# 邮件正文内容
message.attach(MIMEText('你好啊,这是一次测试', 'plain', 'utf-8'))
# ===========================
# 构造附件1
file_name = '附件1.txt'
# 文件路径
filePath = f'file/{file_name}'
appendix1 = MIMEText(open(filePath).read(), 'html', 'utf-8')
# 定附件义内容类型
appendix1['Content-Type'] = 'application/octet-stream'
# 定义内容配置
# 这里的filename可以任意写,写什么名字,邮件中附件就显示什么名字,相当于重新命名
# # 附件名称为非中文且附件内容没有中文时使用
appendix1['Content-Disposition'] = f'attachment; filename="test1.txt"'
# # 将附件添加进邮件内容
message.attach(appendix1)
# 构造附件2
file_name2 = '附件2.txt'
# 文件路径
filePath2 = f'file/{file_name2}'
appendix2 = MIMEText(open(filePath2).read(), 'html', 'utf-8')
# 定附件义内容类型
appendix2['Content-Type'] = 'application/octet-stream'
# 定义内容配置
# 这里的filename可以任意写,写什么名字,邮件中附件就显示什么名字,相当于重新命名
# 附件名称为非中文且附件内容没有中文时使用
appendix2['Content-Disposition'] = f'attachment; filename="test2.txt"'
# # 将附件添加进邮件内容
message.attach(appendix2)
# ③登录并发送邮件
try:
# 创建SMTP对象
smtpObj = smtplib.SMTP()
# 连接到服务器,25为SMTP端口号
smtpObj.connect(mail_host, 25)
# 登录服务器
smtpObj.login(mail_userName, mail_passWord)
# 发送
smtpObj.sendmail(sender, receivers, message.as_string())
# 退出
smtpObj.quit()
print('邮件发送成功')
except smtplib.SMTPException as e:
print(f'QQ向163→邮件发送失败,原因是:{e}')
if __name__ == '__main__':
QQEmailTo163Email_attachment()
注意,我这里对附件进行了重命名,将它们的名字改为了test1.txt和test2.txt,主要是要先看正常情况下是怎么样的,要形成对比。
接收到的文件名没有问题,把文件下载下来看一看
可以看见test2出了点小问题,英文竟然也出了问题,唉,等下一起解决吧
接下来我将附件名称改为中文
appendix1['Content-Disposition'] = f'attachment; filename="{file_name}"'
appendix2['Content-Disposition'] = f'attachment; filename="{file_name2}"'
再次执行
可以看见出了问题,文件名不太对劲,甚至连后缀都没有
解决方法
# 附件命名为中文时使用,文件可以为中文,但下载附件打开时会乱码
appendix1.add_header('Content-Disposition', 'attachment', filename=('utf-8', '', f'{file_name}'))
我先改一个,方便形成对比参照
效果显著,至于内容,我试过了,跟之前的一样。
中文文件名问题已经结解决了,接下来要解决的是,附件内容中的中文乱码
附件内容中的中文报错
先在附件中添加中文
执行之前的代码
直接就裂开,跑都跑不动,报了这么个错误,很显然是中文引起的
UnicodeDecodeError: 'gbk' codec can't decode byte XXX in position XXX: illegal multibyte sequenc
解决方法
这个其实挺好解决的,出现这个现象的原因是:在python中默认的编码方式是 “ gbk ”,而Windows中的文件默认的编码方式是 “ utf-8 ” ,所以导致python编译器无法成功读取或写入文件内容。
在读取文件的时候,指定一下编码就好了
with open(file=f'{filePath}', mode='r', encoding='utf-8') as f:
data = f
appendix1 = MIMEText(data.read(), 'html', 'utf-8')
执行一下
文件名没有问题
附件内容也没有问题
尾声
很抱歉,写的有些乱,再给大家总结一下吧
# 附件名称为非中文且附件内容没有中文时使用
appendix1['Content-Disposition'] = f'attachment; filename="{file_name}"'
# 附件命名为中文时使用,文件可以为中文,但下载附件打开时会乱码
appendix1.add_header('Content-Disposition', 'attachment', filename=('utf-8', '', f'{file_name}'))
#使用这种读取方式可以读取中文内容
with open(file=f'{filePath}', mode='r', encoding='utf-8') as f:
data = f
appendix1 = MIMEText(data.read(), 'html', 'utf-8')
如果这篇文章对您有所帮助,那么这篇文章就有意义!
感谢您的观看!