PythonSMTP发邮件实战教程
想要掌握Python邮件发送?本文为你提供一份详尽的实战教程,深入解析如何使用Python的smtplib和email模块,轻松实现邮件发送功能。我们不仅会教你如何处理邮件内容的编码问题,避免乱码,还会详细讲解如何添加附件,让你的邮件更加丰富多彩。此外,本文还总结了常见的邮件发送失败原因,例如认证失败、连接失败以及收件人被拒绝等,并提供相应的排查建议和解决方案。通过本文,你将学会如何构建稳定可靠的Python邮件发送系统,或者你还可以选择使用更高级的第三方邮件发送服务提供商的API,它们提供了更高级、更稳定的邮件发送解决方案,例如SendGrid、Mailgun、AWS SES (Simple Mail Service)、阿里云邮件推送等。
Python发送邮件时处理编码和附件需使用email模块。1. 对于文本或HTML内容,使用MIMEText类并指定字符集(如utf-8),确保正确编码避免乱码;2. 附件处理需构建MIMEMultipart容器,每个附件作为MIMEBase对象,经Base64编码并添加Content-Disposition头指定文件名。常见发送失败原因包括:1. 认证失败,需使用授权码而非登录密码,并确认SMTP服务已开启;2. 连接失败,检查服务器地址、端口及网络状况,确保SSL/TLS配置正确;3. 收件人被拒绝,确认收件地址有效且未被服务器拦截。此外,可通过开启调试模式、手动测试及查看异常信息辅助排查问题。

Python发送邮件主要依赖其内置的smtplib和email模块。smtplib负责实际的SMTP(Simple Mail Transfer Protocol)连接和邮件发送,而email模块则帮助我们构建符合MIME标准的邮件内容,比如添加附件、设置HTML格式等。这套组合拳用起来效率很高,但要真正做到稳定可靠地发送,有些坑点是需要提前了解的。

