文章目录
- import json import os from dotenv import load_dotenv import smtplib from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart from email.mime.base import MIMEBase from email import encoders 这些模块分别负责加载环境变量、连接 SMTP 服务器、构造邮件内容以及编码附件。
- load_dotenv() EMAIL = os.getenv(‘EMAIL’) PASSWORD = os.getenv(‘EMAIL_PASSWORD’) SMTP_SERVER = os.getenv(‘SMTP_SERVER’) SMTP_PORT = int(os.getenv(‘SMTP_PORT’)) 通过 `python-dotenv` 模块读取 `.env` 中的配置信息,并将其赋值给全局变量。
- 这是整个系统的核心类,封装了连接、发送、断开 SMTP 的逻辑。 初始化方法: def __init__(self, smtp_server, smtp_port, email, password): self.smtp_server = smtp_server self.smtp_port = smtp_port self.email = email self.password = password 连接服务器: def connect(self): try: self.server = smtplib.SMTP(self.smtp_server, self.smtp_port) self.server.starttls() self.server.login(self.email, self.password) return True except Exception as e: print(f”连接失败:{e}”) return False 发送邮件(支持纯文本、HTML、附件): def send_email(self, to_email, subject, body, html_body=None, attachments=None): … 群发邮件功能: def send_bulk_email(self, to_emails, subject, body, html_body=None, attachments=None): … 断开连接: def disconnect(self): if hasattr(self, ‘server’): self.server.quit()
- def checker_send_email(recipient_list, title_text, ret_text): sender = EmailSender(SMTP_SERVER, SMTP_PORT, EMAIL, PASSWORD) if sender.connect(): data = json.dumps(ret_text, ensure_ascii=False, indent=2) if isinstance(ret_text, dict) else ret_text success = sender.send_bulk_email( to_emails=recipient_list, subject=title_text, body=data, ) if success: print(“邮件发送成功!”) sender.disconnect() return 此函数作为对外接口,接受收件人列表、主题、内容,然后进行群发操作。
- if __name__ == ‘__main__’: recipients = [‘402914287@qq.com’] title = ‘群发邮件测试’ ret = “这是一封测试邮件” checker_send_email(recipients, title, ret) 运行脚本时,会向指定邮箱发送一封测试邮件。
- # Gmail 配置 EMAIL=123477787@qq.com ## 你的邮箱地址 EMAIL_PASSWORD=vfoae##### ## 你的授权码 # 其他配置项 SMTP_SERVER=smtp.qq.com SMTP_PORT=587
- import json import os from dotenv import load_dotenv import smtplib from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart from email.mime.base import MIMEBase from email import encoders load_dotenv() EMAIL = os.getenv(‘EMAIL’) PASSWORD = os.getenv(‘EMAIL_PASSWORD’) SMTP_SERVER = os.getenv(‘SMTP_SERVER’) SMTP_PORT = os.getenv(‘SMTP_PORT’) # # 常用邮箱SMTP设置 # SMTP_SETTINGS = { # ‘gmail’: { # ‘server’: ‘smtp.gmail.com’, # ‘port’: 587 # }, # ‘outlook’: { # ‘server’: ‘smtp-mail.outlook.com’, # ‘port’: 587 # }, # ‘qq’: { # ‘server’: ‘smtp.qq.com’, # ‘port’: 587 # }, # ‘163’: { # ‘server’: ‘smtp.163.com’, # ‘port’: 25 # }, # ‘sina’: { # ‘server’: ‘smtp.sina.com’, # ‘port’: 25 # } # } # def get_smtp_config(provider): # “””获取SMTP配置””” # return SMTP_SETTINGS.get(provider, SMTP_SETTINGS[‘gmail’]) class EmailSender: def __init__(self, smtp_server, smtp_port, email, password): self.smtp_server = smtp_server self.smtp_port = smtp_port self.email = email self.password = password def connect(self): “””连接SMTP服务器””” try: self.server = smtplib.SMTP(self.smtp_server, self.smtp_port) self.server.starttls() self.server.login(self.email, self.password) return True except Exception as e: print(f”连接失败:{e}”) return False def send_email(self, to_email, subject, body, html_body=None, attachments=None): “””发送邮件””” try: msg = MIMEMultipart(‘alternative’) msg[‘From’] = self.email msg[‘To’] = to_email msg[‘Subject’] = subject # 添加文本内容 msg.attach(MIMEText(body, ‘plain’, ‘utf-8’)) # 添加HTML内容(如果提供) if html_body: msg.attach(MIMEText(html_body, ‘html’, ‘utf-8’)) # 添加附件(如果提供) if attachments: for file_path in attachments: if os.path.exists(file_path): with open(file_path, “rb”) as attachment: part = MIMEBase(‘application’, ‘octet-stream’) part.set_payload(attachment.read()) encoders.encode_base64(part) part.add_header( ‘Content-Disposition’, f’attachment; filename= {os.path.basename(file_path)}’ ) msg.attach(part) # 发送邮件 self.server.sendmail(self.email, to_email, msg.as_string()) return True except Exception as e: print(f”发送失败:{e}”) return False def send_bulk_email(self, to_emails, subject, body, html_body=None, attachments=None): “”” 群发邮件 :param to_emails: 收件人邮箱列表 :param subject: 邮件主题 :param body: 邮件正文 :param html_body: HTML格式正文 :param attachments: 附件列表 “”” if not self.server: print(“请先连接到SMTP服务器”) return False success_count = 0 for email in to_emails: if self.send_email(email, subject, body, html_body, attachments): success_count += 1 print(f”群发完成:成功 {success_count}/{len(to_emails)}”) return success_count == len(to_emails) def disconnect(self): “””断开连接””” if hasattr(self, ‘server’): self.server.quit() def checker_send_email(recipient_list, title_text, ret_text): “””发送邮件””” sender = EmailSender(SMTP_SERVER, SMTP_PORT, EMAIL, PASSWORD) if sender.connect(): # 单发邮件 # success = sender.send_email( # ‘3909878531@qq.com’, # ‘测试邮件’, # ‘这是一封测试邮件’, # # html_body='<h1>测试邮件</h1><p>这是一封HTML邮件</p>’, # # attachments=[‘file1.pdf’, ‘file2.docx’] # ) # 群发邮件 data = json.dumps(ret_text, ensure_ascii=False, indent=2) if isinstance(ret_text, dict) else ret_text success = sender.send_bulk_email( to_emails=recipient_list, subject=title_text, body=data, # html_body='<h1>测试邮件</h1><p>这是一封HTML邮件</p>’, ) if success: print(“邮件发送成功!”) sender.disconnect() return if __name__ == ‘__main__’: recipients = [‘23398877797@qq.com’] title = ‘群发邮件测试’ ret = “这是一封测试邮件” checker_send_email(recipients, title, ret)
目录
- 一、前言:
- 二、项目概述
- 三、配置文件 `.env` 解析
- 四、代码结构解析
- 1. 导入模块
- 2. 加载环境变量
- 3. EmailSender 类设计
- 4. 主函数调用逻辑
- 5. 测试入口
- 五、完整代码:
- .env文件内容:
- send_mail.python文件内容:
- 六、总结
在现代软件开发和自动化流程中,邮件通知是一个常见且实用的功能。无论是用于发送报告、告警信息还是用户提醒,通过 Python 实现自动化的邮件发送功能都能极大提升工作效率。本文将基于你提供的两个文件(`.env` 配置文件与 Python 脚本),详细介绍如何构建一个支持单发和群发、可配置 SMTP 的邮件发送系统。
我们将使用以下技术栈来完成这个任务:
- Python:核心编程语言
- smtplib:Python 内置库,用于连接 SMTP 服务器
- email.mime:处理邮件内容(文本、HTML、附件)
- python-dotenv:读取 `.env` 文件中的环境变量
- os:获取环境变量
- json:处理结构化数据(如 JSON 格式的邮件正文)
你的 `.env` 文件如下所示:
# Gmail 配置 EMAIL=123477787@qq.com ## 你的邮箱地址 EMAIL_PASSWORD=vfoae##### ## 你的授权码 # 其他配置项 SMTP_SERVER=smtp.qq.com SMTP_PORT=587
该文件定义了发送邮件所需的必要参数:
- EMAIL:发件人邮箱地址
- EMAIL_PASSWORD:授权码(不是登录密码!QQ 邮箱需要开启 POP3/SMTP 并获取授权码)
- SMTP_SERVER 和 SMTP_PORT:指定 SMTP 服务器地址及端口
注意:QQ 邮箱等部分邮箱不支持直接使用登录密码,需启用“POP3/SMTP服务”并获取专用授权码。


