Python之SMTP发送邮件

  • 作者:lwj
  • 分类:Python
  • 发表日期:2021-03-20 21:41:56
  • 阅读(278)
  • 评论(0)

SMTP是发送邮件的协议,Python内置对SMTP的支持,可以发送纯文本邮件、HTML邮件以及带附件的邮件。

Python对SMTP支持有smtplibemail两个模块,email负责构造邮件,smtplib负责发送邮件。

SMTP方法封装

#!/usr/bin/python3
# coding: utf-8
# Author: sitVen


import os
import smtplib
from email import encoders
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.utils import parseaddr, formataddr


# 邮件通知
class Send_Email():
    def __init__(self, smtp_server, port, from_email, to_email: list, password):
        """
        :param smtp_server: smtp服务器地址  示例:163: smtp.163.com
        :param port: smtp服务器端口  示例:163邮箱的非SSL端口:25   163邮箱的SSL端口:465
        :param from_email: 发件邮箱
        :param to_email: 收件邮箱
        :param password: 发件邮箱的密码或者授权码
        """
        self.from_email = from_email                                # 发件邮箱
        self.to_email = to_email                                    # 收件邮箱
        self.msg = MIMEMultipart()                                  # 创建邮件对象
        self.server = smtplib.SMTP(smtp_server, port)               # 连接smtp服务器
        self.server.starttls()                                      # 加密SMTP, 即创建SSL安全连接
        self.server.login(self.from_email, password)                # 登陆需要认证的SMTP服务器

    # 打印和SMTP服务器交互的所有信息
    def set_debuglevel(self, debuglevel=True):
        self.server.set_debuglevel(debuglevel)
        if debuglevel != False: print(" 开启 - 打印SMTP服务器交互的所有信息")
        else: print(" 关闭 - 打印和SMTP服务器交互的所有信息")

    # 对发件realName进行encode后在重新拼接
    def __encode_realName(self, email: str) -> str:
        """
        :param s: 收件邮箱信息 =>
        :return: str
        """
        # 解析邮件地址返回一个tuple,拆分成realName和电子邮件地址
        name, email = parseaddr(email)
        # 对realName进行encode后构建新的邮件地址,传入一个tuple,返回str
        return formataddr((Header(name, 'utf-8').encode(), email))   # 与parseaddr相反

    # 添加邮件和收发邮件信息到邮件对象
    def email_content(self, content, subtype="plain", From="发件人", To="收件人", title="自动化测试通知"):
        """
        :param content: 邮件正文信息   html / text
        :param to_email: 收件箱 -> list
        :param subtype: 邮件正文类型   content=html->html / content=text->plain
        :param From: 发件人昵称
        :param To:  收件人昵称
        :param title: 邮件标题
        :return:
        """
        self.msg['From'] = self.__encode_realName(f'{From} <{self.from_email}>')      # 发件人名称
        self.msg['To'] = self.__encode_realName(f'{To} <{self.to_email}>')            # 收件人名称
        self.msg['Subject'] = Header(f'{title}', 'utf-8').encode()                    # 邮件标题
        self.msg.attach(MIMEText(content, subtype, 'utf-8'))                          # 邮件正文
        print(f" 成功添加{subtype}类型邮件内容")

    # 上传附件
    def upload_accessory(self, filePath, fileName, maintype="text"):
        """
        :param filePath: 附件路径
        :param fileName: 附件名称
        :param maintype: 附件类型   image / text
        :return:
        """
        with open(os.path.join(filePath, fileName), 'rb') as f:
            # 设置附件的MIME和文件名,这里是png类型:
            mime = MIMEBase(maintype, fileName.split(".")[1], filename=fileName)
            # 加上必要的头信息
            mime.add_header('Content-Disposition', 'attachment', filename=fileName)
            mime.add_header('Content-ID', '<0>')
            mime.add_header('X-Attachment-Id', '0')
            # 把附件的内容读进来
            mime.set_payload(f.read())
            # 用Base64编码
            encoders.encode_base64(mime)
            # 添加到MIMEMultipart
            self.msg.attach(mime)
        print(f" 成功将{fileName}上传到邮件附件")

    # 发送邮件并断开smtp连接
    def send_email(self):
        self.server.sendmail(self.from_email, self.to_email, self.msg.as_string())   # 发送邮件
        print(f" 邮箱{self.from_email}成功发送邮件到{self.to_email}")

    def __del__(self):
        self.server.quit()             # 断开smtp服务器链接
        print(" 断开smtp服务器连接")


if __name__ == "__main__":
    html = ""
    # SMTP服务器地址
    smtp_server = "smtp.163.com"
    # Email地址
    from_email = "xxxxxxxxxxx@163.com"
    # Email授权码或者登录密码
    password = "***********"
    # 收件人地址
    to_email = ["yyyyyy@qq.com", "zzzzzzzz@126.com"]
    smtp = Send_Email(smtp_server, 25, from_email, to_email, password)
    smtp.set_debuglevel()
    smtp.email_content(content=html, subtype="html")
    upload_path = "D:\\file\\upload"
    smtp.upload_accessory(filePath=upload_path, fileName="test.png", maintype="image")
    smtp.upload_accessory(filePath=upload_path, fileName="test.txt", maintype="text")
    smtp.send_email()
    del smtp

HTML内容

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>{JOB_NAME}-第{BUILD_NUMBER}次构建日志</title>
</head>
<body leftmargin="8" marginwidth="20" topmargin="8" marginheight="20" offset="0">
    <table width="95%" cellpadding="0" cellspacing="0"  
           style="font-size: 11pt; font-family: Tahoma, Arial, Helvetica, sans-serif">
        <tr>本邮件由系统自动发出,无需回复!
            <br/>各位同事,大家好,以下为{PROJECT_NAME }项目自动化测试通知</br>
        </tr>
        <tr>
            <td><br />
            <b><font color="#0B610B">构建信息</font></b>
            <hr size="2" width="100%" align="center" /></td>
        </tr>
        <tr>
            <td>
                <ul>
                    <h4>项目信息</h4>
                        <li>项目名称: {PROJECT_NAME}</li>
                        <li>构建编号: {BUILD_NUMBER}</li>
                        <li>构建耗时: {time}秒</li>
                        <li>构建URL: <a href="{buildUrl}">{buildUrl}</a></li>
                    <h4>测试结果</h4>
                        <li> 通过: {passed}</li>
                        <li> 失败: {failed}</li>
                        <li> 错误: {error}</li>
                        <li> 跳过: {skipped}</li>
                        <li> 标记失败-失败: {xfailed}</li>
                        <li> 标记失败-成功: {xpassed}</li>
                    <h4>构建记录</h4>
                        <li>构建日志: <a href="{buildUrl}">前往查看</a></li>
                        <li>测试报告: <a href="{reportUrl}">立即查看</a></li>
                </ul>
            </td>
        </tr>
    </table>
</body>
</html>

发送结果

觉得不错,支持一下!

提交评论

您尚未登录,登录之后方可评论~ 登录 or 注册

评论列表

暂无评论
返回顶部

建议反馈

1. 可在博文底部留言评论

2. 发邮件到i_suichuan@163.com