解决方案
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
import os
def send_email_via_smtp(sender_email, sender_password, receiver_email, subject, body, smtp_server, smtp_port, is_html=False, attachments=None):
"""
通过SMTP协议发送邮件。
Args:
sender_email (str): 发件人邮箱地址。
sender_password (str): 发件人邮箱密码或授权码。
receiver_email (str): 收件人邮箱地址。
subject (str): 邮件主题。
body (str): 邮件正文。
smtp_server (str): SMTP服务器地址。
smtp_port (int): SMTP服务器端口(通常是465或587)。
is_html (bool): 正文是否为HTML格式。
attachments (list): 附件文件路径列表。
"""
try:
# 构建邮件内容
if attachments:
msg = MIMEMultipart()
else:
msg = MIMEText(body, 'html' if is_html else 'plain', 'utf-8')
msg['From'] = sender_email
msg['To'] = receiver_email
msg['Subject'] = subject
if attachments:
msg.attach(MIMEText(body, 'html' if is_html else 'plain', 'utf-8'))
for filepath in attachments:
if not os.path.exists(filepath):
print(f"警告:附件文件不存在 - {filepath}")
continue
part = MIMEBase('application', 'octet-stream')
with open(filepath, 'rb') as file:
part.set_payload(file.read())
encoders.encode_base64(part)
part.add_header('Content-Disposition', f'attachment; filename="{os.path.basename(filepath)}"')
msg.attach(part)
# 连接SMTP服务器并发送邮件
print(f"尝试连接SMTP服务器: {smtp_server}:{smtp_port}")
server = None
if smtp_port == 465: # SSL加密
server = smtplib.SMTP_SSL(smtp_server, smtp_port)
elif smtp_port == 587: # TLS加密
server = smtplib.SMTP(smtp_server, smtp_port)
server.starttls() # 启动TLS加密
else:
raise ValueError("不支持的SMTP端口,请使用465 (SSL) 或 587 (TLS)。")
# server.set_debuglevel(1) # 调试模式,会打印详细的SMTP交互日志
server.login(sender_email, sender_password)
server.sendmail(sender_email, receiver_email, msg.as_string())
server.quit()
print("邮件发送成功!")
except smtplib.SMTPAuthenticationError as e:
print(f"SMTP认证失败:请检查邮箱地址或授权码是否正确。错误信息:{e}")
print("提示:部分邮箱服务(如QQ、163)需要开启SMTP服务并使用授权码而非登录密码。")
except smtplib.SMTPConnectError as e:
print(f"SMTP连接失败:请检查SMTP服务器地址和端口是否正确,或网络是否存在问题。错误信息:{e}")
except smtplib.SMTPRecipientsRefused as e:
print(f"收件人被拒绝:可能收件人地址无效或服务器拒绝接收。错误信息:{e.recipients}")
except Exception as e:
print(f"发送邮件时发生未知错误:{e}")
# 示例用法 (请替换为您的实际信息)
if __name__ == "__main__":
SENDER_EMAIL = "your_email@example.com" # 你的邮箱
SENDER_PASSWORD = "your_email_password_or_app_password" # 你的邮箱密码或授权码
RECEIVER_EMAIL = "recipient_email@example.com" # 收件人邮箱
SMTP_SERVER = "smtp.example.com" # 邮箱服务商的SMTP服务器地址,例如 'smtp.qq.com', 'smtp.163.com', 'smtp.gmail.com'
SMTP_PORT = 465 # 或 587
# 简单文本邮件
print("\n--- 发送纯文本邮件 ---")
send_email_via_smtp(
sender_email=SENDER_EMAIL,
sender_password=SENDER_PASSWORD,
receiver_email=RECEIVER_EMAIL,
subject="Python SMTP测试邮件 - 纯文本",
body="这是一封由Python脚本发送的纯文本测试邮件。",
smtp_server=SMTP_SERVER,
smtp_port=SMTP_PORT
)
# HTML格式邮件
print("\n--- 发送HTML格式邮件 ---")
html_body = """
<html>
<body>
<p>你好,</p>
<p>这是一封<b>HTML格式</b>的测试邮件,由Python脚本发送。</p>
<p>你可以尝试点击这个链接:<a href="https://www.python.org">Python官网</a></p>
<img src="https://www.python.org/static/community_logos/python-logo-only.png" alt="Python Logo" width="100">
<p>祝好!</p>
</body>
</html>
"""
send_email_via_smtp(
sender_email=SENDER_EMAIL,
sender_password=SENDER_PASSWORD,
receiver_email=RECEIVER_EMAIL,
subject="Python SMTP测试邮件 - HTML格式",
body=html_body,
smtp_server=SMTP_SERVER,
smtp_port=SMTP_PORT,
is_html=True
)
# 带有附件的邮件 (请确保有这些文件在当前目录下,或者提供完整路径)
# 比如创建一个名为 'test.txt' 和 'image.png' 的文件
# with open('test.txt', 'w') as f:
# f.write("这是一个附件测试文件。")
# from PIL import Image
# img = Image.new('RGB', (60, 30), color = 'red')
# img.save('image.png')
print("\n--- 发送带附件的邮件 ---")
# 假设 'test.txt' 和 'image.png' 存在于脚本同目录下
# 实际使用时,请替换为真实文件路径
test_attachments = ['test.txt', 'image.png'] # 确保这些文件存在
send_email_via_smtp(
sender_email=SENDER_EMAIL,
sender_password=SENDER_PASSWORD,
receiver_email=RECEIVER_EMAIL,
subject="Python SMTP测试邮件 - 带附件",
body="这是一封带有附件的测试邮件,请查收!",
smtp_server=SMTP_SERVER,
smtp_port=SMTP_PORT,
attachments=test_attachments
)如何处理邮件内容编码和附件?
说实话,邮件内容编码和附件这块,初次接触时确实会觉得有点绕,因为这涉及到MIME(Multipurpose Internet Mail Extensions)标准。简单来说,邮件不仅仅是纯文本,它可能包含各种字符集、HTML格式、图片、文档等等,MIME就是一套规则,告诉邮件客户端如何正确解析这些复杂的内容。
email模块就是Python实现MIME标准的利器。对于纯文本或HTML,我们用MIMEText类,它会自动处理编码问题,比如你指定'utf-8',它就会在邮件头里加上Content-Type: text/plain; charset="utf-8"或者text/html; charset="utf-8"。这很关键,否则收件人看到的可能就是乱码。