import json
import os
from dotenv import load_dotenv
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
这些模块分别负责加载环境变量、连接 SMTP 服务器、构造邮件内容以及编码附件。
load_dotenv()
EMAIL = os.getenv('EMAIL')
PASSWORD = os.getenv('EMAIL_PASSWORD')
SMTP_SERVER = os.getenv('SMTP_SERVER')
SMTP_PORT = int(os.getenv('SMTP_PORT'))
通过 `python-dotenv` 模块读取 `.env` 中的配置信息,并将其赋值给全局变量。
这是整个系统的核心类,封装了连接、发送、断开 SMTP 的逻辑。
初始化方法:
def __init__(self, smtp_server, smtp_port, email, password):
self.smtp_server = smtp_server
self.smtp_port = smtp_port
self.email = email
self.password = password
连接服务器:
def connect(self):
try:
self.server = smtplib.SMTP(self.smtp_server, self.smtp_port)
self.server.starttls()
self.server.login(self.email, self.password)
return True
except Exception as e:
print(f"连接失败:{e}")
return False
发送邮件(支持纯文本、HTML、附件):
def send_email(self, to_email, subject, body, html_body=None, attachments=None):
...
群发邮件功能:
def send_bulk_email(self, to_emails, subject, body, html_body=None, attachments=None):
...
断开连接:
def disconnect(self):
if hasattr(self, 'server'):
self.server.quit()
def checker_send_email(recipient_list, title_text, ret_text):
sender = EmailSender(SMTP_SERVER, SMTP_PORT, EMAIL, PASSWORD)
if sender.connect():
data = json.dumps(ret_text, ensure_ascii=False, indent=2) if isinstance(ret_text, dict) else ret_text
success = sender.send_bulk_email(
to_emails=recipient_list,
subject=title_text,
body=data,
)
if success:
print("邮件发送成功!")
sender.disconnect()
return
此函数作为对外接口,接受收件人列表、主题、内容,然后进行群发操作。
if __name__ == '__main__':
recipients = ['402914287@qq.com']
title = '群发邮件测试'
ret = "这是一封测试邮件"
checker_send_email(recipients, title, ret)
运行脚本时,会向指定邮箱发送一封测试邮件。
# Gmail 配置
EMAIL=123477787@qq.com ## 你的邮箱地址
EMAIL_PASSWORD=vfoae##### ## 你的授权码
# 其他配置项
SMTP_SERVER=smtp.qq.com
SMTP_PORT=587
import json
import os
from dotenv import load_dotenv
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
load_dotenv()
EMAIL = os.getenv('EMAIL')
PASSWORD = os.getenv('EMAIL_PASSWORD')
SMTP_SERVER = os.getenv('SMTP_SERVER')
SMTP_PORT = os.getenv('SMTP_PORT')
# # 常用邮箱SMTP设置
# SMTP_SETTINGS = {
# 'gmail': {
# 'server': 'smtp.gmail.com',
# 'port': 587
# },
# 'outlook': {
# 'server': 'smtp-mail.outlook.com',
# 'port': 587
# },
# 'qq': {
# 'server': 'smtp.qq.com',
# 'port': 587
# },
# '163': {
# 'server': 'smtp.163.com',
# 'port': 25
# },
# 'sina': {
# 'server': 'smtp.sina.com',
# 'port': 25
# }
# }
# def get_smtp_config(provider):
# """获取SMTP配置"""
# return SMTP_SETTINGS.get(provider, SMTP_SETTINGS['gmail'])
class EmailSender:
def __init__(self, smtp_server, smtp_port, email, password):
self.smtp_server = smtp_server
self.smtp_port = smtp_port
self.email = email
self.password = password
def connect(self):
"""连接SMTP服务器"""
try:
self.server = smtplib.SMTP(self.smtp_server, self.smtp_port)
self.server.starttls()
self.server.login(self.email, self.password)
return True
except Exception as e:
print(f"连接失败:{e}")
return False
def send_email(self, to_email, subject, body, html_body=None, attachments=None):
"""发送邮件"""
try:
msg = MIMEMultipart('alternative')
msg['From'] = self.email
msg['To'] = to_email
msg['Subject'] = subject
# 添加文本内容
msg.attach(MIMEText(body, 'plain', 'utf-8'))
# 添加HTML内容(如果提供)
if html_body:
msg.attach(MIMEText(html_body, 'html', 'utf-8'))
# 添加附件(如果提供)
if attachments:
for file_path in attachments:
if os.path.exists(file_path):
with open(file_path, "rb") as attachment:
part = MIMEBase('application', 'octet-stream')
part.set_payload(attachment.read())
encoders.encode_base64(part)
part.add_header(
'Content-Disposition',
f'attachment; filename= {os.path.basename(file_path)}'
)
msg.attach(part)
# 发送邮件
self.server.sendmail(self.email, to_email, msg.as_string())
return True
except Exception as e:
print(f"发送失败:{e}")
return False
def send_bulk_email(self, to_emails, subject, body, html_body=None, attachments=None):
"""
群发邮件
:param to_emails: 收件人邮箱列表
:param subject: 邮件主题
:param body: 邮件正文
:param html_body: HTML格式正文
:param attachments: 附件列表
"""
if not self.server:
print("请先连接到SMTP服务器")
return False
success_count = 0
for email in to_emails:
if self.send_email(email, subject, body, html_body, attachments):
success_count += 1
print(f"群发完成:成功 {success_count}/{len(to_emails)}")
return success_count == len(to_emails)
def disconnect(self):
"""断开连接"""
if hasattr(self, 'server'):
self.server.quit()
def checker_send_email(recipient_list, title_text, ret_text):
"""发送邮件"""
sender = EmailSender(SMTP_SERVER, SMTP_PORT, EMAIL, PASSWORD)
if sender.connect():
# 单发邮件
# success = sender.send_email(
# '3909878531@qq.com',
# '测试邮件',
# '这是一封测试邮件',
# # html_body='<h1>测试邮件</h1><p>这是一封HTML邮件</p>',
# # attachments=['file1.pdf', 'file2.docx']
# )
# 群发邮件
data = json.dumps(ret_text, ensure_ascii=False, indent=2) if isinstance(ret_text, dict) else ret_text
success = sender.send_bulk_email(
to_emails=recipient_list,
subject=title_text,
body=data,
# html_body='<h1>测试邮件</h1><p>这是一封HTML邮件</p>',
)
if success:
print("邮件发送成功!")
sender.disconnect()
return
if __name__ == '__main__':
recipients = ['23398877797@qq.com']
title = '群发邮件测试'
ret = "这是一封测试邮件"
checker_send_email(recipients, title, ret)
通过合理使用 `.env` 配置文件、`smtplib` 及 `email` 模块,我们可以轻松实现单发、群发、带附件的邮件功能。这种自动化工具在实际工作中具有很高的实用价值,特别是在定时任务、监控报警、数据分析等场景中。
**提示**:在部署到生产环境前,请务必确认邮箱账号权限设置正确,并对敏感信息(如密码)做好安全保护措施。
以上就是基于Python实现自动化邮件发送系统的完整指南的详细内容,更多关于Python自动化邮件发送系统的资料请关注风君子博客其它相关文章!
您可能感兴趣的文章:
- 基于Python编写自动化邮件发送程序(进阶版)
- Python办公自动化实战之打造智能邮件发送工具
- Python办公自动化之发送电子邮件和Outlook集成
- Python自动化办公之定时发送邮件的实现
- Python实现自动化发送邮件