python3 自动发邮件

背景:当UI Recorder录制的GUI自动化脚本回放失败时,自动发邮件通知,并打包测试报告作为附件发送。

#!/usr/bin/python
# -*- coding: utf-8 -*-
'''
Created on 2018年12月28日
@author: Rethink
'''
import re
import os
from datetime import datetime
import zipfile
import smtplib
from email.header import Header
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders


def get_email_obj(email_subject, email_sender, email_receivers):
    '''
    构造邮件对象
    :param email_subject:邮件主题
    :param email_sender:发件人
    :param email_receivers:收件人列表
    :return 邮件对象
    '''
    email_obj = MIMEMultipart()
    email_obj["subject"] = Header(email_subject, "utf-8")
    email_obj["From"] = Header(email_sender, "utf-8")
    email_obj["To"] = Header(','.join(email_receivers), "utf-8")
    return email_obj


def attach_content(email_obj, email_content, content_type="plain", content_charset="utf-8"):
    '''
    创建邮件正文,并将其附加到根容器:正文格式支持plain/html
    :param email_obj:邮件对象
    :param email_content:邮件正文
    :param content_type:邮件正文格式
    :param content_charset:邮件正文编码
    '''
    content = MIMEText(email_content, content_type, content_charset)
    email_obj.attach(content)


def attach_part(email_obj, source_path, part_name):
    '''
    添加附件:附件可以为照片,也可以是文档
    :param email_obj:邮件对象
    :param source_path:资源路径
    :param part_name:附件名称
    '''
    part = MIMEBase('application', 'octet-stream')    # 创建附件对象
    part.set_payload(open(source_path, 'rb').read()
                     )                        # 将附件源文件加载到附件对象
    encoders.encode_base64(part)
    part.add_header('Content-Disposition', 'attachment',
                    filename=('gbk', '', '%s' % part_name))     # 给附件添加头文件
    email_obj.attach(part)


def send_email(email_obj, email_host, host_port, sender, sender_pwd, receivers):
    '''
    发送邮件
    :param email_obj:邮件对象
    :param email_host:SMTP服务器主机
    :param host_port:SMTP服务端口号
    :param sender:发件地址
    :param sender_pwd:发件地址授权码,而非密码
    :param receivers:收件地址列表,list
    :return 发送成功,返回 True;发送失败,返回 False
    '''
    try:
        smtp_obj = smtplib.SMTP_SSL(email_host, host_port)
        smtp_obj.set_debuglevel(1)   # 打印与邮件服务器的交互信息
        smtp_obj.login(sender, sender_pwd)
        smtp_obj.sendmail(sender, receivers, email_obj.as_string())
        smtp_obj.quit()
        print("邮件发送成功 ,发件人为:%s,收件人为: %s" % (sender, receivers))
        return True
    except smtplib.SMTPException as e:
        print("Error,无法发送邮件: %s" % e)
        return False


def createZip(file_path, save_path, note=""):
    '''
    打包测试报告目录
    :param file_path: 目标目录路径
    :param save_path: 保存路径
    :param note: 备份文件说明,会在压缩文件名中展示
    :return 压缩文件完整保存路径
    '''
    now = datetime.now().strftime("%Y%m%d%H%M%S")
    fileList = []
    if len(note) == 0:
        target = save_path + os.sep + now + ".zip"
    else:
        target = save_path + os.sep + now + "_" + str(note) + ".zip"
    newZip = zipfile.ZipFile(target, 'w')
    for dirpath, dirnames, filenames in os.walk(file_path):
        for filename in filenames:
            fileList.append(os.path.join(dirpath, filename))
    for tar in fileList:
        # tar为写入的文件,tar[len(filePath)]为保存的文件名
        newZip.write(tar, tar[len(file_path):])
    newZip.close()
    return target

if __name__ == "__main__":
    # QQ邮箱SMTP服务器
    mail_host = "smtp.exmail.qq.com"    # 发件服务器(企业邮箱)
    host_port = 465
    mail_user = "YOUR EMAIL"
    mail_pwd = "YOUR PASSWORD"  # 密码

    # mail_host = "smtp.qq.com"    # 发件服务器(个人邮箱,注意和企业邮箱是不同的服务器)
    # host_port = 465
    # mail_user = "YOUR EMAIL"
    # mail_pwd = "YOUR CODE"   # 授权码

    script_path = "E:/uirecorder"
    os.chdir(script_path)
    os.system("run.bat ./sample/park.spec.js")

    with open("./reports/index.json", mode="r", encoding="utf-8") as f:
        a = f. readlines()
        suites, tests, passes, pending, failures, start, end, duration, passPercent = a[
            3].strip(), a[4].strip(), a[5].strip(), a[6].strip(), a[7].strip(), a[8].strip(), a[9].strip(), a[10].strip(), a[12].strip()
        result = "\n".join(
            (suites, tests, passes, pending, failures, start, end, duration, passPercent))
        failNum = re.search("(\d+)", failures).group()

    if int(failNum) == 0:
        print("GUI Test Success! 用例运行成功,无须发邮件通知")
    if int(failNum) != 0:
        email_content = "Hi,all\n" + "GUI Test Fail! 运行结果摘要如下:\n" + \
            "\t" + result + "\n完整测试报告以及报错截图见附件"

        email_subject = "UI Recorder Script Running Failed"
        test_result_path = createZip("./reports",
                                     "./reports_zip", note="rethink")
        source_path1 = "./reports/index.json"
        source_path2 = test_result_path
        part_name1 = "index.json"
        part_name2 = "test_result.zip"
        receivers = ["ADDR1", "ADDR2"]  # 收件人列表

        email_obj = get_email_obj(email_subject, mail_user, receivers)
        attach_content(email_obj, email_content)
        attach_part(email_obj, source_path1, part_name1)
        attach_part(email_obj, source_path2, part_name2)
        send_email(email_obj, mail_host, host_port,
                   mail_user, mail_pwd, receivers)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,858评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,372评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,282评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,842评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,857评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,679评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,406评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,311评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,767评论 1 315
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,945评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,090评论 1 350
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,785评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,420评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,988评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,101评论 1 271
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,298评论 3 372
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,033评论 2 355

推荐阅读更多精彩内容