Python3 SMTP发送邮件(保姆级教程)
💡一则或许对你有用的小广告
欢迎加入小哈的星球 ,你将获得:专属的项目实战(已更新的所有项目都能学习) / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
- 新开坑项目:《Spring AI 项目实战》 正在持续爆肝中,基于 Spring AI + Spring Boot 3.x + JDK 21..., 点击查看 ;
- 《从零手撸:仿小红书(微服务架构)》 已完结,基于
Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...
,点击查看项目介绍 ;演示链接: http://116.62.199.48:7070 ;- 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;
截止目前, 星球 内专栏累计输出 90w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 3100+ 小伙伴加入学习 ,欢迎点击围观
前言
在数字化时代,自动化发送邮件是开发者的必备技能之一。无论是电商订单通知、系统告警,还是定期报告生成,SMTP(Simple Mail Transfer Protocol)技术都能高效完成任务。本文将从零开始,逐步讲解如何使用Python3实现SMTP邮件发送功能,帮助编程初学者和中级开发者掌握这一实用技能。
SMTP协议的基础概念
SMTP(简单邮件传输协议)是互联网电子邮件系统的核心协议之一,它负责在邮件服务器之间或客户端与服务器之间传递邮件。可以将其比喻为“邮件快递公司”:当用户通过客户端(如Outlook或Python脚本)编写邮件后,SMTP协议会像快递员一样,将邮件从发件人的服务器“打包”并“投递”到收件人的服务器中。
SMTP的工作流程包含三个关键步骤:
- 连接服务器:客户端与SMTP服务器建立TCP连接(通常使用端口25、465或587)。
- 身份验证:用户通过用户名和密码(或令牌)向服务器证明身份。
- 发送邮件:将邮件内容按照特定格式(如RFC 5322标准)传输至目标服务器。
环境准备与核心库介绍
Python中实现SMTP功能的核心库是smtpd
和smtplib
。其中,smtplib
提供了与SMTP协议交互的接口,而email
模块用于构建邮件内容。
安装与导入
无需额外安装,Python3标准库已包含这些模块:
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
邮件服务器配置
不同邮件服务商的SMTP设置不同,常见配置如下:
邮箱服务商 | SMTP服务器地址 | 端口(SSL) | 端口(TLS) |
---|---|---|---|
Gmail | smtp.gmail.com | 465 | 587 |
Outlook | smtp.office365.com | 587 | 587 |
163邮箱 | smtp.163.com | 465 | 25/994 |
注意:使用前需确保邮箱已开启SMTP服务。例如,Gmail用户需在账户安全设置中允许“不够安全的应用”访问。
第一步:发送纯文本邮件
以下代码演示了如何通过Gmail发送最基础的纯文本邮件:
def send_simple_email(subject, body, to_email):
# 邮箱配置
smtp_server = "smtp.gmail.com"
smtp_port = 587 # TLS加密端口
from_email = "your-email@gmail.com"
password = "your-password"
# 构建邮件内容
message = MIMEText(body)
message["Subject"] = subject
message["From"] = from_email
message["To"] = to_email
# 连接并发送
with smtplib.SMTP(smtp_server, smtp_port) as server:
server.starttls() # 启用TLS加密
server.login(from_email, password)
server.sendmail(
from_addr=from_email,
to_addrs=to_email,
msg=message.as_string()
)
send_simple_email(
subject="测试邮件",
body="这是一封测试邮件,由Python发送!",
to_email="recipient@example.com"
)
关键步骤解析:
- MIMEText:将文本内容封装为符合邮件规范的MIME格式。
- starttls():在建立连接后启用TLS加密,确保传输过程的安全性。
- sendmail():接收发件人、收件人和邮件内容字符串,完成实际传输。
进阶功能:发送带附件的HTML邮件
实际应用中,邮件常包含HTML格式的内容或附件。以下示例演示如何发送包含图片和PDF文件的复杂邮件:
def send_complex_email(subject, html_body, to_email, attachments=None):
smtp_server = "smtp.gmail.com"
smtp_port = 587
from_email = "your-email@gmail.com"
password = "your-password"
# 创建复合消息对象
message = MIMEMultipart()
message["Subject"] = subject
message["From"] = from_email
message["To"] = to_email
# 添加HTML正文
html_part = MIMEText(html_body, "html")
message.attach(html_part)
# 添加附件(可选)
if attachments:
for file_path in attachments:
with open(file_path, "rb") as f:
part = MIMEText(f.read(), "base64", "utf-8")
part["Content-Type"] = "application/octet-stream"
part.add_header(
"Content-Disposition",
"attachment",
filename=file_path.split("/")[-1]
)
message.attach(part)
# 发送逻辑与之前相同
with smtplib.SMTP(smtp_server, smtp_port) as server:
server.starttls()
server.login(from_email, password)
server.sendmail(
from_email,
to_email,
message.as_string()
)
send_complex_email(
subject="带附件的邮件",
html_body="<h1>这是HTML内容</h1><img src='cid:image1'>",
to_email="recipient@example.com",
attachments=["report.pdf", "screenshot.png"]
)
扩展点说明:
- MIMEMultipart:用于组合多个邮件部分(文本、附件等)。
- Content-Disposition:指定附件的名称和类型。
- CID引用图片:若需内联图片,可通过
cid:图片ID
在HTML中引用。
异常处理与安全性优化
在实际开发中,需考虑以下常见问题:
异常处理
SMTP发送过程中可能因网络波动、认证失败或邮件内容错误引发异常。使用try-except
块捕获并处理这些情况:
try:
server.sendmail(...)
except smtplib.SMTPAuthenticationError:
print("认证失败,请检查邮箱密码或SMTP权限")
except smtplib.SMTPException as e:
print(f"发送失败:{str(e)}")
except Exception as e:
print(f"未知错误:{str(e)}")
安全性优化建议
- 避免明文密码:使用环境变量或加密配置文件存储敏感信息。
- 使用环境变量示例:
import os password = os.getenv("SMTP_PASSWORD")
- 双重认证(2FA):若邮箱启用了2FA,需生成并使用“应用专用密码”。
实战案例:自动化订单通知系统
假设我们需要为电商平台开发一个订单通知功能,当用户下单后自动发送确认邮件。代码逻辑如下:
def send_order_confirmation(order_id, customer_email):
subject = "订单确认通知"
html_body = f"""
<p>尊敬的客户:</p>
<p>您的订单#{order_id}已成功提交!</p>
<p>预计将在3个工作日内发货。</p>
"""
send_complex_email(
subject=subject,
html_body=html_body,
to_email=customer_email
)
优势:
- 可扩展性:可轻松添加物流跟踪链接或退订选项。
- 模板化:将HTML内容提取为独立模板文件,便于维护。
最佳实践与性能调优
并发发送优化
若需批量发送邮件(如营销活动),单线程逐个发送效率较低。可使用concurrent.futures
实现多线程:
from concurrent.futures import ThreadPoolExecutor
def batch_send_emails(email_list):
with ThreadPoolExecutor(max_workers=5) as executor:
for email in email_list:
executor.submit(send_email, **email_params)
日志与监控
记录发送状态以排查问题:
import logging
logging.basicConfig(filename="mail.log", level=logging.INFO)
def send_email(...):
try:
# 发送逻辑
logging.info(f"邮件发送成功:{to_email}")
except Exception as e:
logging.error(f"发送失败:{str(e)}")
结论
通过本文,读者已掌握从基础SMTP原理到复杂邮件功能的实现方法。无论是自动化通知、系统告警还是商业应用,Python3的SMTP模块都能提供强大支持。建议读者结合自身需求,进一步探索以下方向:
- 集成邮件模板引擎(如Jinja2)实现动态内容渲染。
- 邮件队列系统(如Celery)实现异步发送,提升系统响应速度。
- 反垃圾邮件策略(如SPF、DKIM验证)确保邮件送达率。
掌握SMTP发送邮件技术后,开发者可以更灵活地构建智能化、自动化的解决方案,进一步提升开发效率和用户体验。