7人参与 • 2025-10-27 • Python
在日常开发和工作中,我们经常需要实现自动发送邮件的功能,比如监控告警通知、数据报表推送、用户注册验证等。python 中的 smtplib 库和 email 库为我们提供了便捷的 smtp 邮件发送解决方案,本文将从基础概念出发,逐步讲解如何用 python3 实现纯文本邮件、html 格式邮件、带附件邮件以及嵌入图片的邮件发送,最后还会介绍如何使用第三方 smtp 服务(以 qq 邮箱为例)实现跨环境邮件发送,适合零基础开发者学习和实战。
在开始代码实战前,我们先了解两个核心知识点:smtp 协议和 python 中用于发送邮件的库。
smtp(simple mail transfer protocol,简单邮件传输协议)是一组用于将邮件从源地址传输到目的地址的规则,它定义了邮件服务器之间如何通信,以及如何控制邮件的中转方式。我们日常发送邮件,本质上就是通过 smtp 协议与邮件服务器交互,完成邮件的投递。
python 内置了两个关键库,无需额外安装即可使用:
smtplib:对 smtp 协议进行封装,提供了建立 smtp 连接、登录服务器、发送邮件等核心功能。email:用于构造邮件内容,包括邮件头(发件人、收件人、主题)、邮件正文(纯文本/html)、附件、图片等,解决了邮件格式符合 smtp 协议规范的问题(避免因格式错误导致邮件发送失败或乱码)。在实现具体功能前,我们先掌握 smtplib 库的核心对象和方法,这是后续所有实战的基础。
要发送邮件,首先需要创建 smtplib.smtp 对象,用于与 smtp 服务器建立连接。其语法如下:
import smtplib # 语法格式 smtpobj = smtplib.smtp([host [, port [, local_hostname]]])
参数说明:
host(可选):smtp 服务器主机地址,可填 ip 或域名(如 qq 邮箱的 smtp.qq.com)。port(可选):smtp 服务器端口号,默认端口为 25(非加密),ssl 加密端口通常为 465 或 587(如 qq 邮箱用 465)。local_hostname(可选):若 smtp 服务器在本机,可指定为 localhost。创建 smtp 对象后,通过 sendmail 方法发送邮件,语法如下:
smtpobj.sendmail(from_addr, to_addrs, msg[, mail_options, rcpt_options])
参数说明:
from_addr:发件人邮箱地址(如 xxx@qq.com)。to_addrs:收件人邮箱地址列表(即使只有一个收件人,也需用列表格式,如 ['yyy@163.com'])。msg:邮件内容字符串,必须符合 smtp 协议格式(需包含 from、to、subject 等头部信息,以及正文/附件)。接下来,我们通过四个实战案例,逐步掌握不同类型邮件的发送方法,所有代码均可直接修改后运行。
纯文本邮件是最基础的类型,仅包含文字内容,适合简单通知。
#!/usr/bin/python3
import smtplib
from email.mime.text import mimetext
from email.header import header
# 1. 配置邮件基本信息
sender = 'xcsharp@126.com' # 发件人邮箱
receivers = ['xcleigh@126.com'] # 收件人邮箱列表(可多个)
# 2. 构造邮件正文(三个参数:文本内容、格式(plain=纯文本)、编码)
message = mimetext('python 邮件发送测试...这是纯文本内容', 'plain', 'utf-8')
# 3. 设置邮件头部信息(发件人昵称、收件人昵称、邮件主题)
message['from'] = header("xcsharp", 'utf-8') # 发件人显示的昵称
message['to'] = header("xcleigh", 'utf-8') # 收件人显示的昵称
message['subject'] = header('python smtp 纯文本邮件测试', 'utf-8') # 邮件主题
# 4. 连接 smtp 服务器并发送邮件
try:
# 若使用本机 smtp 服务器(如已安装 sendmail),直接连接 localhost
smtpobj = smtplib.smtp('localhost')
# 发送邮件(发件人、收件人、邮件内容字符串)
smtpobj.sendmail(sender, receivers, message.as_string())
print("纯文本邮件发送成功")
except smtplib.smtpexception:
print("error: 无法发送纯文本邮件")
sendmail 服务(如 linux 系统),直接运行代码即可发送成功。sendmail,可跳过此案例,直接学习 3.5 节(第三方 smtp 服务)。html 格式邮件支持富文本(如链接、表格、样式),适合展示复杂内容(如数据报表、活动通知)。其核心是将 mimetext 的 _subtype 参数设为 html。
#!/usr/bin/python3
import smtplib
from email.mime.text import mimetext
from email.header import header
sender = 'from@runoob.com'
receivers = ['429240967@qq.com']
# 1. 构造 html 格式的邮件正文
mail_msg = """
<p>python 邮件发送测试...</p>
<p>这是 <b>html 格式</b> 的邮件,支持富文本:</p>
<p>1. 点击访问 <a href="http://www.runoob.com" rel="external nofollow" >菜鸟教程</a></p>
<p>2. 以下是表格示例:</p>
<table border="1">
<tr><th>姓名</th><th>年龄</th></tr>
<tr><td>张三</td><td>25</td></tr>
<tr><td>李四</td><td>30</td></tr>
</table>
"""
# 2. 构造邮件(subtype 设为 html,表明是 html 格式)
message = mimetext(mail_msg, 'html', 'utf-8')
message['from'] = header("菜鸟教程", 'utf-8')
message['to'] = header("测试用户", 'utf-8')
message['subject'] = header('python smtp html 邮件测试', 'utf-8')
# 3. 发送邮件
try:
smtpobj = smtplib.smtp('localhost')
smtpobj.sendmail(sender, receivers, message.as_string())
print("html 邮件发送成功")
except smtplib.smtpexception:
print("error: 无法发送 html 邮件")
发送成功后,收件人邮箱中会显示带链接、表格的富文本内容,而非纯文字。
工作中常需发送带附件的邮件(如日志文件、excel 报表),核心是使用 mimemultipart 类组合“正文 + 附件”。
#!/usr/bin/python3
import smtplib
from email.mime.text import mimetext
from email.mime.multipart import mimemultipart
from email.header import header
sender = 'from@runoob.com'
receivers = ['429240967@qq.com']
# 1. 创建带附件的邮件实例(mimemultipart 用于组合多部分内容)
message = mimemultipart()
message['from'] = header("菜鸟教程", 'utf-8')
message['to'] = header("测试用户", 'utf-8')
message['subject'] = header('python smtp 带附件邮件测试', 'utf-8')
# 2. 添加邮件正文(纯文本或 html 均可)
message.attach(mimetext('这是带附件的邮件正文...', 'plain', 'utf-8'))
# 3. 构造附件 1(传送当前目录下的 test.txt 文件)
# 读取文件内容,用 base64 编码(确保二进制文件传输不损坏)
att1 = mimetext(open('test.txt', 'rb').read(), 'base64', 'utf-8')
att1["content-type"] = 'application/octet-stream' # 声明附件类型
# 设置附件显示名称(filename 为邮件中显示的文件名,可自定义)
att1["content-disposition"] = 'attachment; filename="test.txt"'
message.attach(att1) # 将附件添加到邮件
# 4. 构造附件 2(传送 runoob.txt 文件,方法同上)
att2 = mimetext(open('runoob.txt', 'rb').read(), 'base64', 'utf-8')
att2["content-type"] = 'application/octet-stream'
att2["content-disposition"] = 'attachment; filename="runoob.txt"'
message.attach(att2)
# 5. 发送邮件
try:
smtpobj = smtplib.smtp('localhost')
smtpobj.sendmail(sender, receivers, message.as_string())
print("带附件邮件发送成功")
except smtplib.smtpexception:
print("error: 无法发送带附件邮件")
test.txt)在代码运行的当前目录下,否则需指定完整路径(如 c:/files/test.txt)。xlsx、pdf、zip),只需修改文件名和路径即可。若想在 html 邮件中直接显示图片(而非作为附件),需将图片以“内嵌资源”的方式添加,核心是通过 content-id 关联 html 中的图片引用。
#!/usr/bin/python3
import smtplib
from email.mime.image import mimeimage
from email.mime.multipart import mimemultipart
from email.mime.text import mimetext
from email.header import header
sender = 'from@runoob.com'
receivers = ['429240967@qq.com']
# 1. 创建关联型邮件实例(related 表示内容间有关联,如图片引用)
msgroot = mimemultipart('related')
msgroot['from'] = header("菜鸟教程", 'utf-8')
msgroot['to'] = header("测试用户", 'utf-8')
msgroot['subject'] = header('python smtp 内嵌图片邮件测试', 'utf-8')
# 2. 创建备选内容容器(兼容不支持 html 的邮件客户端)
msgalternative = mimemultipart('alternative')
msgroot.attach(msgalternative)
# 3. 构造 html 正文(通过 cid:image1 引用图片,与后续图片的 content-id 对应)
mail_msg = """
<p>python 邮件发送测试...</p>
<p>这是内嵌图片的 html 邮件:</p>
<p><img src="cid:image1"></p> <!-- 引用图片 id 为 image1 -->
"""
msgalternative.attach(mimetext(mail_msg, 'html', 'utf-8'))
# 4. 读取图片并添加为内嵌资源
fp = open('test.png', 'rb') # 读取当前目录下的 test.png 图片
msgimage = mimeimage(fp.read())
fp.close()
# 5. 设置图片的 content-id(需与 html 中的 cid 一致)
msgimage.add_header('content-id', '<image1>')
msgroot.attach(msgimage)
# 6. 发送邮件
try:
smtpobj = smtplib.smtp('localhost')
smtpobj.sendmail(sender, receivers, msgroot.as_string())
print("内嵌图片邮件发送成功")
except smtplib.smtpexception:
print("error: 无法发送内嵌图片邮件")
发送成功后,图片会直接显示在邮件正文中,而非作为附件下载(部分邮箱可能需要将邮件从垃圾箱移到收件箱才能正常显示图片)。
前面的案例依赖本机 sendmail 服务,实际开发中更常用 第三方 smtp 服务(如 qq 邮箱、网易邮箱、企业邮箱),支持跨环境发送(windows、mac、linux 通用)。
以 qq 邮箱为例,需先完成两步准备工作:
qq 邮箱不允许直接使用登录密码作为 smtp 密码,需生成“授权码”(用于第三方应用登录):
smtp.qq.com465(推荐使用 ssl 加密,更安全)#!/usr/bin/python3
import smtplib
from email.mime.text import mimetext
from email.utils import formataddr
# 1. 配置 qq 邮箱信息(需替换为自己的信息)
my_sender = '123456@qq.com' # 发件人 qq 邮箱账号
my_pass = 'abcdefghijklmnop' # 发件人邮箱授权码(不是登录密码!)
my_user = '654321@qq.com' # 收件人邮箱账号(可发给自己测试)
def send_qq_mail():
ret = true # 标记邮件是否发送成功
try:
# 2. 构造纯文本邮件正文
msg = mimetext('这是用 qq 邮箱 smtp 发送的测试邮件', 'plain', 'utf-8')
# 3. 设置邮件头部(formataddr 避免中文乱码)
# 格式:(昵称, 邮箱账号)
msg['from'] = formataddr(["我的 qq 邮箱", my_sender])
msg['to'] = formataddr(["测试收件人", my_user])
msg['subject'] = "python smtp qq 邮箱测试" # 邮件主题
# 4. 连接 qq 邮箱 smtp 服务器(ssl 加密)
# 注意:使用 smtp_ssl 而非 smtp,端口为 465
server = smtplib.smtp_ssl("smtp.qq.com", 465)
server.login(my_sender, my_pass) # 登录 smtp 服务器
# 5. 发送邮件(收件人列表需用列表格式)
server.sendmail(my_sender, [my_user,], msg.as_string())
# 6. 关闭连接
server.quit()
except exception as e:
print(f"发送失败原因:{e}")
ret = false
return ret
# 调用函数发送邮件
ret = send_qq_mail()
if ret:
print("qq 邮箱邮件发送成功")
else:
print("qq 邮箱邮件发送失败")
smtp.163.com,端口 465,同样需要开启 smtp 服务并获取授权码。在实战中可能遇到邮件发送失败的问题,以下是高频问题及解决方法:
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
报错 smtplib.smtpauthenticationerror | 1. 授权码错误 2. 未开启 smtp 服务 | 1. 重新生成 qq/网易邮箱授权码(注意区分登录密码与授权码) 2. 登录邮箱进入“设置-账户”,开启 imap/smtp 服务 |
| 邮件发送成功但收件箱未收到 | 1. 邮件被判定为垃圾邮件 2. 收件人邮箱地址错误 | 1. 检查垃圾箱,将发件人添加到联系人白名单 2. 核对 receivers 列表中的邮箱地址,确保无拼写错误 |
报错 smtplib.smtpconnecterror | 1. smtp 服务器地址或端口错误 2. 本地网络防火墙拦截端口 | 1. 确认第三方邮箱 smtp 地址(如 qq 是 smtp.qq.com)和端口(465 用于 ssl)2. 临时关闭防火墙,或在防火墙设置中允许 python 程序访问网络 |
| html 邮件乱码或图片不显示 | 1. 编码未设置为 utf-82. html 中图片 cid 与 content-id 不匹配 | 1. 构造 mimetext 时确保编码参数为 utf-82. 检查图片 content-id 与 html 中 src="cid:xxx" 的值完全一致(包括尖括号,如 <image1>) |
通过本文的学习,我们已经掌握了 python3 发送各类 smtp 邮件的核心方法,从基础的纯文本邮件到复杂的带附件、内嵌图片邮件,再到跨环境的第三方 smtp 服务调用,基本能覆盖日常开发中自动发送邮件的需求,如服务器监控告警、定时数据报表推送、用户注册验证码发送等场景。
若需进一步拓展功能,可参考以下方向:
schedule 库或 apscheduler 库,实现每天/每周定时发送邮件(如周报自动推送)。sendmail 方法的 to_addrs 列表中添加抄送(cc)或密送(bcc)地址,同时在邮件头部通过 message['cc']/message['bcc'] 设置显示名称。email.mime.application 类发送 pdf、excel 等特殊格式附件,或通过 email.mime.multipart 组合纯文本+html 双版本正文(兼容不同邮件客户端)。以上就是python3实现smtp发送邮件的实战指南的详细内容,更多关于python3 smtp发送邮件的资料请关注代码网其它相关文章!
您想发表意见!!点此发布评论
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论