Python自动化邮件发送类深度解析
一、类结构设计与初始化方法
1.1 类定义与参数说明
class Email : def __init__ ( self, sender: str , receiver: [ str , list ] , title: str , server: str , auth_code: str , message: str = None , attachment_file: [ str , list ] = None ) :
参数验证逻辑表
参数 类型 必需性 示例值 sender str 是 “user@qq.com” receiver str/list 是 [“user1@qq.com”, …] auth_code str 是 “xwjfghxcz…” server str 是 “smtp.qq.com”
二、核心方法实现解析
2.1 邮件发送主流程
def send ( self) : self. msg[ 'Subject' ] = self. title self. msg[ 'From' ] = self. sender self. msg[ 'To' ] = ', ' . join( self. receiver) if isinstance ( self. receiver, list ) else self. receiverif self. message: self. msg. attach( MIMEText( self. message, 'html' if '<html>' in self. message else 'plain' ) ) if self. attachment_file: . . . smtp_server = SMTP( self. server) smtp_server. login( self. sender, self. auth_code) smtp_server. sendmail( . . . ) smtp_server. quit( )
2.2 附件处理机制
def _attach_file ( self, file_path) : if not exists( file_path) : raise FileNotFoundError( . . . ) with open ( file_path, 'r' , encoding= 'utf-8' ) as f: att = MIMEText( f. read( ) , 'plain' , 'utf-8' ) att[ 'Content-Type' ] = 'application/octet-stream' file_name = re. split( r'[\\|/]' , file_path) [ - 1 ] att[ 'Content-Disposition' ] = f'attachment; filename=" { file_name} "' self. msg. attach( att)
支持的文件类型
文件类型 处理方式 限制条件 .txt/.log 直接读取 需UTF-8编码 .csv/.json 同文本文件 内容需为文本格式 二进制文件 当前不支持 会引发解码错误
三、完整使用示例
3.1 测试报告发送场景
report_email = Email( sender= 'tester@qq.com' , receiver= [ 'manager@qq.com' , 'dev_team@qq.com' ] , title= '[自动化测试报告] 2024-01-01' , server= 'smtp.qq.com' , auth_code= 'xwjfghxcz...' , message= '''<html><body><h2>测试执行概要</h2><p>成功率:<span style="color:green">95%</span></p><p>详细报告请查看附件</p></body></html>''' , attachment_file= [ r'E:\reports\test_result_20240101.html' , r'E:\logs\execution.log' ]
)
try : report_email. send( ) print ( "✅ 测试报告邮件发送成功" )
except Exception as e: print ( f"❌ 邮件发送失败: { str ( e) } " )
3.2 实际输出效果
✅ 测试报告邮件发送成功
收件箱显示效果
发件人: tester@qq.com
主题: [自动化测试报告] 2024-01-01
正文: 测试执行概要成功率:95%详细报告请查看附件
附件: test_result_20240101.html (1.2MB)execution.log (350KB)
四、代码优化建议
4.1 现存问题清单
问题描述 风险等级 改进方案 附件仅支持文本文件 高 添加二进制文件处理逻辑 未实现SSL加密传输 高 使用SMTP_SSL类替代SMTP 缺乏重试机制 中 添加失败重试逻辑(最多3次) 收件人列表处理不完善 低 统一转换为列表格式处理
4.2 增强型附件处理
from email. mime. application import MIMEApplicationdef _attach_file ( self, file_path) : with open ( file_path, 'rb' ) as f: att = MIMEApplication( f. read( ) ) att. add_header( 'Content-Disposition' , 'attachment' , filename= ( 'utf-8' , '' , file_name) )
4.3 企业级最佳实践
某大厂邮件服务规范要求 :
敏感信息(授权码)必须通过环境变量传递 所有邮件必须包含退订链接(法律合规) 附件大小超过10MB需使用云存储链接替代 必须记录邮件发送日志(含时间戳和收件人哈希值) 实施速率限制(每分钟最多发送10封)
import os
from hashlib import md5auth_code = os. getenv( 'SMTP_AUTH_CODE' )
def send ( self) : . . . log_msg = f"[ { datetime. now( ) } ] Sent to { md5( receiver. encode( ) ) . hexdigest( ) } " logging. info( log_msg)
五、完整代码
from email. mime. multipart import MIMEMultipart
from email. mime. text import MIMEText
from os. path import exists
import re
from smtplib import SMTPclass Email : def __init__ ( self, sender: str , receiver: [ str , list ] , title: str , server: str , auth_code: str , message: str = None , attachment_file: [ str , list ] = None ) : self. sender = senderself. receiver = receiverself. title = titleself. message = messageself. attachment_file = attachment_fileself. server = serverself. auth_code = auth_codeself. msg = MIMEMultipart( 'related' ) def send ( self) : self. msg[ 'Subject' ] = self. titleself. msg[ 'From' ] = self. senderself. msg[ 'To' ] = self. receiverif self. message: self. msg. attach( MIMEText( self. message) ) if self. attachment_file: if isinstance ( self. attachment_file, str ) : self. _attach_file( self. attachment_file) if isinstance ( self. attachment_file, list ) : for _path in self. attachment_file: self. _attach_file( _path) smtp_server = SMTP( self. server) smtp_server. login( self. sender, self. auth_code) smtp_server. sendmail( self. sender, self. receiver, self. msg. as_string( ) ) smtp_server. quit( ) def _attach_file ( self, file_path) : if not exists( file_path) : raise FileNotFoundError( f' { file_path} :附件文件不存在或者附件文件路径' ) with open ( file_path, 'r' , encoding= 'utf-8' ) as f: att = MIMEText( f. read( ) , 'plain' , 'utf-8' ) att[ 'Content-Type' ] = 'application/octet-stream' file_name = re. split( r'[\\|/]' , file_path) [ - 1 ] att[ 'Content-Disposition' ] = f'attachment; filename=" { file_name} "' self. msg. attach( att) email = Email( sender= 'xxx@qq.com' , receiver= 'xxx@qq.com' , title= 'title' , server= 'smtp.qq.com' , auth_code= 'xxxxxx' , message= 'xxxxx' , attachment_file= 'E:\\Py3Sel3Ifram\\report.html' )
「小贴士」 :点击头像→【关注 】按钮,获取更多软件测试的晋升认知不迷路! 🚀