虽然一般自动化持续集成中都用Jenkins来发送邮件,但了解掌握一下python的smtplib模块发送邮件也是必要的。
先明确一下发邮件的步骤:
1.确定邮件服务商:网易、qq等
2.登录邮箱:用户名/密码(密码一般是授权码)
3.编辑邮件主题、内容、附件
4.发送邮件
最简单的实现:
server = smtplib.SMTP('smtp.163.com',25) server.login(emailname,emailpwd) # 登录 # 邮件内容 msg = '''\\From: xia Subject: Hello World This is a test ''' # 发送邮件 server.sendmail(emailname,'[email protected]',msg)
如上代码创建一个实例化对象server,调用SMTP类下的login方法,采用163邮件服务,默认端口是25,emailname和emailpwd分别为发送邮件的用户名和授权码。
实际在发邮件的时候,我们通常使用加密模式。简单的两种加密方法:
1.tls模式加密
server = smtplib.SMTP('smtp.163.com',25) server.login(emailname,emailpwd) # 登录 context = ssl.create_default_context() server.starttls(context=context) # 邮件内容 msg = '''\\ From: xia Subject: Hello World This is a test ''' # 发送邮件 server.sendmail(emailname,'[email protected]',msg) server.quit()
2.ssl加密,默认加密端口是465
server = smtplib.SMTP_SSL('smtp.163.com',465) server.login(emailname,emailpwd) # 登录 # 邮件内容 msg = '''\\ From: xia Subject: Hello World This is a test ''' # 发送邮件 server.sendmail(emailname,'[email protected]',msg) server.quit()
创建server后,要记得quit关闭。也可以使用上下文管理器,防止忘记关闭邮件:
with smtplib.SMTP_SSL('smtp.163.com',465) as server: server.login(emailname,emailpwd) # 登录 # 加密1. tls模式 server.starttls(context=context) # 邮件内容 msg = '''\\ From: xia Subject: Hello World This is a test ''' # 发送邮件 server.sendmail(emailname,'[email protected]',msg)
但是实际应用中,不可能会发送这么简单的邮件。我们需要丰富邮件主题、内容和附件。
这就需要引入两个模块:
from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart
首先创建一个带附件的实例,设置邮件主题,from,to信息:
msg_total = MIMEMultipart() msg_total['subject'] = Header(self.subject,'utf-8') msg_total['From'] = emailname msg_total['To'] = self.tolist
添加邮件正文内容,这里添加html格式的内容:
content = '''<p style="color:red">你好,我是一份测试邮件。</p>''' msg_total.attach(MIMEText(content, 'html','utf-8'))
也可以读取某个文件内容作为邮件正文:
with open(file, 'rb') as f: content = f.read() msg_total.attach(MIMEText(content, 'html', 'utf-8'))
添加附件之前,首先要获取想要发送的附件:
with open(file, 'rb') as f: mail_attach = f.read() att = MIMEText(mail_attach, 'base64', 'utf-8') att["Content-Type"] = 'application/octet-stream' # 这里的filename可以任意写,写什么名字,邮件中显示什么名字 att["Content-Disposition"] = 'attachment; filename="测试报告"' msg_total.attach(att)
上面邮件正文和附件文件都是写死的,一般在应用中,我们可以获取当前最新的测试执行报告作为附件:
file = os.listdir(report_path) # 列出目录的下所有文件和文件夹 file.sort(key=lambda fn: os.path.getmtime(report_path + "\\" + fn)) # 按时间排序 file_name = file[-1] file_new = os.path.join(report_path, file[-1]) # 获取最新的文件保存到file_new # 添加文件内容作为正文模块 with open(file_new, 'rb') as f: content = f.read() msg_total.attach(MIMEText(content, 'html', 'utf-8')) # 附件模块 with open(file_new, 'rb') as f: mail_attach = f.read() att = MIMEText(mail_attach, 'base64', 'utf-8') att["Content-Type"] = 'application/octet-stream' # 这里的filename可以任意写,写什么名字,邮件中显示什么名字 att["Content-Disposition"] = 'attachment; filename="{}"'.format(file_name) msg_total.attach(att)
整合以上邮件主题、内容、附件,并封装成一个类,便于后续调用。完整代码如下:
import smtplib from python15.class_email.conf import * from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart from email.header import Header import os class MyEmail: def __init__(self,host,port,tolist,subject,content=None): self.host = host #邮件服务地址 self.port = port # 邮件服务端口 self.tolist = tolist # 接收人 self.subject = subject # 邮件主题 self.content = content # 邮件内容 def send_email(self): # 总的邮件内容,创建一个带附件的实例 msg_total = MIMEMultipart() msg_total['subject'] = Header(self.subject,'utf-8') msg_total['From'] = emailname msg_total['To'] = self.tolist file = os.listdir(report_path) # 列出目录的下所有文件和文件夹 file.sort(key=lambda fn: os.path.getmtime(report_path + "\\" + fn)) # 按时间排序 file_name = file[-1] file_new = os.path.join(report_path, file[-1]) # 获取最新的文件保存到file_new # 添加文件内容作为正文模块 with open(file_new, 'rb') as f: content = f.read() msg_total.attach(MIMEText(content, 'html', 'utf-8')) # 附件模块 with open(file_new, 'rb') as f: mail_attach = f.read() att = MIMEText(mail_attach, 'base64', 'utf-8') att["Content-Type"] = 'application/octet-stream' # 这里的filename可以任意写,写什么名字,邮件中显示什么名字 att["Content-Disposition"] = 'attachment; filename="{}"'.format(file_name) msg_total.attach(att) try: self.server = smtplib.SMTP_SSL(self.host, self.port) self.server.login(emailname, emailpwd) self.server.sendmail(emailname, self.tolist, msg_total.as_string()) print("邮件发送成功") except smtplib.SMTPException as e: print("Error: 无法发送邮件",e) finally: self.server.quit()