基于Python實(shí)現(xiàn)自動(dòng)化郵件發(fā)送系統(tǒng)的完整指南
一、前言:
在現(xiàn)代軟件開(kāi)發(fā)和自動(dòng)化流程中,郵件通知是一個(gè)常見(jiàn)且實(shí)用的功能。無(wú)論是用于發(fā)送報(bào)告、告警信息還是用戶(hù)提醒,通過(guò) Python 實(shí)現(xiàn)自動(dòng)化的郵件發(fā)送功能都能極大提升工作效率。本文將基于你提供的兩個(gè)文件(`.env` 配置文件與 Python 腳本),詳細(xì)介紹如何構(gòu)建一個(gè)支持單發(fā)和群發(fā)、可配置 SMTP 的郵件發(fā)送系統(tǒng)。
二、項(xiàng)目概述
我們將使用以下技術(shù)棧來(lái)完成這個(gè)任務(wù):
- Python:核心編程語(yǔ)言
- smtplib:Python 內(nèi)置庫(kù),用于連接 SMTP 服務(wù)器
- email.mime:處理郵件內(nèi)容(文本、HTML、附件)
- python-dotenv:讀取 `.env` 文件中的環(huán)境變量
- os:獲取環(huán)境變量
- json:處理結(jié)構(gòu)化數(shù)據(jù)(如 JSON 格式的郵件正文)
三、配置文件 `.env` 解析
你的 `.env` 文件如下所示:
# Gmail 配置 EMAIL=123477787@qq.com ## 你的郵箱地址 EMAIL_PASSWORD=vfoae##### ## 你的授權(quán)碼 # 其他配置項(xiàng) SMTP_SERVER=smtp.qq.com SMTP_PORT=587
該文件定義了發(fā)送郵件所需的必要參數(shù):
- EMAIL:發(fā)件人郵箱地址
- EMAIL_PASSWORD:授權(quán)碼(不是登錄密碼!QQ 郵箱需要開(kāi)啟 POP3/SMTP 并獲取授權(quán)碼)
- SMTP_SERVER 和 SMTP_PORT:指定 SMTP 服務(wù)器地址及端口
注意:QQ 郵箱等部分郵箱不支持直接使用登錄密碼,需啟用“POP3/SMTP服務(wù)”并獲取專(zhuān)用授權(quán)碼。


