python发送邮件并附带.zip附件

一、需求

老板要求每天跑一边自动化测试脚本,并把测试报告用邮箱发给他。于是去查了资料,顺利完成了这个需求,在此记录分享一下

二、压缩文件

首先做的事是调试压缩文件的函数。利用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种。

  1. 授权码不正确,导致登录失败,检查授权码的正确性
  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)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值