1. 程式人生 > >Python3 自動發郵件

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)