Python发送邮件
By 青衣极客 Blue Geek In 2020-01-20
有时我们需要监控一些线上的任务或者收集网络咨询,并及时通知相关的责任人任务运行的状态。在企业中解决这种问题的方法至少有三种:一是发短信,二是开发即时聊天工具并设置机器人,三是发邮件。这三个方法中前两种要么费钱,要么费力,只有第三种是免费且简单的,对于普通开发者的普通任务更友好。如果你有几个在线的小项目或者非商业的项目,那么使用邮件来监控线上状态就是最划算的方法。
1. 所需材料
我们当然也可以选择自己搭建邮件服务器,但是这样就相当于还要多维护一个模块。对于“懒惰”的程序员而言并不是最优选择。现在的邮件服务提供商基本都是免费的,我们又何必在这些保密性并不强的事情上拒绝现成服务呢?从现状来看,国内邮件服务提供商,比如新浪、网易、QQ等,已经可以将邮件发送到全球;但是考虑到可能会向一些敏感的收件地址发送邮件,那么使用微软的outlook邮箱就万无一失了。
无论使用什么客户端发送邮件,基本都是需要提供以下四条信息:邮件提供商的smtp发件服务器地址,smtp发件代理端口,用户名和用户密码。大家可以根据自己的实际情况修改以下代码的配置。如果需要使用django模块发送邮件的话,这四个同名变量也是核心设置。
# 发件代理服务器
EMAIL_HOST = 'smtp.XXXXXXXXX.com'
# SMTP代理服务器端口,不同的服务提供商开放的端口可能不同
EMAIL_PORT = 587
# 管理员邮箱
EMAIL_HOST_USER = 'xxxxxxxxxx@outlook.com'
# 管理员邮箱密码,有些服务提供商可能需要“授权码”,比如QQ
EMAIL_HOST_PASSWORD = 'xxxxxxxx'
2. 纯文本邮件
相比于复杂格式的邮件,纯文本邮件在接收端解析的时候基本没有什么风险,即使是一些老旧的服务器仍然能够正确获得纯文本的邮件信息。python发送邮件的功能由两个模块配合完成。email模块负责邮件内容的组织,包括格式、附件以及主题。比如下面的代码就是创建一个纯文本内容的邮件。
from email.mime.text import MIMEText
from email.header import Header
# 构造测试邮件
msg = MIMEText('测试python邮件发送功能', 'plain', 'utf-8')
msg['Subject'] = Header('【测试】纯文本格式邮件', 'utf-8')
print(msg.as_string())
smtplib模块负责将邮件内容发送到指定的目标邮箱。收件邮箱地址存储在一个列表中,因为可能会有群发邮件的需求。下面封装了一个发送邮件的示例,其中的操作顺序是不能更改的。
import smtplib
# 封装邮件发送的函数
def my_send_email(receivers, msg):
# 检查收件人
if not isinstance(receivers, list):
raise ValueError('not list type, but {}'.format(type(receivers_list)))
if len(receivers) == 0:
raise ValueError('not allow empty receivers')
# 设置收发件人
msg['From'] = EMAIL_HOST_USER
msg['To'] = ';'.join(receivers)
# 连接账户并发送邮件
try:
smtp_server = smtplib.SMTP(EMAIL_HOST)
smtp_server.connect(EMAIL_HOST, EMAIL_PORT)
smtp_server.ehlo()
smtp_server.starttls()
smtp_server.login(EMAIL_HOST_USER, EMAIL_HOST_PASSWORD)
smtp_server.sendmail(EMAIL_HOST_USER, receivers, msg.as_string())
smtp_server.quit()
print('send email to {} succc'.format(receivers))
except smtplib.SMTPException as e:
print('failed to send email, caused by {}'.format(e))
# 发送测试邮件
receivers = ['cnbluegeek@gmail.com']
my_send_email(receivers, msg)
send email to ['cnbluegeek@gmail.com'] succc
从输出的信息来看应该是发送成功了。我们到对应的邮箱账户下查看接收的情况。

3. HTML邮件
现在的服务器一般都是支持HTML格式的邮件解析的,而使用HTML格式能够展示更加丰富多彩的数据,可读性更强,吸引力更大。使用python发送html邮件只需将邮件内容使用html的方式即可,具体负责邮件发送的模块使用还是与之前的一样。
# 构造邮件内容
email_cont="""
<h1>测试邮件HTML格式</h1>
<p> 这是一封html格式的<span style="color:#ff0000">测试邮件</span> </p>
"""
msg = MIMEText(email_cont, 'html', 'utf-8')
msg['Subject'] = Header('【测试】HTML格式邮件', 'utf-8')
# 发送html格式测试邮件
my_send_email(receivers, msg)
send email to ['cnbluegeek@gmail.com'] succc
查看客户端邮箱账户可以发现收到的邮件情况如下:

html格式的邮件总体而言比纯文本要美观得多,如果尚有余力,现在大家发送邮件也更愿意使用html格式。
4. 带附件的邮件
有些邮件免不了要带上一些附件,比如文本数据、音频数据、图像数据等等。python所提供的发邮件功能也能满足这些需求了,同样只是在构造邮件内容时稍有改动。带附件的邮件消息需要使用MIMEMultipart构造,然后将文字内容和附件添加到消息上。
from email.mime.multipart import MIMEMultipart
email_cont="""
<h1>测试邮件HTML格式</h1>
<p> 这是一封带附件的<span style="color:#ff0000">测试邮件</span> </p>
"""
msg = MIMEMultipart()
msg['Subject'] = Header('【测试】带附件的邮件', 'utf-8')
# 设置邮件内容
msg.attach(MIMEText(email_cont, 'html', 'utf-8'))
# 设置附件
att1 = MIMEText(open('../data/bg64/test.txt', 'rb').read(), 'base64', 'utf-8')
att1["Content-Type"] = 'application/octet-stream'
att1["Content-Disposition"] = 'attachment; filename="helloworld.txt"'
msg.attach(att1)
# 发送带附件的测试邮件
my_send_email(receivers, msg)
send email to ['cnbluegeek@gmail.com'] succc
程序显示发送成功以后,到客户端邮箱查看如下:

从上图看出,邮件已经正常发送到目标邮箱。
使用这种方式来发送监控告警信息不仅免费而且开发简单,如果你有自己的线上任务在运行不妨考虑这种方式。如果你使用django项目开发网站,可以使用Django封装的邮件发送,其实其内部的核心仍然是调用python的邮件发送模块。

COMMENT
博客评论区功能由Github Issue提供,提交Issue时请以本文标题为话题。
"BG64-Python发送邮件"