如何用Python案例发送电子邮件?从零到实战的完整指南
目录导读
- 引言:为什么选择Python发送邮件?
- 核心原理:SMTP协议与Python内置库
- 准备工作:获取邮箱授权码与配置
- 实战案例1:发送纯文本邮件(含完整代码)
- 实战案例2:发送带附件与HTML内容的邮件
- 常见错误与问答(Q&A)
- 安全与性能优化建议
- 自动化邮件的无限可能
引言:为什么选择Python发送邮件?
在日常工作中,我们经常需要批量发送通知、报表或验证码,Python凭借其简洁的语法和强大的标准库,成为自动化邮件发送的首选语言,根据Stack Overflow 2024年调查,超过65%的开发者使用Python进行自动化任务,无论是监控告警、定时报表还是用户注册验证,Python都能通过smptplib和email库高效实现。

核心原理:SMTP协议与Python内置库
电子邮件发送依赖SMTP(简单邮件传输协议),Python的smtplib库封装了SMTP客户端的操作,而email.mime模块则负责构造符合RFC标准的邮件内容(文本、HTML、附件等),关键组件包括:
- MIMEText:纯文本或HTML内容
- MIMEBase:二进制附件(如图片、PDF)
- MIMEMultipart:组合多种内容类型
准备工作:获取邮箱授权码与配置
大多数邮箱(如QQ、163、Gmail)要求使用授权码而非登录密码进行SMTP登录,以下是通用步骤:
- 开启SMTP服务:登录邮箱设置,找到“POP3/SMTP服务”并开启(以QQ邮箱为例,路径:设置→账户→POP3/IMAP/SMTP服务)。
- 生成授权码:开启后获得16位授权码,请妥善保管。
- 记录服务器信息:
- QQ邮箱:
smtp.qq.com,端口465(SSL)或587(TLS) - 163邮箱:
smtp.163.com,端口465 - Gmail:
smtp.gmail.com,端口587(需开启“低安全性应用访问”)
- QQ邮箱:
实战案例1:发送纯文本邮件(完整代码)
以下代码实现向指定邮箱发送一封“Python测试邮件”:
import smtplib
from email.mime.text import MIMEText
from email.header import Header
# 配置信息
mail_host = "smtp.qq.com" # SMTP服务器
mail_user = "your_email@qq.com" # 发件人邮箱
mail_pass = "your_authorization_code" # 授权码
receivers = ["receiver@example.com"] # 收件人列表
# 构建邮件内容
message = MIMEText("这是来自Python的自动化测试邮件。", "plain", "utf-8")
message["From"] = Header("Python机器人", "utf-8")
message["To"] = Header("测试用户", "utf-8")
message["Subject"] = Header("Python SMTP测试", "utf-8")
try:
smtpObj = smtplib.SMTP_SSL(mail_host, 465) # 使用SSL连接
smtpObj.login(mail_user, mail_pass)
smtpObj.sendmail(mail_user, receivers, message.as_string())
print("邮件发送成功")
except smtplib.SMTPException as e:
print(f"发送失败: {e}")
finally:
smtpObj.quit()
关键点:
- 建议使用
SMTP_SSL提高安全性。 sendmail方法的第三个参数必须是字符串格式(as_string()转化)。
实战案例2:发送带附件与HTML内容的邮件
工作中常需发送带报告或图片的邮件,以下示例整合了HTML正文与PDF附件:
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
import os
# 配置同案例1
msg = MIMEMultipart()
msg["From"] = mail_user
msg["To"] = ",".join(receivers)
msg["Subject"] = "月度报表附件"
# 1. HTML内容
html_content = """
<html><body>
<h2>2025年4月报表摘要</h2>
<p>总销售额:<strong>¥128,000</strong></p>
<p>同比增幅:<b>+15%</b></p>
</body></html>
"""
msg.attach(MIMEText(html_content, "html", "utf-8"))
# 2. 添加附件(假设report.pdf存在当前目录)
file_path = "./report.pdf"
with open(file_path, "rb") as f:
attachment = MIMEBase("application", "octet-stream")
attachment.set_payload(f.read())
encoders.encode_base64(attachment)
attachment.add_header(
"Content-Disposition",
f"attachment; filename= {os.path.basename(file_path)}"
)
msg.attach(attachment)
# 发送流程同案例1
实用技巧:
- 多附件可循环
os.listdir()添加。 - HTML邮件支持嵌入CSS与图片(需用
cid引用)。
常见错误与问答(Q&A)
Q1:出现“535 Login Fail”错误怎么办?
A:大概率是授权码错误,或未开启SMTP服务,请检查:
- 是否使用授权码而非登录密码。
- QQ邮箱需要开启“POP3/SMTP”后重试。
Q2:邮件被识别为垃圾邮件?
A:注意以下优化:
- 避免使用敏感词(如”免费“”活动“)。
- 设置正确的
From字段(与邮箱地址一致)。 - 添加退订链接(商业邮件合规要求)。
Q3:如何发送给多个收件人?
A:receivers列表可包含多个邮箱,如["a@abc.com", "b@abc.com"],需注意To字段用逗号拼接(",".join(receivers))。
Q4:支持SSL/TLS混合模式吗?
A:大部分服务商不支持混合,建议统一用SSL(端口465)或TLS(端口587)。
Q5:如何处理非ASCII字符的附件名?
A:使用Header编码,如Header("中文文件名.pdf", "utf-8").encode()。
安全与性能优化建议
- 敏感信息保护:授权码绝不可硬编码,应存入环境变量(如
os.getenv("MAIL_PASS"))或配置文件。 - 频繁发送限制:QQ邮箱每日限额约500封,163约200封,超过可能被封。
- 错误重试机制:使用
try-except捕获异常,并加入简易重试逻辑(如延迟10秒后重试)。 - 异步发送:对于Web应用,建议使用Celery或异步任务队列(如
asyncio+aioSMTP)防止阻塞请求。
自动化邮件的无限可能
通过Python案例,你现在可以:
- 1分钟搭建定时监控告警系统(结合
schedule库)。 - 批量发送个性化营销邮件(数据源来自CSV)。
- 对接API(如SendGrid)实现企业级邮件服务。
任何自动化工具都需遵守反垃圾邮件法规(如CAN-SPAM法案),实践时从测试邮箱开始,逐步扩展,你的下一个项目——自动发送每日工作汇总,就从本文的代码起步吧。