【Flask】测试平台开发,实现全局邮件发送工具 第十二篇

发布于:2025-09-02 ⋅ 阅读:(16) ⋅ 点赞:(0)

概述:

我们都知道,开发一个测试平台,那么对应也有有一个全局发送邮件的功能,对此我们需要实现一个发送全局邮件通知的功能

  • 平台工具开发
    • 后端
      • 学习使用smtplib邮件模块
      • 学习使用yamail邮件服务
      • 编码逻辑发送邮件服务工具类
    • 问题
      • smtplib使用中一些问题集锦

内置邮件模块 smtplib

从某度搜索关于python如何发送邮件,给到结果最多的就是 smtplib,资料参差不齐,抑或内容太陈旧,这里通过实践整理总结如下:

首先 了解基本使用

官方 [注解1] 的语法以及教程参考 [注解2]

# 导入包,python环境默认自有,无需而外安装
import smtplib
from smtplib import SMTP

# 通过给定参数链接服务对象
smtplib.SMTP(host='', port=0, local_hostname=None, [timeout, ]source_address=None)
# 或需要SSL连接
smtplib.SMTP_SSL(host='', port=0, local_hostname=None, keyfile=None, certfile=None, [timeout, ]context=None, source_address=None)

# 支持with方式,否则一般上边的操作需要手动关闭
with smtplib.SMTP("domain.org") as smtp:
     # 配置发送地址和内容等

建立服务对象重要参数说明:

  • host: SMTP 服务器主机。你可以指定主机的ip地址或者域名;

  • port: 需要指定 SMTP 服务使用的端口号,一般情况下 SMTP 端口号为25;

Python SMTP 对象使用 sendmail 方法发送邮件,语法如下:

SMTP.sendmail(from_addr, to_addrs, msg, mail_options=(), rcpt_options=())

其中重要参数说明:

  • from_addr: 邮件发送者地址。

  • to_addrs: 字符串列表,邮件发送地址。

  • msg: 发送消息

其次 准备一个可用的邮件发送服务

可以本地,公司邮箱服务,或者是第三方服务,我这里准备的一个测试邮件服务是“企业微信邮箱”

最后 一个完整的例子

直接通过给定HTML样式,实现模版发送,内容文字+链接,这里需要特别注意的是测试“微信企业邮箱”链接需要SSL,所以需要使用 SMTP_SSL 创建链接,而非往上很多例子使用SMTP进行创建,执行测试内容如下:

查看我自己的邮箱是否真的收到了邮件,可以看到功能正常,上边代码中有一处需要主要是发件人和服务登录人应为为同一个否则会报SMTP 501错误。

但这里代码发送后有个问题,在邮箱列表里的发件人信息和详细内容里的邮件人信息展示异常:列表显示空白,邮件详细没能正确显示邮箱等。

经过资料查询,需要依赖包的一个工具类进行格式化,分别是email.utils 中的 parseaddr, formataddr,经过优化后代码如图红色标注:

增加优化逻辑后再发送一个测试邮件,看看结果,列表和详细都正常显示了。

简单易用邮件模块 yagmail

yagmail 使用

yagmail 是个外部包,使用前需要安装

# 可能需要外网访问
pip3 install yagmail
# 或从github安装
pip3 install -e git+https://github.com/kootenpv/yagmail#egg=yagmail

从实践的例子来看,发送邮件变得如此简单,不需要多说,直接上代码:

def demo_yagmail():
    # 设置收件人(不需要再设置发件人)
    receivers = ['rebort@qq.com', 'rebort@.com']
    # 邮件主题
    subject = 'Yagmail测试主题'
    # 内容,可以单独定义,然后组成一个内容体
    body = 'Body描述'
    html = '<a href="http:www.baidu.com?spm=1001.2014.3001.5482">点我!</a>'

    # 附件文件绝对路径, 或者 通过open打开直接给io流文件
    path_file = os.path.dirname(os.path.abspath(__file__))+'/source/result.txt'
    attachments =[path_file]

    # 初始化服务对象直接根据参数给定,更多参考SMTP()内部
    server = yagmail.SMTP(host='smtp.exmail.qq.com', port=465, user='daqi@mrzcode.com', password='Test@2021')
    # 发送内容,设置接受人等信息,更多参考SMTP.send()内部
    server.send(to=receivers,
                subject=subject,
                contents=[body, html],
                attachments=attachments)

    server.close()
    print("邮件发送的如此简单!")

