一、需求
老板要求每天跑一边自动化测试脚本,并把测试报告用邮箱发给他。于是去查了资料,顺利完成了这个需求,在此记录分享一下
二、压缩文件
首先做的事是调试压缩文件的函数。利用python自带的zipfile库,具体思路是通过os.walk()函数遍历某一文件夹的所有文件,再把这些文件写入到压缩包内。
step1:利用zipfile库的ZipFile函数创建一个压缩包(.zip类型)的对象
step2::利用os.walk()函数和for循环遍历每个文件。os.walk()返回一3元组,第一个指的是当前正在遍历的这个文件夹的本身的地址,第二个是当前地址下所含的文件夹,第三个是当前地址下所含的文件(不清楚的,自己写个demo感受一下就理解了)
step3:使用write()函数写入这些文件就可以了
def zip_dir(dir_path, outFullName):
"""
压缩指定文件夹
:param dir_path: 目标文件夹路径
:param outFullName: 压缩文件保存路径+XXXX.zip
:return:
"""
testcase_zip = zipfile.ZipFile(outFullName, 'w', zipfile.ZIP_DEFLATED)
for path, dir_names, file_names in os.walk(dir_path):
for filename in file_names:
testcase_zip.write(os.path.join(path, filename))
testcase_zip.close()
print("打包成功")
三、配置邮件正文
完成压缩文件后,尝试发送邮件。查找资料发现都是使用smtplib完成的。思路是通过通过登录某个邮箱,然后填入正文,发件人和收件人地址,完成发送。
step1:使用smtplib库的SMTP类初始化一个对象,含两个参数,一个是服务器类型(QQ邮箱、163邮箱等等),一个是端口号。我的使用的163邮箱
smtp_server = "smtp.163.com"
server = smtplib.SMTP(smtp_server,25)
step2:利用login函数登录邮箱,含2个参数,一个是登录账号,一个是密码。其实这里的密码不是登录密码,而是授权码,需要去邮箱内开启SMTP服务,我用163在设置内开启后给了一个授权码,这里配置为该码
username = "XXX@163.com"
password = "XXX"
server.login(username,password)
step3:利用MIMEMultipart()创建一个对象用来配置邮件各个信息。利用attacg函数添加邮件正文,然后配置发件人From属性,收件人To属性,标题Subject属性
time = datetime.datetime.today().strftime("%m-%d %H:%M")
msg = MIMEMultipart()
# 邮件正文
msg.attach(MIMEText("{}的测试报告见附件".format(time),'plain','utf-8'))
msg['From'] = "XXX@163.com"
msg['To'] = "XXX@163.com"
subject = "{}的测试报告".format(time)
msg['Subject'] = subject
四、配置附件(.zip压缩包)
其实这段代码中间过程不是很清楚,看到别人这些写拿过来直接用发现可以就这样用了,原理应该是先先读文件内容然后在编码。其中第一步打开的文件就是之前所压缩好的文件,配置好附件后,通过attach方法添加进邮件内
data = open(filepath, 'rb')
ctype, encoding = mimetypes.guess_type(filepath)
if ctype is None or encoding is not None:
ctype = 'application/octet-stream'
maintype, subtype = ctype.split('/', 1)
file_msg = MIMEBase(maintype, subtype)
file_msg.set_payload(data.read())
data.close()
encoders.encode_base64(file_msg) # 把附件编码
# 修改附件名称
file_msg.add_header('Content-Disposition', 'attachment', filename="测试报告.zip")
msg.attach(file_msg)
五、发送邮件
配置好发件人邮箱,收件人邮箱后,利用sendmail函数完成发送
sender = 'XXX@163.com'
receivers = 'XXX@moego.com'
server.sendmail(sender,receivers,msg.as_string())
server.quit()
六、踩的坑
调试发送邮件时,失败时可能有很多提示,一般就是2种。
- 授权码不正确,导致登录失败,检查授权码的正确性
- 第二种,邮件内容被当做垃圾邮件处理,查了很多资料说不能有test、测试等字眼,亲测后发现其实可以有,原因大概率是配置内容出现了问题,首先from和to一定要配置,其实要直接赋值,我刚开始是按照菜鸟教程去写的,菜鸟里from和to均用了一个Head的类来赋值,我各种调试都是一直提示相同的错误,后来看来别人帖子都是直接赋值,我修改了from和to的值后,发送成功
七、源码
# coding=gbk
import mimetypes
import smtplib
from email import encoders
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email.mime.text import MIMEText
import datetime
filepath = "./test_report.zip"
smtp_server = "smtp.163.com"
username = "XXX@163.com"
password = "XXX"
sender = 'XXX@163.com'
receivers = 'XXX@moego.com'
time = datetime.datetime.today().strftime("%m-%d %H:%M")
msg = MIMEMultipart()
# 邮件正文
msg.attach(MIMEText("{}的测试报告见附件".format(time),'plain','utf-8'))
msg['From'] = "XXX@163.com"
msg['To'] = "XXX@163.com"
subject = "{}的测试报告".format(time)
msg['Subject'] = subject
data = open(filepath, 'rb')
ctype, encoding = mimetypes.guess_type(filepath)
if ctype is None or encoding is not None:
ctype = 'application/octet-stream'
maintype, subtype = ctype.split('/', 1)
file_msg = MIMEBase(maintype, subtype)
file_msg.set_payload(data.read())
data.close()
encoders.encode_base64(file_msg) # 把附件编码
file_msg.add_header('Content-Disposition', 'attachment', filename="测试报告.zip") # 修改邮件头
msg.attach(file_msg)
try:
server = smtplib.SMTP(smtp_server,25)
server.login(username,password)
server.sendmail(sender,receivers,msg.as_string())
server.quit()
print("发送成功")
except Exception as err:
print("发送失败")
print(err)
八、封装后源码
嵌入项目后重新封装
# coding=gbk
import logging
import mimetypes
import smtplib
from email import encoders
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email.mime.text import MIMEText
import datetime
from airtest.utils.logger import get_logger
import yaml
time = datetime.datetime.today().strftime('%Y{y}%m{m}%d{d} %H{h}%M{f}%S{s}').format(y='年', m='月', d='日', h='时', f='分',
s='秒')
class Email(object):
global time
logger = get_logger('Email')
logger.setLevel(logging.INFO)
def __init__(self):
self.config = yaml.safe_load(open('../config/email.yaml', 'r'))
self.smtp_server = self.config['Email']['smtp_server']
self.username = self.config['Email']['username']
self.password = self.config['Email']['password']
self.file_path = self.config['Email']['file_path']
self.sender = self.config['Email']['sender']
self.receivers = self.config['Email']['receivers']
self.addr_from = self.config['Email']['from']
self.addr_to = self.config['Email']['to']
# 设置邮件正文
def set_content(self, attach_zip):
msg = MIMEMultipart()
msg.attach(MIMEText("{}的测试报告见附件".format(time), 'plain', 'utf-8')) # 邮件正文
msg['From'] = self.addr_from # 发送邮件的地址
msg['To'] = self.addr_to # 接收邮件的地址
subject = "{}的测试报告".format(time) # 邮件标题
msg['Subject'] = subject
msg.attach(attach_zip)
return msg
# 设置附件
def set_attach(self):
data = open(self.file_path, 'rb')
ctype, encoding = mimetypes.guess_type(self.file_path)
if ctype is None or encoding is not None:
ctype = 'application/octet-stream'
maintype, subtype = ctype.split('/', 1)
attach_zip = MIMEBase(maintype, subtype)
attach_zip.set_payload(data.read())
data.close()
encoders.encode_base64(attach_zip) # 把附件编码
# 修改附件名称
filename = "{}-测试报告.zip".format(time)
attach_zip.add_header('Content-Disposition', 'attachment', filename=filename)
return attach_zip
# 发送邮件
def send_email(self):
try:
server = smtplib.SMTP(self.smtp_server, 25)
server.login(self.username, self.password)
attact_zip = self.set_attach()
msg = self.set_content(attact_zip)
server.sendmail(self.sender, self.receivers, msg.as_string())
server.quit()
self.logger.info('---------->发送邮件成功')
except Exception as err:
self.logger.info('---------->发送邮件失败')
self.logger.info(err)