四、代碼結(jié)構(gòu)解析
1. 導(dǎo)入模塊
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
這些模塊分別負(fù)責(zé)加載環(huán)境變量、連接 SMTP 服務(wù)器、構(gòu)造郵件內(nèi)容以及編碼附件。
2. 加載環(huán)境變量
load_dotenv()
EMAIL = os.getenv('EMAIL')
PASSWORD = os.getenv('EMAIL_PASSWORD')
SMTP_SERVER = os.getenv('SMTP_SERVER')
SMTP_PORT = int(os.getenv('SMTP_PORT'))通過(guò) `python-dotenv` 模塊讀取 `.env` 中的配置信息,并將其賦值給全局變量。
3. EmailSender 類(lèi)設(shè)計(jì)
這是整個(gè)系統(tǒng)的核心類(lèi),封裝了連接、發(fā)送、斷開(kāi) 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連接服務(wù)器:
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發(fā)送郵件(支持純文本、HTML、附件):
def send_email(self, to_email, subject, body, html_body=None, attachments=None):
...群發(fā)郵件功能:
def send_bulk_email(self, to_emails, subject, body, html_body=None, attachments=None):
...斷開(kāi)連接:
def disconnect(self):
if hasattr(self, 'server'):
self.server.quit()4. 主函數(shù)調(diào)用邏輯
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("郵件發(fā)送成功!")
sender.disconnect()
return此函數(shù)作為對(duì)外接口,接受收件人列表、主題、內(nèi)容,然后進(jìn)行群發(fā)操作。
5. 測(cè)試入口
if __name__ == '__main__':
recipients = ['402914287@qq.com']
title = '群發(fā)郵件測(cè)試'
ret = "這是一封測(cè)試郵件"
checker_send_email(recipients, title, ret)運(yùn)行腳本時(shí),會(huì)向指定郵箱發(fā)送一封測(cè)試郵件。
五、完整代碼:
.env文件內(nèi)容:
# Gmail 配置 EMAIL=123477787@qq.com ## 你的郵箱地址 EMAIL_PASSWORD=vfoae##### ## 你的授權(quán)碼 # 其他配置項(xiàng) SMTP_SERVER=smtp.qq.com SMTP_PORT=587
send_mail.python文件內(nèi)容:
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設(shè)置
# 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服務(wù)器"""
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):
"""發(fā)送郵件"""
try:
msg = MIMEMultipart('alternative')
msg['From'] = self.email
msg['To'] = to_email
msg['Subject'] = subject
# 添加文本內(nèi)容
msg.attach(MIMEText(body, 'plain', 'utf-8'))
# 添加HTML內(nèi)容(如果提供)
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)
# 發(fā)送郵件
self.server.sendmail(self.email, to_email, msg.as_string())
return True
except Exception as e:
print(f"發(fā)送失?。簕e}")
return False
def send_bulk_email(self, to_emails, subject, body, html_body=None, attachments=None):
"""
群發(fā)郵件
:param to_emails: 收件人郵箱列表
:param subject: 郵件主題
:param body: 郵件正文
:param html_body: HTML格式正文
:param attachments: 附件列表
"""
if not self.server:
print("請(qǐng)先連接到SMTP服務(wù)器")
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"群發(fā)完成:成功 {success_count}/{len(to_emails)}")
return success_count == len(to_emails)
def disconnect(self):
"""斷開(kāi)連接"""
if hasattr(self, 'server'):
self.server.quit()
def checker_send_email(recipient_list, title_text, ret_text):
"""發(fā)送郵件"""
sender = EmailSender(SMTP_SERVER, SMTP_PORT, EMAIL, PASSWORD)
if sender.connect():
# 單發(fā)郵件
# success = sender.send_email(
# '3909878531@qq.com',
# '測(cè)試郵件',
# '這是一封測(cè)試郵件',
# # html_body='<h1>測(cè)試郵件</h1><p>這是一封HTML郵件</p>',
# # attachments=['file1.pdf', 'file2.docx']
# )
# 群發(fā)郵件
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>測(cè)試郵件</h1><p>這是一封HTML郵件</p>',
)
if success:
print("郵件發(fā)送成功!")
sender.disconnect()
return
if __name__ == '__main__':
recipients = ['23398877797@qq.com']
title = '群發(fā)郵件測(cè)試'
ret = "這是一封測(cè)試郵件"
checker_send_email(recipients, title, ret)六、總結(jié)
通過(guò)合理使用 `.env` 配置文件、`smtplib` 及 `email` 模塊,我們可以輕松實(shí)現(xiàn)單發(fā)、群發(fā)、帶附件的郵件功能。這種自動(dòng)化工具在實(shí)際工作中具有很高的實(shí)用價(jià)值,特別是在定時(shí)任務(wù)、監(jiān)控報(bào)警、數(shù)據(jù)分析等場(chǎng)景中。
**提示**:在部署到生產(chǎn)環(huán)境前,請(qǐng)務(wù)必確認(rèn)郵箱賬號(hào)權(quán)限設(shè)置正確,并對(duì)敏感信息(如密碼)做好安全保護(hù)措施。
以上就是基于Python實(shí)現(xiàn)自動(dòng)化郵件發(fā)送系統(tǒng)的完整指南的詳細(xì)內(nèi)容,更多關(guān)于Python自動(dòng)化郵件發(fā)送系統(tǒng)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
利用Python自動(dòng)監(jiān)控網(wǎng)站并發(fā)送郵件告警的方法
這篇文章介紹的是通過(guò)定時(shí)執(zhí)行python腳本,可以實(shí)現(xiàn)定期批量訪問(wèn)網(wǎng)站,如果發(fā)現(xiàn)網(wǎng)站打不開(kāi),第一時(shí)間發(fā)郵件到管理員郵箱進(jìn)行預(yù)警。有需要的可以參考借鑒。2016-08-08
PyQt5實(shí)現(xiàn)界面(頁(yè)面)跳轉(zhuǎn)的示例代碼
這篇文章主要介紹了PyQt5實(shí)現(xiàn)界面跳轉(zhuǎn)的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04
使用matplotlib畫(huà)圖之坐標(biāo)軸不等距
這篇文章主要介紹了使用matplotlib畫(huà)圖之坐標(biāo)軸不等距方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-02-02
python實(shí)現(xiàn)簡(jiǎn)單文件讀寫(xiě)函數(shù)
這篇文章主要為大家詳細(xì)介紹了python實(shí)現(xiàn)簡(jiǎn)單文件讀寫(xiě)函數(shù),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-02-02
Python實(shí)現(xiàn)的多線程端口掃描工具分享
這篇文章主要介紹了Python實(shí)現(xiàn)的多線程端口掃描工具分享,工具實(shí)現(xiàn)了掃單IP和掃IP段功能,本文給出運(yùn)行效果和實(shí)現(xiàn)源碼,需要的朋友可以參考下2015-01-01
Python運(yùn)維開(kāi)發(fā)之psutil庫(kù)的使用詳解
這篇文章主要介紹了Python運(yùn)維開(kāi)發(fā)之psutil庫(kù)的使用,psutil能夠輕松實(shí)現(xiàn)獲取系統(tǒng)運(yùn)行的進(jìn)程和系統(tǒng)利用率。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-10-10

