zoukankan      html  css  js  c++  java
  • python之smtplib模块发送邮件

    虽然一般自动化持续集成中都用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,'18551052425@163.com',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,'18551052425@163.com',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,'18551052425@163.com',msg)
    server.quit()
    

    创建server后,要记得quit关闭。也可以使用上下文管理器,防止忘记关闭邮件:

    with smtplib.SMTP_SSL('smtp.163.com',465) as server:
        server.login(emailname,emailpwd)    # 登录
        # 邮件内容
        msg = '''\
                 From: xia
                 Subject: Hello World           
                 This is a test '''
        # 发送邮件
        server.sendmail(emailname,'18551052425@163.com',msg)
    

     但是实际应用中,不可能会发送这么简单的邮件。我们需要丰富邮件主题、内容和附件。

    这就需要引入3个模块:

    from email.mime.multipart import MIMEMultipart
    from email.mime.text import MIMEText
    from email.mime.application import MIMEApplication

     首先创建一个带附件的实例MIMEMultipart(),设置邮件主题,from,to信息:

    msg_total = MIMEMultipart()
    msg_total['subject'] = Header(self.subject,'utf-8')
    msg_total['From'] = emailname
    msg_total['To'] = 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')) 

     添加附件的话,MIMEText模块和MIMEAplication模块都可以添加,只不过看源码发现,MIMEApplication比MIMEText要简单一些,需要配置的参数少一些。

    MIMEText模块添加附件:

    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)

    MIMEApplication模块添加附件:

    with open(file_new, 'rb') as f:
         mail_attach = f.read()
         att2 = MIMEApplication(mail_attach)
         # 添加附件的头信息
         att2.add_header('content-disposition', 'attachment', filename='{}'.format(file_name))
         msg_total.attach(att2)
    

     对比代码也可以发现,MIMEapplication模块添加附件更方便一些。

    上面邮件正文和附件文件都是写死的,一般在应用中,我们可以获取当前最新的测试执行报告作为附件:

    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.multipart import MIMEMultipart
    from email.mime.text import MIMEText
    from email.mime.application import MIMEApplication
    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
    
            # 添加普通正文模块
            # msg_total.attach(MIMEText(self.content, 'html','utf-8'))
    
            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'))
    
            # 附件模块1 MIMEText添加附件
            with open(file_new, 'rb') as f:
                mail_attach = f.read()
                att1 = MIMEText(mail_attach, 'base64', 'utf-8')
                att1["Content-Type"] = 'application/octet-stream'
                # 这里的filename可以任意写,写什么名字,邮件中显示什么名字
                att1["Content-Disposition"] = 'attachment; filename="{}"'.format(file_name)
                msg_total.attach(att1)
    
            # 附件模块2 MIMEApplication模块添加附件
            with open(file_new, 'rb') as f:
                mail_attach = f.read()
                att2 = MIMEApplication(mail_attach)
                # 添加附件的头信息
                att2.add_header('content-disposition', 'attachment', filename='{}'.format(file_name))
                msg_total.attach(att2)
    
            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("邮件发送失败",e)
            finally:
                self.server.quit()
    

      

  • 相关阅读:
    用TortoiseSVN忽略文件或文件夹(ignore)(网络摘抄记录)
    GridView解决同一行item的高度不一样,如何同一行统一高度问题?
    解决android studio引用远程仓库下载慢(转)
    Databinding在自定义ViewGroup中如何绑定view
    (转 )【Android那些高逼格的写法】InvocationHandler与代理模式
    (转)秒懂,Java 注解 (Annotation)你可以这样学
    View拖拽 自定义绑定view拖拽的工具类
    bcrypt对密码加密的一些认识(学习笔记)
    Node.js+Koa开发微信公众号个人笔记(三)响应文本
    Node.js+Koa开发微信公众号个人笔记(二)响应事件
  • 原文地址:https://www.cnblogs.com/Dahlia/p/10639916.html
Copyright © 2011-2022 走看看