在系统管理领域,我们常常使用邮件来发送告警信息、业务质量报表等,方便运维人员第一时间了解业务的服务状态。
这里需要用到一个模块是smtplib,它是python自带的一个模块,可以通过它来实现邮件的发送功能,模拟一个smtp客户端,通过与smtp服务器交互来实现邮件发送的功能,这可以理解成Foxmail的发邮件功能,在第一次使用之前我们需要配置smtp主机地址、邮箱账号及密码等信息。

SMTP类定义及方法

smtplib.SMTP([host[,port[,local_hostname[,timeout]]]]),作为SMTP的构造函数,功能是与smtp服务器建立连接,在连接成功后,就可以向服务器发送相关请求,比如登录、校验、发送、退出等。host参数为远程smtp主机地址,比如smtp.163.com;port为连接端口,默认为25。SMTP类具有如下方法:
1. SMTP.connect([host[,port]])方法,连接远程smtp主机方法,host为远程主机地址,port为远程主机smtp端口,默认25,也可以直接使用host:port形式来表示,如:

SMTP.connect(“smtp.163.com”,“25”)

2. SMTP.login(user,password)方法,远程smtp主机的校验方法,
参数为用户名与密码。
3. SMTP.sendmail(from_addr,to_addrs,msg[,mail_optionsrcpt_options])方法,实现邮件的发送功能,参数依次为是发件人、收件人、邮件内容。to_addrs可以是一个列表。
4. SMTP.starttls([keyfile[,certfile]])方法,启用TLS(安全传输)模式,所有SMTP指令都将加密传输,例如使用gmail的smtp服务时需要启动此项才能正常发送邮件,如SMTP.starttls()。
5. SMTP.quit()方法,断开smtp服务器的连接。

发送第一个邮件

import smtplib

HOST = "smtp.163.com" #定义smtp主机
TITLE = "Test email from Python" #定义邮件主题
TO = "myqq@qq.com" #定义邮件收件人,
FROM = "mymail@163.com" #定义邮件发件人,mymail自行替换
text = "here i am,lin!" #邮件内容

#组装sendmail方法的邮件主体内容,各段以"\r\n"进行分隔
BODY = "\r\n".join([ 
"From:%s" % FROM,
"To:%s" % TO,
"Subject:%s" % TITLE ,
"",
text
])
try:
	server = smtplib.SMTP() #创建一个SMTP()对象
	server.connect(HOST,"25") #通过connect方法连接smtp主机
	server.starttls() #启动安全传输模式
	server.login("mymail@163.com","mypass") #邮箱账号登录校验,注意这里的密码并不一定为邮箱登录密码,像163邮箱需要在设置里开启SMTP,并使用里面的授权码进行登录
	server.sendmail(FROM, [TO], BODY) #邮件发送
	server.quit() #断开smtp连接
except Exception as e:
    print(e)

如果都设置好后,运行上面代码就可以往自己的qq发送邮件了,注意标题、内容都不能为中文,否则会报错。

定制个性化的邮件

通过邮件传输简单的文本已经无法满足我们的需求,比如我们时常会定制业务质量报表,在邮件主体中会包含HTML、图像、声音以及附件格式等,MIME(Multipurpose Internet Mail Extensions,多用途互联网邮件扩展)作为一种新的扩展邮件格式很好地补充了这一点,下面介绍几个Python中常用的MIME实现类,这里需要用到一个新的模块email

1. email.mime.multipart.MIMEMultipart([_subtype[,boundary[,_subparts[,_params]]]]),作用是生成包含多个部分的邮件体的MIME对象,参数_subtype指定要添加到"Content-type:multipart/subtype"报头的可选的三种子类型,分别为mixed、related、alternative,默认值为mixed。定义mixed实现构建一个带附件的邮件体;定义related实现构建内嵌资源的邮件体;定义alternative则实现构建纯文本与超文本共存的邮件体。
2. email.mime.audio.MIMEAudio(_audiodata[,_subtype[,_encoder[, _params]]]),创建包含音频数据的邮件体,_audiodata包含原始二进制音频数据的字节字符串。
3. email.mime.image.MIMEImage(_imagedata[,_subtype[,_encoder[,_params]]]),创建包含图片数据的邮件体,_imagedata是包含原始图片数据的字节字符串。
4. email.mime.text.MIMEText(_text[,_subtype[,_charset]]),创建包含文本数据的邮件体,_text是包含消息负载的字符串,_subtype指定文本类型,支持plain(默认值)或html类型的字符串。

开始定制第一个邮件(实现HTML格式的数据报表邮件)

这需要我们刚才前面讲到的的smtplib及email模块结合使用,我们可以将email.mime理解成smtplib模块邮件内容主体的扩展,从原先默认只支持纯文本格式扩展到HTML,同时支持附件、音频、图像等格式,smtplib只负责邮件的投递即可。

import smtplib
from email.mime.text import MIMEText

HOST = "smtp.163.com" #定义smtp主机
TITLE = u"官网流量数据报表" #定义邮件主题
TO = "myqq@qq.com" #定义邮件收件人,
FROM = "mymail@163.com" #定义邮件发件人,mymail@gmail.com