而附件,那更是MIME的拿手好戏。它需要将邮件拆分成多个“部分”(Part),用MIMEMultipart来做这个容器。每个附件都是一个独立的MIMEBase对象。比如,你要发一个PDF,你就得读取PDF文件的二进制内容,然后用encoders.encode_base64进行Base64编码(因为邮件传输协议通常是基于文本的,二进制数据需要转换),最后加上Content-Disposition头,告诉收件箱“这是一个附件,它的原始文件名是什么”。代码里我已经把这个逻辑封装进去了,MIMEMultipart作为主容器,邮件正文和各个附件都是它的子部分。这样做,收件方就能清晰地看到邮件内容和可下载的附件了。
为什么我的邮件发送失败了?常见问题与排查
这大概是大家用Python发邮件最常遇到的问题了,我个人也踩过不少坑。遇到发送失败,别急着怀疑人生,通常是以下几个原因:

认证失败 (SMTPAuthenticationError):
- 密码错误? 检查你输入的密码是否正确。
- 授权码? 很多邮箱服务商(比如QQ邮箱、163邮箱、Gmail等)出于安全考虑,不再允许直接使用登录密码进行SMTP认证,而是需要你登录网页版邮箱,在设置里开启SMTP服务,然后生成一个“授权码”或“客户端专用密码”。这个授权码才是你在Python脚本里需要使用的密码。这个是最常见的坑,没有之一。
- 账户未开启SMTP服务? 同样,需要在邮箱设置里手动开启SMTP服务。
连接失败 (SMTPConnectError):
- 服务器地址或端口错误?
smtp.example.com这样的地址和465/587这样的端口号,一定要和你的邮箱服务商提供的一致。比如Gmail是smtp.gmail.com,QQ邮箱是smtp.qq.com。 - 网络问题? 检查你的网络连接是否正常,防火墙是否阻止了Python程序访问外部SMTP端口。有时候公司内网会有严格的端口限制。
- SSL/TLS配置问题? 如果是465端口,通常是直接SSL连接 (
SMTP_SSL);如果是587端口,则需要先建立普通连接,再调用starttls()方法升级为TLS加密连接。端口和加密方式不匹配会导致连接失败。
- 服务器地址或端口错误?
收件人被拒绝 (SMTPRecipientsRefused):
- 收件人地址无效? 检查收件人邮箱地址是否拼写错误或不存在。
- 服务器拒绝? 有时发件服务器会拒绝向某些域名或地址发送邮件,可能是对方服务器的黑名单,或者你的邮件被判定为垃圾邮件特征。
排查建议:
- 开启调试模式:在
smtplib.SMTP或smtplib.SMTP_SSL对象创建后,调用server.set_debuglevel(1)。这会打印出SMTP服务器和客户端之间的详细通信日志,你能清楚看到是哪个环节出了问题,比如认证失败的具体原因码。 - 手动测试:尝试使用邮件客户端(如Outlook、Thunderbird)配置相同的SMTP服务器、端口、邮箱和密码,看能否正常发送。如果客户端也无法发送,那问题多半出在邮箱设置或网络上。
- 查看错误信息:Python的异常信息通常很详细,比如
SMTPAuthenticationError就明确告诉你认证出了问题。
除了SMTP,还有其他发送邮件的方式吗?
当然有,SMTP是底层协议,但很多时候我们并不需要直接去操作它。想象一下,你造房子不需要从挖矿炼铁开始,直接买钢筋水泥多方便。邮件发送也是类似。
现在非常流行的是使用第三方邮件发送服务提供商的API。这些服务商,比如SendGrid、Mailgun、AWS SES (Simple Email Service)、阿里云邮件推送等,它们提供了更高级、更稳定的邮件发送解决方案。
它们的优势在于:
- 简化开发:你不需要关心SMTP的细节,只需要调用它们提供的API(通常是RESTful API),传入发件人、收件人、主题、正文等参数即可。
- 高送达率:这些服务商有专业的团队来维护IP信誉,确保你的邮件能顺利进入收件箱,而不是被当成垃圾邮件。这对于批量发送、营销邮件尤其重要。
- 统计分析:它们通常提供邮件的发送状态、打开率、点击率、退订率等详细数据,方便你进行后续分析和优化。
- 弹性扩展:面对大量的邮件发送需求,这些服务可以轻松扩展,而你自己搭建的SMTP服务器可能很快就会遇到性能瓶颈。
- 处理复杂场景:比如邮件模板、批量发送、延时发送、Webhook通知等,这些都是它们服务的亮点。
虽然直接使用SMTP能让你对邮件发送过程有更深的理解和控制,但对于生产环境或有更高要求的场景,我个人更倾向于推荐使用这些专业的第三方服务。它们能让你把精力放在业务逻辑上,而不是邮件发送的各种技术细节和坑点上。
好了,本文到此结束,带大家了解了《PythonSMTP发邮件实战教程》,希望本文对你有所帮助!关注golang学习网公众号,给大家分享更多文章知识!
JavaScript移除事件监听器方法详解
- 上一篇
- JavaScript移除事件监听器方法详解
- 下一篇
- Deepseek满血版与GeniusAI解析全攻略
-
- 文章 · python教程 | 46分钟前 |
- Python类型错误调试方法详解
- 129浏览 收藏
-
- 文章 · python教程 | 51分钟前 |
- 函数与方法有何不同?详解解析
- 405浏览 收藏
-
- 文章 · python教程 | 55分钟前 | docker Python Dockerfile 官方Python镜像 容器安装
- Docker安装Python步骤详解教程
- 391浏览 收藏
-
- 文章 · python教程 | 1小时前 |
- DjangoJWT刷新策略与页面优化技巧
- 490浏览 收藏
-
- 文章 · python教程 | 1小时前 |
- pandas缺失值处理技巧与方法
- 408浏览 收藏
-
- 文章 · python教程 | 1小时前 |
- TF变量零初始化与优化器关系解析
- 427浏览 收藏
-
- 文章 · python教程 | 1小时前 |
- Python字符串与列表反转技巧
- 126浏览 收藏
-
- 文章 · python教程 | 2小时前 | Python 错误处理 AssertionError 生产环境 assert语句
- Python断言失败解决方法详解
- 133浏览 收藏
-
- 文章 · python教程 | 2小时前 |
- 动态设置NetCDF图表标题的实用方法
- 247浏览 收藏
-
- 文章 · python教程 | 2小时前 |
- PyCharm切换英文界面教程
- 405浏览 收藏
-
- 文章 · python教程 | 2小时前 |
- Behave教程:单个BDD示例运行方法
- 411浏览 收藏
-
- 文章 · python教程 | 3小时前 |
- PythonGTK3动态CSS技巧分享
- 497浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- ChatExcel酷表
- ChatExcel酷表是由北京大学团队打造的Excel聊天机器人,用自然语言操控表格,简化数据处理,告别繁琐操作,提升工作效率!适用于学生、上班族及政府人员。
- 3201次使用
-
- Any绘本
- 探索Any绘本(anypicturebook.com/zh),一款开源免费的AI绘本创作工具,基于Google Gemini与Flux AI模型,让您轻松创作个性化绘本。适用于家庭、教育、创作等多种场景,零门槛,高自由度,技术透明,本地可控。
- 3414次使用
-
- 可赞AI
- 可赞AI,AI驱动的办公可视化智能工具,助您轻松实现文本与可视化元素高效转化。无论是智能文档生成、多格式文本解析,还是一键生成专业图表、脑图、知识卡片,可赞AI都能让信息处理更清晰高效。覆盖数据汇报、会议纪要、内容营销等全场景,大幅提升办公效率,降低专业门槛,是您提升工作效率的得力助手。
- 3444次使用
-
- 星月写作
- 星月写作是国内首款聚焦中文网络小说创作的AI辅助工具,解决网文作者从构思到变现的全流程痛点。AI扫榜、专属模板、全链路适配,助力新人快速上手,资深作者效率倍增。
- 4552次使用
-
- MagicLight
- MagicLight.ai是全球首款叙事驱动型AI动画视频创作平台,专注于解决从故事想法到完整动画的全流程痛点。它通过自研AI模型,保障角色、风格、场景高度一致性,让零动画经验者也能高效产出专业级叙事内容。广泛适用于独立创作者、动画工作室、教育机构及企业营销,助您轻松实现创意落地与商业化。
- 3822次使用
-
- Flask框架安装技巧:让你的开发更高效
- 2024-01-03 501浏览
-
- Django框架中的并发处理技巧
- 2024-01-22 501浏览
-
- 提升Python包下载速度的方法——正确配置pip的国内源
- 2024-01-17 501浏览
-
- Python与C++:哪个编程语言更适合初学者?
- 2024-03-25 501浏览
-
- 品牌建设技巧
- 2024-04-06 501浏览

