Python3.x 发送各种形式的告警邮件内容

By | 2020年9月16日
目录
[隐藏]

在写脚本时,放到后台运行,想知道执行情况,会通过邮件,短信,微信等方式通知管理员,邮件当前用的最多的通知方式。在Linux下,Shell脚本发送邮件正确是件很简单的事,有现成的邮件服务软件或调用运营商邮箱服务器,对于Python而言,需要编写脚本调用邮件服务器来发送邮件。

Python分别提供了收发邮件的库,smtplib,poplib和imaplib。

该库主要用smtplib.SMTP()类,使用这个类封装一个SMTP连接,语法如下:

smtplib.SMTP(host =”,port = 0,local_hostname = None,[ timeout,] source_address = None )
SMTP实例后有以下常用方法:

方法

描述

SMTP.connect([主机[,端口]])

连接到指定的SMTP服务器

SMTP.login(用户名,密码)

登录SMTP服务器

SMTP.sendmail(from_addr,to_addrs,msg,mail_options = [],rcpt_options = [])

发送邮件

from_addr:邮件发件人

to_addrs:邮件收件人

msg:发送消息

SMTP.quit()

关闭SMTP会话

SMTP.close()

关闭SMTP服务器连接

为更好的学习smtplib模块,我们下面写几个具体的示例来熟悉它的用法。

示例1:发送文本邮件
先通过本地 SMTP 服务器发送邮件。

本地SMTP服务器,可以通过安装sendmail,postfix等服务提供。

例如安装sendmail:

yum install sendmail –y
systemctl start sendmail
SMTP 默认 25 端口,查看是否监听:

ss -anpt|grep 25
sendmail 服务运行,就可以使用了:

from smtplib import SMTP
s = SMTP(“localhost”)
to_mail = [“baojingtongzhi@163.com”] #收件人列表,可以写多个
# 内容必须靠左,否则邮件头不识别
msg = ”’\
From: aliang@ctnrs.com
Subject: test
这是一份测试邮件”’.encode(“utf8”)
s.sendmail(“aliang@ctnrs.com”,to_mail,msg)
s.quit()
msg对象里来自表示发件人,主题是邮件标题,换行后输入的是邮件内容。

上面的示例使用本地SMTP服务器发送的邮件,这种自建的SMTP服务器容易被当做垃圾邮件,甚至大部分公有云也无法自建(禁止25端口),所以一般情况下都采用个人邮箱或企业邮箱发邮件。

例如,使用163邮箱发邮件:

from smtplib import SMTP
email_account = “baojingtongzhi@163.com”
account_password = “VCGXTBHXFPVDVLGZ” #授权密码
s = SMTP(“smtp.163.com”)
s.login(email_account, account_password)
to_mail = [“1121267855@qq.com”]
msg = f”’\
From: {email_account}
Subject: 测试
这是一封测试邮件”’.encode(“utf8”)
s.sendmail(“baojingtongzhi@163.com”,to_mail,msg)
s.quit()
现在一般个人邮箱需要授权码才可以在客户端收发邮件,设置-> POP3 / SMTP / IMAP->授权密码:

运行结果:

