一、创造灵感
这几天在指导学生做毕业设计,学生做的是跌倒检测。然后我突然想到,如果这个系统只是单纯地从视频流中检测到人的跌倒动作,其实并没有任何的用途和意义。于是,我又想到,如果跌倒的检测结果,能够通知到其他人,比如老人的儿子、女儿、或者邻居,那岂不是可以即时的发现?是的,于是我通过大语言模型,生成了Python实现邮件发送的代码。效果还可以,就是遇到了一个报错。但是最终通过对大模型的push,我的目的也达到了。
二、Python实现纯文本的邮件发送
如果只是通知,那么纯文本就足够了。实现的思路很简单,因为邮件是基于SMTP网络协议实现的,所以需要用到一个SMTP服务器,这个一般由邮件公司提供。然后就是还有提供一个用于发送邮件的账号,及其密码或者授权码。此外,接收方的邮箱账号我们也需要提供,不然发送给谁呢?最后就是写一份纯文本的字符串啦,当做是邮件的正文。
下面是实现的代码:
import smtplib
from email.mime.text import MIMEText
import base64
# 设置邮件服务器信息
smtp_server = 'smtp.qq.com' # QQ邮件服务器地址
smtp_port = 465 # QQ邮件服务器端口
username = '10********@qq.com' # 换成你的QQ邮箱账号
password = '**************' # 换成你的QQ邮箱授权码,设置方式:https://mbd.baidu.com/newspage/data/dtlandingsuper?nid=dt_3758488124459701973
# 设置邮件内容
sender = '10*********@qq.com' # 换成你的QQ邮箱账号
receivers = ['*********@163.com'] # 换成收件人邮箱账号
subject = '测试Python发送邮件' # 设置邮件主题
body = '世界,你好!' # 设置邮件正文(可以使用HTML格式设置邮件正文,这样更好看些)
# 创建邮件
message = MIMEText(body, 'plain', 'utf-8')
# 设置邮件header
nickname = "中文昵称"
encoded_nickname = base64.b64encode(nickname.encode('utf-8')).decode('utf-8') # 带中文的header需转成base64格式
from_header = f"=?utf-8?B?{encoded_nickname}?= <{sender}>"
message['From'] = from_header
message['To'] = "收件人"
message['Subject'] = subject
try:
# 连接邮件服务器
server = smtplib.SMTP_SSL(smtp_server, smtp_port)
server.login(username, password) # 登录邮件服务器
# 发送邮件
server.sendmail(sender, receivers, message.as_string())
print("邮件发送成功!")
except smtplib.SMTPException as e:
print("邮件发送失败:", e)
finally:
# 关闭连接
server.quit()
实现邮件的发送有两个值得注意的地方,一是邮箱密码,二是邮件的header。
(一)邮箱密码的获取
现在的邮箱账号一般不会直接使用密码进行登录,而是使用授权码,作为其登录方式。那么授权码怎么才可以获得呢?很简单,在网页上登录你的邮箱,就可以拿到一个。以QQ邮箱为例:
先是登录QQ邮箱:
然后点击设置,找到“账号”选项:
滑到下面的“POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务”:开启该服务。这样就可以获取一个邮箱的授权码啦。授权码的用途就是在第三方邮箱软件登录你的账号,这里的“第三方”也指你在Python里写的程序!
在上面的“继续获取授权码”就可以了。期间可能需要你扫描发送一个短信,验证你的个人信息、身份信息啥的。按步骤做就好了。
(二)邮件的header设置
QQ邮箱服务器要求邮件的header使用base64编码。这个时候就需要对邮件的header进行编码的转换(其实上面给出的代码已经做了相应的转换):
import base64
nickname = "中文昵称"
# 带中文的header需转成base64格式
encoded_nickname = base64.b64encode(nickname.encode('utf-8')).decode('utf-8')
from_header = f"=?utf-8?B?{encoded_nickname}?= <{sender}>"
message['From'] = from_header
message['To'] = "收件人"
message['Subject'] = subject
否则,就会报错,例如:
邮件发送失败: (550, b'The "From" header is missing or invalid. Please follow RFC5322, RFC2047, RFC822 standard protocol. https://service.mail.qq.com/detail/124/995 .')
这主要是由于QQ邮箱的反垃圾邮件设置造成:
根据这个提示,我将其抛给大语言模型,强行让它对邮件的header进行base64编码,终于把问题解决掉。
发送邮件的效果如下:
看得出来,正文是OK的,但header还是有点小问题。目的基本达到。
三、Python实现带附件的邮件发送
邮件的发送有时候还需要附上文件,比如,跌倒检测的时候,如果能够附上一个跌倒的图,那就更加有助于人类去判断模型的识别结果是否可信。
有了前面的纯文本邮件发送代码,实现一个带附件的邮件发送,就简单多了。此时我们需要在Python中import两个东西,即:
from email.mime.multipart import MIMEMultipart
from email.mime.application import MIMEApplication
没有这两个类,不能发送附件。
发送的时候添加附件(下面的'tom_and_jerry.jpg'是我放在项目路径下的一张图片,然后我用此作为邮件的附件)的方法如下:
# 添加附件
attachment_path = 'tom_and_jerry.jpg' # 替换为你的附件文件路径
with open(attachment_path, 'rb') as attachment_file:
attachment = MIMEApplication(attachment_file.read(), Name='tom_and_jerry.jpg') # 替换为你的附件文件名
attachment['Content-Disposition'] = f'attachment; filename="tom_and_jerry.jpg"' # 替换为你的附件文件名
message.attach(attachment)
而邮件的对象也要变成:
message = MIMEMultipart() # 创建一个 MIMEMultipart 消息对象
其它的地方跟Python实现纯文本邮件无异。完整的代码如下:
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.application import MIMEApplication
import base64
# 设置邮件服务器信息
smtp_server = 'smtp.qq.com' # QQ邮件服务器地址
smtp_port = 465 # QQ邮件服务器端口
username = '**********@qq.com' # 换成你的QQ邮箱账号
password = '****************' # 换成你的QQ邮箱授权码,设置方式:https://mbd.baidu.com/newspage/data/dtlandingsuper?nid=dt_3758488124459701973
# 设置邮件内容
sender = '***********@qq.com' # 换成你的QQ邮箱账号
receivers = ['*********@163.com'] # 换成收件人邮箱账号
subject = '测试Python发送邮件' # 设置邮件主题
# 创建邮件
body = '世界,你好!' # 设置邮件正文(可以使用HTML格式设置邮件正文,这样更好看些)
message = MIMEMultipart() # 创建一个 MIMEMultipart 消息对象
message.attach(MIMEText(body, 'html', 'utf-8'))
# 添加附件
attachment_path = 'tom_and_jerry.jpg' # 替换为你的附件文件路径
with open(attachment_path, 'rb') as attachment_file:
attachment = MIMEApplication(attachment_file.read(), Name='tom_and_jerry.jpg') # 替换为你的附件文件名
attachment['Content-Disposition'] = f'attachment; filename="tom_and_jerry.jpg"' # 替换为你的附件文件名
message.attach(attachment)
# 设置邮件header
nickname = "中文昵称"
encoded_nickname = base64.b64encode(nickname.encode('utf-8')).decode('utf-8') # 带中文的header需转成base64格式
from_header = f"=?utf-8?B?{encoded_nickname}?= <{sender}>"
message['From'] = from_header
message['To'] = "收件人"
message['Subject'] = subject
try:
# 连接邮件服务器
server = smtplib.SMTP_SSL(smtp_server, smtp_port)
server.login(username, password) # 登录邮件服务器
# 发送邮件
server.sendmail(sender, receivers, message.as_string())
print("邮件发送成功!")
except smtplib.SMTPException as e:
print("邮件发送失败:", e)
finally:
# 关闭连接
server.quit()
邮件发送的效果如下图所示:
效果感觉还不错咧!
四、后记
好久都没有写CSDN博客了,自从22年ChatGPT出来以后,很多问题都直接去问大语言模型了,这也使得自己很多问题都通过大模型得到了解决。那么写博客还有意义吗?感觉很少。要不是官方把我的原力值冻结了,可能这篇博客也不会出现在CSDN上边。
其实也不是没有意义啦,记录一下自己的学习过程,代码的执行效果,还是不错的!虽然大模型解决了不少问题,但是多步推理能力还比较弱,也就是说,大模型在解决某个问题的深度上,还是有一定限制,如果博客记录的深度足够,那么还是有一点意义的。
本篇博客深度比大模型的直接回答,好一丢丢,但整体还是偏水。
无所谓啦,写着消磨一下时间也好。