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

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

本文主要学习如何使用smtplib库发送各种形式的邮件内容。该库主要用smtplib.SMTP()类,使用这个类封装一个SMTP连接,语法如下:

smtplib.SMTP(host ='',port = 0,local_hostname = None,[ timeout,] source_address = None )

SMTP实例后有以下常用方法:

方法

描述

SMTP.connect([host[,  port]])

连接到指定的SMTP服务器

SMTP.login(user,  password)

登录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 –ysystemctl start sendmail

smtp默认25端口,查看是否监听:

ss -anpt|grep 25

sendmail服务运行,就可以使用了:

from smtplib import SMTPs = SMTP("localhost")to_mail = ["baojingtongzhi@163.com"] #收件人列表,可以写多个# 内容必须靠左,否则邮件头不识别msg = '''\ From: aliang@ctnrs.comSubject: test这是一份测试邮件'''.encode("utf8")   s.sendmail("aliang@ctnrs.com",to_mail,msg)s.quit()

msg对象里From表示发件人,Subject是邮件标题,换行后输入的是邮件内容。

上面示例使用本地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(to_mail)转成字符串,以逗号分隔元素。

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

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

示例2:发送邮件并抄送

import smtplibdef 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 " % (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 smtplibfrom email.mime.text import MIMETextfrom email.mime.multipart import MIMEMultipartfrom email.header import Headerfrom email import encodersfrom email.mime.base import MIMEBasefrom 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('管理员 ' % 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 smtplibfrom email.mime.text import MIMETextfrom email.mime.multipart import MIMEMultipartfrom email.header import Headerfrom 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('管理员 ' % 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 smtplibfrom email.mime.text import MIMETextfrom email.mime.image import MIMEImagefrom email.mime.multipart import MIMEMultipartfrom email.header import Headerfrom 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('管理员 ' % 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")

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

- END -

 推荐阅读 
Python 自动创建 Grafana 仪表板Python 调用 Kubernetes API 自动化管理资源支付宝架构师眼中的高并发架构

SpringCloud微服务项目运维必知必会Java 应用最常见的3个问题排查思路一篇漫画带你了解 Linux 内核长啥样!

点亮,服务器三年不宕机

为什么每个邮件收到后都会有一个htm的附件_Python3.x 发送各种形式的告警邮件内容...相关推荐

  1. 为什么每个邮件收到后都会有一个htm的附件_Python 发送邮件各种姿势

    电子邮件是互联网应用最广的通讯服务,在工作中经常会有自动发邮件的需求,例如监控告警.注册通知.激活链接等. 而发送邮件是基于SMTP协议,接收邮件则是基于POP3或IMAP协议. 那POP3与IMAP ...

  2. html 表格_UiPath之发送正文包含表格的邮件(通过Html实现表格)

    我们在日常工作中,经常需要把整理好的表格,复制粘贴到邮件的正文中,那么怎样通过UiPath来实现带有表格内容的邮件正文. 本次内容所要用到的Activities有: ReadRange---获取数据源 ...

  3. 裁缝式开发:用MATLAB批量发送一封图文并茂的邮件

    问题背景 前几天,女朋友公司要求她周末加班发送宣传推广邮件给高校老师,而我才知晓之前她们发送邮件全靠手动-目前待发名单至少有三千人,而现在才发了一百多封,我的心情如下 为了能够不加班周末去放风筝,于是 ...

  4. 邮件内容以html形式,如何以邮件的形式发送HTML文件?

    回答: 发送HTML格式的邮件voID jButton8_actionPerFormed(ActionEvent e) { try {//此段代码用来发送带有HTML信息的邮件 Properties ...

  5. alertmanager设置告警邮件的邮件头/邮件模板

    模板,让邮件更好看! alertmanager对应告警消息的下发配置的较完善,官方给出的邮件配置几乎都是见名知义的,本文我们来看看告警邮件的邮件头部和邮件内容模板怎样自定义设置. 官方给出的可选配置如 ...

  6. 神奇的数学之回文数(不论开始是什么正整数,在经过有限次正序数和倒序数相加的步骤后,都会得到一个回文数)

    神奇的数学之回文数 Description 回文数是一种数字.如:8008, 这个数字正读是8008,倒读也是8008,正读倒读一样,所以这个数字就是回文数. 任取一个正整数,如果不是回文数,将该数与 ...

  7. 操作系统:为什么IO操作不占用CPU却会导致进程阻塞?Web服务器每接收一个请求都会创建一个新的线程吗?Tomcat服务器工作原理?

    为什么IO操作不占用CPU却会导致进程阻塞?Web服务器每接收一个请求都会创建一个新的线程吗?这两个问题在我学操作系统以前我都挺困惑的.现在我来尝试着解答一下. 1. 为什么IO操作不占用CPU却会导 ...

  8. TURBOMAIL反垃圾邮件清洁工,还你一个清爽的邮箱

    "清明时节雨纷纷,路上行人欲断魂",又到了一年一季的梅雨季节,看到阴沉沉的天气.湿漉漉的地面.发霉的墙壁等等,总让人心情郁闷.昏昏欲睡.员工们每天呼吸着灰蒙蒙的空气上班,再看到垃圾 ...

  9. Java的HttpClient类以POST方式提交数据,目标端收到后中文乱码

     h ttpClient HttpMethod NameValuePair setRequestBody 今天开发时,遇到利用Java中HttpClient类以POST方式提交数据,目标收到后中文 ...

最新文章

  1. php中的大括号用法
  2. 炼丹侠必知的9大池化操作​汇总
  3. 搭建基于飞桨的OCR工具库,总模型仅8.6M的超轻量级中文OCR,单模型支持中英文数字组合识别、竖排文本识别、长文本识别的PaddleOCR
  4. spring boot定时任务解析
  5. SQL Serve 查询所有可用的数据库语句
  6. CoralCache:一个提高微服务可用性的中间件
  7. android_ratingbar的使用错误
  8. pptx库ppt演示 python_详解 Python 操作 PPT 的各种骚操作!
  9. Scala学习教程笔记三之函数式编程、集合操作、模式匹配、类型参数、隐式转换、Actor、...
  10. MAC VSCODE配置C语言开发环境
  11. python开发人工智能要不要很高数学_CFA、FRM持证人的“秘密武器”—Python,连潘石屹都在学,你确定不要了解一下吗?...
  12. opencv画框显示python_Python OpenCV实现鼠标画框效果
  13. 重磅:国刊4区变1区!2021年中科院分区表正式公布!
  14. 评价——TOPSIS
  15. 蛋白质结构预测---残基接触的基础知识(二)
  16. #01 Linear Regression Excise
  17. Hive中如何统计用户三个月或者以上的行为数据
  18. UiBot If(如果条件成立)
  19. python汇率换算程序_Python第六课 汇率兑换4.0
  20. 浅析GIS行业地图绘制基本要求

热门文章

  1. Vue项目中的RSA加解密
  2. 如何从“点子”落地到“执行”?—完整解析1个手游传播类mini项目的进化
  3. Socket开发框架之消息的回调处理
  4. Qt3D学习之键盘交互
  5. 03 入门 - 安装MVC 5和创建应用程序
  6. android开发(44) 使用了 SoundPool 播放提示音
  7. OSPF:STUB与NSSA区别
  8. Cisco1721的简单配置
  9. [高级软件调试方法] SoftProbe调试方法及实现
  10. 华为机试HJ24:合唱队