smtplib.SMTPDataError: (554, b’DT:SPM 163 smtp12,EMCowAC312M29l5fNpBQAw–.41693S2 1600058934,please see http://mail.163.com/help/help_spam_16.htm?ip=27.189.225.231&hostid=smtp12&time=1600058934′)
访问指定的163网址,SMTP554错误是:“ 554 DT:SUM收件人发件人和信头发件人不匹配”
在上面第一个示例中你会发现收件人是空的,看这样163的SMTP服务器拒绝的原因应该就是这里收件人没指定。

重新修改下msg对象,添加收件人:

msg = f”’\
From: {email_account}
To: {‘,’.join(to_mail)}
Subject:测试
这是一封测试邮件”’.encode(“utf8”)
‘,’。join(t o_mail )转成字符串,以逗号分隔元素。

如果msg对象含带中文需要编码encode(“utf8”)

可以正常发送邮件了。msg这个格式是SMTP规定的,一定要遵守。

示例2:发送邮件并抄送
import smtplib
def sendMail(body):
smtp_server = ‘smtp.163.com’
email_account = ‘baojingtongzhi@163.com’
account_password = ‘VCGXTBHXFPVDVLGZ’
to_mail = [“1121267855@qq.com”]
cc_mail = [“xxx@163.com”]
from_name = ‘monitor’
subject = ‘监控’
“””
msg = ”’\
From: {email_account}
To: {‘,’.join(to_mail)}
Subject: 测试”’
“””
# 或者写成列表再拼接,相比上面顶头写更美化些
mail = [
“From: %s <%s>” % (from_name, account_password),
“To: %s” % ‘,’.join(to_mail),
“Subject: %s” % subject,
“Cc: %s” % ‘,’.join(cc_mail),
“”,
body
]
msg = ‘\n’.join(mail).encode(“utf8”)

try:
s = smtplib.SMTP()
s.connect(smtp_server, ’25’)
s.login(email_account, account_password)
s.sendmail(email_account, to_mail+cc_mail, msg)
s.quit()
except smtplib.SMTPException as e:
print(“Error: %s” %e)
if __name__ == “__main__”:
sendMail(“这是一封测试邮件”)

s.sendmail(from_mail,to_mail + cc_mail,msg)这里看到,收件人和抄送人为什么放在一起发送呢?

其实无论是收件人还是抄送人,这些收到的邮件都是一样的,SMTP服务器也是认为发件人这样张贴的发出。所以实际上并没有抄送这个概念,只是在邮件头加了抄送人的信息罢了!

示例3:发送邮件带附件

由于SMTP.sendmail()方法不支持添加附件,所以需要通过email模块来实现。email模块是一个构造邮件和解析邮件的模块。

import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.header import Header
from email import encoders
from email.mime.base import MIMEBase
from email.utils import parseaddr, formataddr

# 格式化邮件地址
def formatAddr(s):
name, addr = parseaddr(s)
return formataddr((Header(name, ‘utf-8’).encode(), addr))

def sendMail(body, attachment):
smtp_server = ‘smtp.163.com’
email_account = ‘baojingtongzhi@163.com’
account_password = ‘VCGXTBHXFPVDVLGZ’
to_mail = [“1121267855@qq.com”]

# 构造一个MIMEMultipart对象代表邮件本身
msg = MIMEMultipart()
# Header对中文进行转码
msg[‘From’] = formatAddr(‘管理员 <%s>’ % email_account)
msg[‘To’] = ‘,’.join(to_mail)
msg[‘Subject’] = Header(‘监控’, ‘utf-8’)

# plain代表纯文本
msg.attach(MIMEText(body, ‘plain’, ‘utf-8’))

# 二进制方式模式文件
with open(attachment, ‘rb’) as f:
# MIMEBase表示附件的对象
mime = MIMEBase(‘text’, ‘txt’, filename=attachment) # 使用MIMEBase类构造附件并添加到msg对象
# filename是显示附件名字
mime.add_header(‘Content-Disposition’, ‘attachment’, filename=attachment)
# 获取附件内容
mime.set_payload(f.read())
encoders.encode_base64(mime)
# 作为附件添加到邮件
msg.attach(mime)
try:
s = smtplib.SMTP()
s.connect(smtp_server, “25”)
s.login(email_account, account_password)
s.sendmail(email_account, to_mail, msg.as_string()) # as_string()把MIMEText对象变成str
s.quit()
except smtplib.SMTPException as e:
print(“Error: %s” % e)
if __name__ == “__main__”:
sendMail(‘这是一封携带附件的测试邮件’, ‘test.txt’)

示例4:发送HTML邮件

import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.header import Header
from email.utils import parseaddr, formataddr

# 格式化邮件地址
def formatAddr(s):
name, addr = parseaddr(s)
return formataddr((Header(name, ‘utf-8’).encode(), addr))

def sendMail(body):
smtp_server = ‘smtp.163.com’
email_account = ‘baojingtongzhi@163.com’
account_password = ‘VCGXTBHXFPVDVLGZ’
to_mail = [“1121267855@qq.com”]

# 构造一个MIMEMultipart对象代表邮件本身
msg = MIMEMultipart()
# Header对中文进行转码
msg[‘From’] = formatAddr(‘管理员 <%s>’ % email_account)
msg[‘To’] = ‘,’.join(to_mail)
msg[‘Subject’] = Header(‘监控’, ‘utf-8’)
msg.attach(MIMEText(body, ‘html’, ‘utf-8’))

try:
s = smtplib.SMTP()
s.connect(smtp_server, “25”)
s.login(email_account, account_password)
s.sendmail(email_account, to_mail, msg.as_string()) # as_string()把MIMEText对象变成str
s.quit()
except smtplib.SMTPException as e:
print(“Error: %s” % e)
if __name__ == “__main__”:
body = “””

测试邮件

这是一封HTML测试邮件

“””
sendMail(body)

示例5:发送图片邮件

import smtplib
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from email.header import Header
from email.utils import parseaddr, formataddr

# 格式化邮件地址
def formatAddr(s):
name, addr = parseaddr(s)
return formataddr((Header(name, ‘utf-8’).encode(), addr))

def sendMail(body, image):
smtp_server = ‘smtp.163.com’
email_account = ‘baojingtongzhi@163.com’
account_password = ‘VCGXTBHXFPVDVLGZ’
to_mail = [“1121267855@qq.com”]

# 构造一个MIMEMultipart对象代表邮件本身
msg = MIMEMultipart()
# Header对中文进行转码
msg[‘From’] = formatAddr(‘管理员 <%s>’ % email_account)
msg[‘To’] = ‘,’.join(to_mail)
msg[‘Subject’] = Header(‘监控’, ‘utf-8’)
msg.attach(MIMEText(body, ‘html’, ‘utf-8’))

# 二进制模式读取图片
with open(image, ‘rb’) as f:
msgImage = MIMEImage(f.read()) # 使用MIMEImage类构造图片并添加到msg对象
# 定义图片ID,根据ID在HTML里获取图片
msgImage.add_header(‘Content-ID’, ”)
msg.attach(msgImage)

try:
s = smtplib.SMTP()
s.connect(smtp_server, “25”)
s.login(email_account, account_password)
s.sendmail(email_account, to_mail, msg.as_string()) # as_string()把MIMEText对象变成str
s.quit()
except smtplib.SMTPException as e:
print(“Error: %s” % e)
if __name__ == “__main__”:
body = “””

测试图片


“””
sendMail(body, “123.jpg”)

动手试试吧〜 代码复制粘贴就行。

– 结束 –

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注