Email

使用 Python 发送邮件

Python 无需安装任何依赖即可发送邮件。

Python 无需安装任何依赖即可发送邮件。标准库提供了 smtplib 用于 SMTP 连接,以及 email.message.EmailMessage 用于构建邮件,因此一个可运行的脚本大约只需十五行代码。下面是正确完成 TLS 的脚本,以及当真实流量到来时迁移到 HTTP API 的理由。

如何使用标准库发送邮件?

EmailMessage 构建邮件并为你设置请求头。smtplib.SMTP_SSL 在端口 465 上打开加密连接:

import smtplib
from email.message import EmailMessage

msg = EmailMessage()
msg["From"] = "you@yourdomain.com"
msg["To"] = "recipient@example.org"
msg["Subject"] = "Your receipt"
msg.set_content("Thanks for your order. This is the plain-text version.")
msg.add_alternative("<p>Thanks for your order.</p>", subtype="html")

with smtplib.SMTP_SSL("smtp.example.com", 465) as server:
    server.login("smtp-user", "smtp-password")
    server.send_message(msg)

set_content 写入纯文本正文,add_alternative 附加 HTML 版本,客户端会选择它能渲染的部分。同时发送两种格式是良好实践,也有助于提升送达能力

SSL 还是 STARTTLS?

有两种加密路径,它们使用不同的端口。SMTP_SSL 在 465 端口从第一个字节开始协商 TLS。另一种方式是在 587 端口使用明文 SMTP,然后通过 starttls() 将明文连接升级为加密连接:

with smtplib.SMTP("smtp.example.com", 587) as server:
    server.starttls()
    server.login("smtp-user", "smtp-password")
    server.send_message(msg)

根据你的邮件服务器支持的方式选择其一。不要通过未加密的连接发送凭据。将用户名和密码保存在环境变量中,使用 os.environ 读取,而不是硬编码。

如何添加附件?

add_attachment 接收字节数据和 MIME 类型。以二进制模式读取文件:

with open("invoice.pdf", "rb") as f:
    msg.add_attachment(
        f.read(),
        maintype="application",
        subtype="pdf",
        filename="invoice-1042.pdf",
    )

为什么生产环境不应使用原始 SMTP?

脚本可以运行,但生产环境会带来标准库无法解决的问题。你需要一个 IP 信誉良好的邮件服务器、正确的 SPF、DKIM 和 DMARC 记录、针对瞬时故障的重试逻辑,以及查看退信和投诉的途径。HTTP API 将这些全部集成在内。你使用密钥进行身份验证,发送 JSON,并读取结构化响应,而非解析 SMTP 状态码。

使用 Bird 发送

Bird Python SDK 可以在不涉及 SMTP 底层细节的情况下发送同样的邮件:

import bird

client = bird.Bird(api_key=os.environ["BIRD_API_KEY"])

data, error = client.emails.send(
    from_="you@yourdomain.com",
    to="delivered@bird.dev",
    subject="Hello from Python",
    html="<p>It works.</p>",
)

delivered@bird.dev 沙箱地址始终接受邮件,因此首次运行可以在发给真实收件人之前确认你的密钥和载荷。SDK 返回一个 (data, error) 对,这使错误处理更加明确,而不必捕获 SMTP 异常。如果你更熟悉 PHP,PHPMailer 教程涵盖了该生态系统中的等效方案。

常见问题

在 Python 中发送邮件需要安装什么吗?

不需要。smtplibemail.message 在标准库中,因此基本的 SMTP 发送无需额外包。只有在你需要更高层级的客户端或 HTTP API 时才需要添加依赖。

端口 465 和 587 有什么区别?

端口 465 从一开始就要求 TLS,由 smtplib.SMTP_SSL 处理。端口 587 以明文启动,然后通过 starttls() 升级。两者最终都会加密,只是协商加密的时机不同。

什么时候应该从 smtplib 切换到 API?

当你关注送达能力、重试和事件追踪时。标准库只负责发送邮件,不管理信誉,也不报告邮件移交后发生了什么。像 Bird email 这样的 API 覆盖了这一层。

有关完整的请求和响应结构,发送邮件指南端到端地讲解了 API。

基于同一网络构建。

测试 API 密钥即刻获取。添加付款方式并验证发送者身份后,即可解锁生产环境。

你的下一个创意。
随时连接。