#创建一个MIMEText对象,分别指定HTML内容、类型(文本或html)、字符编码
msg=MIMEText("""
<table width="800" border="0" cellspacing="0" cellpadding="4">
<tr>
<td bgcolor="#CECFAD" height="20"duokan-code-cn">:14px">*官网数据
<a href="monitor.domain.com">更多>></a></td>
</tr>
<tr>
<td bgcolor="#EFEBDE" height="100"duokan-code-cn">:13px">
1)日访问量:<font color=red>152433</font> 访问次数:23651 页面浏览量:
45123 点击数:545122 数据流量:504Mb<br>
2)状态码信息<br>
 ; ;500:105 404:3264 503:214<br>
3)访客浏览器信息<br>
 ; ;IE:50% firefox:10% chrome:30% other:10%<br>
4)页面信息<br>
 ; ;/index.php 42153<br>
</td>
</tr>
</table>""","html","utf-8")

msg['Subject'] = TITLE #邮件主题
msg['From']=FROM #邮件发件人,邮件头部可见
msg['To']=TO #邮件收件人,邮件头部可见

try:
    server = smtplib.SMTP() #创建一个SMTP()对象
    server.connect(HOST,"25") #通过connect方法连接smtp主机
    server.starttls() #启动安全传输模式
    server.login("mymail@163.com","mypass") #邮箱账号登录校验
    server.sendmail(FROM, [TO], msg.as_string()) #邮件发送
    server.quit() #断开smtp连接
except Exception as e:
    print(e)

实现图文格式的服务器性能报表邮件

上面我们通过MIMEText类来实现HTML格式的邮件,当要求包含图片数据的邮件内容时,需要引用MIMEImage类,若邮件主体由多个MIME对象组成,则同时需引用MIMEMultipart类来进行组装。下面我们看下通过MIMEText与MIMEImage类的组合来实现图文格式的服务器性能报表邮件的定制。

import smtplib
from email.mime.multipart import MIMEMultipart #导入MIMEMultipart类
from email.mime.text import MIMEText #导入MIMEText类
from email.mime.image import MIMEImage #导入MIMEImage类

def addimg(src,imgid): #添加图片函数,参数1:图片路径,参数2:图片id
    fp = open(src, 'rb') #打开文件
    msgImage = MIMEImage(fp.read()) #创建MIMEImage对象,读取图片内容并作为参数
    fp.close() #关闭文件
    msgImage.add_header('Content-ID', imgid) #指定图片文件的Content-ID,<img>标签src用到
    return msgImage #返回msgImage对象

HOST = "smtp.gmail.com" #定义smtp主机
SUBJECT = u"业务性能数据报表" #定义邮件主题
TO = "testmail@qq.com" #定义邮件收件人
FROM = "mymail@163.com" #定义邮件发件人
msg = MIMEMultipart('related') #创建MIMEMultipart对象,采用related定义内嵌资源的邮件体

msgtext = MIMEText(""" #创建一个MIMEText对象,HTML元素包括表格<table>及图片
<img>
<table width="600" border="0" cellspacing="0" cellpadding="4">
<tr bgcolor="#CECFAD" height="20"duokan-code-cn">:14px">
<td colspan=2>*官网性能数据 <a href="monitor.domain.com">更多>></a>
</td>
</tr>
<tr bgcolor="#EFEBDE" height="100"duokan-code-cn">:13px">
<td>
<img src="cid:io"></td><td>
<img src="cid:key_hit"></td>
</tr>
<tr bgcolor="#EFEBDE" height="100"duokan-code-cn">:13px">
<td>
<img src="cid:men"></td><td>
<img src="cid:swap"></td>
</tr>
</table>""","html","utf-8") #<img>标签的src属性是通过Content-ID来引用的

msg.attach(msgtext) #MIMEMultipart对象附加MIMEText的内容
msg.attach(addimg("img/bytes_io.png","io")) #使用MIMEMultipart对象附加MIMEImage的内容
msg.attach(addimg("img/myisam_key_hit.png","key_hit"))
msg.attach(addimg("img/os_mem.png","men"))
msg.attach(addimg("img/os_swap.png","swap"))
msg['Subject'] = SUBJECT #邮件主题
msg['From']=FROM #邮件发件人,邮件头部可见
msg['To']=TO #邮件收件人,邮件头部可见

try:
    server = smtplib.SMTP() #创建一个SMTP()对象
    server.connect(HOST,"25") #通过connect方法连接smtp主机
    server.starttls() #启动安全传输模式
    server.login("mymail@163.com","mypassword") #邮箱账号登录校验
    server.sendmail(FROM, TO, msg.as_string()) #邮件发送
    server.quit() #断开smtp连接
    print ("邮件发送成功!")
except Exception as e:
    print ("失败:"+str(e))

运行程序后,收到邮件的内容如下:

Python 邮件系统 项目 python 电子邮件_数据


另外我们还可以另通过MIMEText类再定义Content-Disposition属性来实现带附件的邮件。