Python邮件发送全场景实现:核心库解析、代码示例与最佳实践
Python邮件发送全场景实现摘要 本文系统介绍了Python邮件发送的核心方法,包含标准库(smtplib+email)和第三方库(yagmail)的对比分析。详细讲解了主流邮箱SMTP服务配置和授权码获取方法,并提供了四种典型场景的代码实现:纯文本邮件发送、HTML格式邮件发送、带附件邮件发送以及使用yagmail简化发送流程。文章还强调了关键注意事项,如授权码安全、HTML内容规范等,帮助开
文章目录
Python邮件发送全场景实现:核心库解析、代码示例与最佳实践
在Python开发中,邮件发送是常见需求,涵盖验证码推送、告警通知、报表投递等场景。Python提供了内置标准库(smtplib
+email
)实现底层邮件协议交互,也有第三方库(如yagmail
)简化开发流程。本文系统梳理主流邮件发送库的功能、使用方法、实战代码及注意事项,帮助开发者快速实现各类邮件发送需求。
一、核心库与功能解析
Python发送邮件的核心依赖两类工具:标准库(原生支持,无需额外安装)和第三方库(简化代码,提升效率),其功能与适用场景如下:
库/工具组合 | 核心功能 | 优势 | 劣势 | 适用场景 |
---|---|---|---|---|
smtplib (标准库) |
实现SMTP协议(简单邮件传输协议),负责建立连接、身份验证、发送邮件 | 原生支持,灵活可控,无依赖 | 需手动构造邮件结构(如收件人、附件) | 需定制化邮件(如带复杂附件、HTML格式) |
email (标准库) |
构造邮件内容,支持纯文本、HTML、附件、图片等格式 | 支持所有邮件结构,可高度定制 | 代码繁琐,需手动组装MIME对象 | 复杂邮件场景(多附件、内嵌图片) |
yagmail (第三方) |
封装smtplib 与email ,提供极简API |
代码量减少80%,自动处理连接与格式 | 定制化能力弱于标准库,需额外安装 | 快速开发(如验证码、简单通知) |
二、环境准备:开启SMTP服务与获取授权码
发送邮件前需先配置发件人邮箱的SMTP服务(非登录密码,需获取“授权码”,避免暴露邮箱密码),主流邮箱的配置步骤如下:
1. 主流邮箱SMTP配置信息
邮箱类型 | SMTP服务器地址 | 端口(SSL加密) | 开启SMTP路径 |
---|---|---|---|
QQ邮箱 | smtp.qq.com |
465 | 邮箱设置 → 账户 → 开启“POP3/SMTP服务” |
163邮箱 | smtp.163.com |
465 | 设置 → POP3/SMTP/IMAP → 开启SMTP |
Gmail | smtp.gmail.com |
465 | 账户 → 安全 → 开启“两步验证”→ 生成应用密码 |
企业微信邮箱 | smtp.exmail.qq.com |
465 | 管理中心 → 账户 → 开启SMTP服务 |
2. 获取授权码(以QQ邮箱为例)
- 登录QQ邮箱 → 点击顶部“设置” → 进入“账户”页面;
- 下拉找到“POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务”;
- 开启“POP3/SMTP服务”,按提示发送短信验证;
- 验证通过后,系统生成16位授权码(保存此授权码,用于代码登录)。
三、实战代码示例:覆盖全场景需求
以下按“基础到复杂”的顺序,提供不同场景的代码示例,涵盖纯文本、HTML格式、带附件、第三方库简化发送等需求。
场景1:发送纯文本邮件(标准库smtplib
+email
)
适用于简单通知(如系统告警、验证码),仅包含文本内容。
import smtplib
from email.mime.text import MIMEText
from email.header import Header
def send_text_email(sender, auth_code, receivers, subject, content):
"""
发送纯文本邮件
:param sender: 发件人邮箱(如 "xxx@qq.com")
:param auth_code: 邮箱授权码(非登录密码)
:param receivers: 收件人列表(如 ["yyy@163.com", "zzz@gmail.com"])
:param subject: 邮件主题
:param content: 邮件正文(纯文本)
"""
# 1. 构造纯文本邮件对象(_subtype="plain"表示纯文本,编码用utf-8避免中文乱码)
msg = MIMEText(content, _subtype="plain", _charset="utf-8")
# 设置邮件头:发件人、收件人、主题
msg["From"] = Header(sender, "utf-8") # 发件人显示名(可自定义,如 "系统通知<xxx@qq.com>")
msg["To"] = Header(", ".join(receivers), "utf-8") # 收件人(多个用逗号分隔)
msg["Subject"] = Header(subject, "utf-8") # 邮件主题
try:
# 2. 连接SMTP服务器(以QQ邮箱为例,端口465用SSL加密)
smtp_obj = smtplib.SMTP_SSL("smtp.qq.com", 465)
# 3. 登录邮箱(用户名=发件人邮箱,密码=授权码)
smtp_obj.login(sender, auth_code)
# 4. 发送邮件(from_addr=发件人,to_addrs=收件人列表,msg.as_string()=邮件内容字符串)
smtp_obj.sendmail(sender, receivers, msg.as_string())
print("纯文本邮件发送成功!")
except smtplib.SMTPException as e:
print(f"纯文本邮件发送失败:{e}")
finally:
# 5. 关闭连接
smtp_obj.quit()
# ------------------- 调用示例 -------------------
if __name__ == "__main__":
SENDER = "your_email@qq.com" # 替换为你的发件人邮箱
AUTH_CODE = "your_auth_code" # 替换为你的授权码
RECEIVERS = ["recipient1@163.com", "recipient2@gmail.com"] # 替换为收件人邮箱
SUBJECT = "Python纯文本邮件测试"
CONTENT = "这是一封由Python smtplib库发送的纯文本邮件,用于测试基础邮件发送功能。"
send_text_email(SENDER, AUTH_CODE, RECEIVERS, SUBJECT, CONTENT)
场景2:发送HTML格式邮件(含样式与链接)
适用于美观的通知(如营销邮件、报表通知),支持HTML标签(如<h1>
、<a>
、<table>
)与内联样式。
import smtplib
from email.mime.text import MIMEText
from email.header import Header
def send_html_email(sender, auth_code, receivers, subject, html_content):
"""
发送HTML格式邮件
:param html_content: 邮件正文(HTML字符串)
"""
# 1. 构造HTML邮件对象(_subtype="html"表示HTML格式)
msg = MIMEText(html_content, _subtype="html", _charset="utf-8")
msg["From"] = Header(f"Python邮件测试<{sender}>", "utf-8")
msg["To"] = Header(", ".join(receivers), "utf-8")
msg["Subject"] = Header(subject, "utf-8")
try:
smtp_obj = smtplib.SMTP_SSL("smtp.qq.com", 465)
smtp_obj.login(sender, auth_code)
smtp_obj.sendmail(sender, receivers, msg.as_string())
print("HTML邮件发送成功!")
except smtplib.SMTPException as e:
print(f"HTML邮件发送失败:{e}")
finally:
smtp_obj.quit()
# ------------------- 调用示例 -------------------
if __name__ == "__main__":
# HTML内容(支持内联样式和链接)
HTML_CONTENT = """
<html>
<body>
<h2 style="color:#165DFF;">Python HTML邮件测试</h2>
<p>这是一封带HTML格式的邮件,支持以下功能:</p>
<ul style="color:#333;">
<li>字体颜色与大小设置</li>
<li>超链接:<a href="https://www.python.org" target="_blank">Python官网</a></li>
<li>表格展示:</li>
</ul>
<table border="1" cellpadding="5" style="border-collapse:collapse;">
<tr style="background:#f5f5f5;">
<th>序号</th>
<th>功能</th>
</tr>
<tr>
<td>1</td>
<td>HTML格式渲染</td>
</tr>
<tr>
<td>2</td>
<td>内联样式支持</td>
</tr>
</table>
</body>
</html>
"""
send_html_email(
sender="your_email@qq.com",
auth_code="your_auth_code",
receivers=["recipient@163.com"],
subject="Python HTML邮件测试",
html_content=HTML_CONTENT
)
场景3:发送带附件的邮件(支持多附件)
适用于需要传输文件的场景(如报表Excel、日志文件、图片),需使用MIMEMultipart
组装“邮件正文+附件”。
import smtplib
import os
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email.header import Header
from email import encoders
def send_attachment_email(sender, auth_code, receivers, subject, content, attachment_paths):
"""
发送带附件的邮件
:param attachment_paths: 附件路径列表(如 ["report.xlsx", "log.txt"])
:param content: 邮件正文(纯文本或HTML字符串)
"""
# 1. 创建带附件的邮件对象(MIMEMultipart()表示多部分邮件)
msg = MIMEMultipart()
msg["From"] = Header(f"附件邮件<{sender}>", "utf-8")
msg["To"] = Header(", ".join(receivers), "utf-8")
msg["Subject"] = Header(subject, "utf-8")
# 2. 添加邮件正文(先判断是否为HTML格式)
if "<html>" in content:
msg.attach(MIMEText(content, "html", "utf-8"))
else:
msg.attach(MIMEText(content, "plain", "utf-8"))
# 3. 逐个添加附件
for file_path in attachment_paths:
if not os.path.exists(file_path):
print(f"附件 {file_path} 不存在,跳过添加")
continue
# 3.1 读取附件文件(二进制模式)
with open(file_path, "rb") as f:
# 3.2 创建附件对象(MIMEBase类型,主类型为"application",子类型为"octet-stream"表示二进制流)
attachment = MIMEBase("application", "octet-stream")
attachment.set_payload(f.read()) # 设置附件内容
# 3.3 编码附件(避免中文文件名乱码)
encoders.encode_base64(attachment)
# 3.4 设置附件头(filename为附件显示名)
filename = os.path.basename(file_path)
attachment.add_header(
"Content-Disposition",
f"attachment; filename={Header(filename, 'utf-8').encode()}"
)
# 3.5 将附件添加到邮件对象
msg.attach(attachment)
try:
smtp_obj = smtplib.SMTP_SSL("smtp.qq.com", 465)
smtp_obj.login(sender, auth_code)
smtp_obj.sendmail(sender, receivers, msg.as_string())
print("带附件邮件发送成功!")
except smtplib.SMTPException as e:
print(f"带附件邮件发送失败:{e}")
finally:
smtp_obj.quit()
# ------------------- 调用示例 -------------------
if __name__ == "__main__":
# 附件路径(替换为你的文件路径,支持多个附件)
ATTACHMENTS = ["test_report.xlsx", "system_log.txt"]
send_attachment_email(
sender="your_email@qq.com",
auth_code="your_auth_code",
receivers=["recipient@163.com"],
subject="Python带附件邮件测试",
content="这是一封带附件的邮件,包含测试报表和系统日志。",
attachment_paths=ATTACHMENTS
)
场景4:用yagmail
简化发送(第三方库)
yagmail
通过封装smtplib
与email
,将邮件发送代码简化至3行以内,适合快速开发。
4.1 安装依赖
pip install yagmail
4.2 代码示例(支持纯文本、HTML、附件)
import yagmail
def send_email_with_yagmail(sender, auth_code, receivers, subject, content, attachments=None):
"""
用yagmail简化发送邮件
:param attachments: 附件路径列表(可选,如 ["file1.txt", "file2.xlsx"])
"""
try:
# 1. 初始化SMTP连接(host为SMTP服务器,如QQ邮箱为"smtp.qq.com")
yag = yagmail.SMTP(user=sender, password=auth_code, host="smtp.qq.com")
# 2. 发送邮件(contents支持字符串(纯文本)、HTML字符串、列表(正文+附件))
if attachments:
# 若有附件,contents格式为 [正文, 附件1路径, 附件2路径, ...]
contents = [content] + attachments
else:
contents = content
yag.send(
to=receivers, # 收件人(列表或单个邮箱字符串)
subject=subject, # 主题
contents=contents # 内容(正文+附件)
)
print("yagmail邮件发送成功!")
except Exception as e:
print(f"yagmail邮件发送失败:{e}")
finally:
# 3. 关闭连接
yag.close()
# ------------------- 调用示例 -------------------
if __name__ == "__main__":
# 发送带HTML和附件的邮件
HTML_CONTENT = "<h3>yagmail测试</h3><p>这是用yagmail发送的HTML邮件,带附件。</p>"
send_email_with_yagmail(
sender="your_email@qq.com",
auth_code="your_auth_code",
receivers=["recipient1@163.com", "recipient2@gmail.com"],
subject="yagmail简化邮件测试",
content=HTML_CONTENT,
attachments=["test_file.txt"] # 可选附件
)
四、关键注意事项
-
SMTP服务与端口配置
- 必须使用对应邮箱的SMTP服务器地址(如163邮箱为
smtp.163.com
),端口优先选择465(SSL加密,更安全),避免使用25端口(多数服务商已禁用非加密端口); - 若连接超时,检查网络是否屏蔽SMTP端口(如企业内网需开放465端口)。
- 必须使用对应邮箱的SMTP服务器地址(如163邮箱为
-
授权码而非登录密码
- 现代邮箱(如QQ、163)均不支持用登录密码直接登录SMTP服务,必须使用“授权码”;
- 若出现
smtplib.SMTPAuthenticationError: (535, b'Login Fail...')
,检查授权码是否正确、是否过期(部分邮箱授权码长期有效,部分需定期重新生成)。
-
中文编码与乱码问题
- 构造邮件时必须指定
_charset="utf-8"
,避免中文主题或正文乱码; - 附件文件名含中文时,需用
Header(filename, 'utf-8').encode()
处理(如场景3示例)。
- 构造邮件时必须指定
-
反垃圾邮件策略
- 发件人邮箱与
msg["From"]
需一致(避免被判定为伪造邮件); - 邮件内容避免包含大量敏感词(如“垃圾邮件”“营销”“免费”)或链接(如短链接、可疑域名);
- 批量发送时控制频率(如每分钟不超过10封),避免IP被邮箱服务商拉黑。
- 发件人邮箱与
-
异常处理与日志
- 捕获
smtplib
常见异常(如SMTPConnectError
连接失败、SMTPTimeoutError
超时、SMTPAuthenticationError
授权失败); - 记录邮件发送日志(成功/失败、时间、收件人),便于问题排查。
- 捕获
五、总结
Python发送邮件的核心工具可分为两类:
- 标准库(
smtplib
+email
):灵活性高,支持纯文本、HTML、多附件等复杂场景,适合需要定制化的业务(如企业报表投递、系统告警),但代码量较多; - 第三方库(
yagmail
):API简洁,大幅简化代码,适合快速开发(如验证码、简单通知),但定制化能力弱于标准库。
实际开发中,需根据需求选择工具:简单场景用yagmail
提升效率,复杂场景用标准库实现定制;同时需重点关注SMTP服务配置、授权码正确性、中文编码与反垃圾邮件策略,确保邮件稳定送达。通过本文的代码示例与注意事项,可覆盖绝大多数Python邮件发送需求,快速构建可靠的邮件发送功能。
更多推荐
所有评论(0)