SMTP是发送邮件的协议,Python内置对SMTP的支持,可以发送纯文本邮件、HTML邮件以及带附件的邮件。
Python对SMTP支持有smtplib
和email
两个模块,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>
发送结果