if __name__ == "__main__":
    demo_yagmail()

看看发送结果,正常收到,各项均没有异常,完美~ 更多参数说明参考官方 [注释3] 或者在idea 开发工具点跳到源码。

不是Pyhon 发送邮件变得如此轻松愉快了~,上述的调研实践代码均提交到git项目代码库了,可以前去查看位置:/demoCode/emailDemo.py

邮件工具类编写

调研和实践完了上述“Python 如何实现邮件发送服务” 内容,最终目的是编写个工具类和一些方法来供后续的提测流程使用

  • configs/config.py 添加邮件服务的常量

# config.py
MAIL_HOST = "发送服务的地址"
MAIL_PORT = 25
MAIL_USER = "发送服务邮箱账号"
MAIL_PASSWORD = "发送服务邮箱密码"
  • 创建/utils/emialUtils.py 实现的参数化方法,这里对于模版因为是否也定义在其中,后边实际开发后再优化

#!/usr/bin/python
# -*- coding: UTF-8 -*-

import yagmail
import traceback
from configs import config
import re
from typing import Union, List


def _validate_email(email: str) -> bool:
    """验证单个邮箱地址格式"""
    pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
    return re.match(pattern, email) is not None


def _ensure_valid_emails(receivers: Union[str, List[str]]) -> List[str]:
    """统一处理 receivers 参数并验证格式"""
    if isinstance(receivers, str):
        receivers = [receivers]

    invalid_emails = [email for email in receivers if not _validate_email(email)]
    if invalid_emails:
        raise ValueError(f"Invalid email addresses: {invalid_emails}")
    return receivers


def sendEmail(receivers: Union[str, List[str]], subject: str, contents: Union[str, List[str]],
              attachments: List[str] = None) -> bool:
    try:
        # 1. 验证邮箱格式
        valid_receivers = _ensure_valid_emails(receivers)

        # 2. 初始化 SMTP 服务
        server = yagmail.SMTP(
            host=config.MAIL_HOST,
            port=config.MAIL_PORT,
            user=config.MAIL_USER,
            password=config.MAIL_PASSWORD
        )

        # 3. 发送邮件
        server.send(
            to=valid_receivers,
            subject=subject,
            contents=contents,
            attachments=attachments or []  # 处理 None 情况
        )
        return True

    except ValueError as e:
        print(f"邮箱格式错误: {e}")
        return False
    except yagmail.error.YagInvalidEmailAddress as e:
        print(f"yagmail 邮箱验证失败: {e}")
        return False
    except Exception as e:
        print(f"邮件发送异常: {traceback.format_exc()}")
        return False
    finally:
        if 'server' in locals():
            server.close()

# def sendEmail(receivers, subject, contents, attachments=[]):
#
#
#     try:
#
#         # 初始化服务对象直接根据参数给定,更多参考SMTP()内部
#         server = yagmail.SMTP(host=config.MAIL_HOST, port=config.MAIL_PORT,
#                               user=config.MAIL_USER, password=config.MAIL_PASSWORD)
#         # 发送内容,设置接受人等信息,更多参考SMTP.send()内部
#         server.send(to=receivers,
#                     subject=subject,
#                     contents=contents,
#                     attachments=attachments)
#
#         server.close()
#     except Exception:
#         print('traceback.format_exc(): {}'.format(traceback.format_exc()))
#         return False
#
#     # 无任何异常表示发送成功
#     return True

if __name__ == "__main__":
    # 测试发送服务
    receivers = ['rebort.chen@howentech.com']
    subject = '工具类测试'
    body = '简单的问题内容体'
    sendEmail(receivers, subject, [body])
  • 调用测试,工具类直接编写变量调用方法进行测试,查看邮件发送是否OK

【注解&参考】

  • [注解1]:https://docs.python.org/zh-cn/3.8/library/smtplib.html#

  • [注解2]:https://www.runoob.com/python/python-email.html

  • [注解3]:https://github.com/kootenpv/yagmail


网站公告

今日签到

点亮在社区的每一天
去签到