使用 Python 发送邮件

在 Python 中,可以使用标准库中的 email.message.EmailMessage 和 smtplib.SMTP_SSL 发送邮件;如需用于生产环境投递,可以通过 messagebird-sdk 包调用 HTTP 邮件 API。

Python 标准库提供了用于 SMTP 连接的 smtplib 和用于构建邮件的 email.message.EmailMessage,因此基本的 SMTP 发送无需任何第三方包。对于生产环境投递,HTTP 邮件 API 会处理 IP 预热、重试和退信事件,你无需自行运行邮件服务器。

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

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 负责处理这一层:你使用 API 密钥进行身份验证,发送 JSON,并读取结构化响应,而无需解析 SMTP 状态码。

使用 Bird 发送

安装 Bird Python SDK(pip install messagebird-sdk),即可通过 HTTPS 发送邮件,无需自行管理 SMTP 连接:

from bird import APIError, Bird

client = Bird()

try:
    message = client.email.send(
        from_="onboarding@messagebird.dev",
        to=["delivered@messagebird.dev"],
        subject="Hello from Python",
        text="It works.",
        html="<p>It works.</p>",
    )
    print(message.id, message.status)
except APIError as err:
    print("send failed:", err)

Bird() 会自动从环境变量中读取 BIRD_API_KEY。从 onboarding@messagebird.dev 发送到 delivered@messagebird.dev 沙箱地址,可以在配置自定义域名之前验证你的密钥和载荷。如果请求未通过校验,APIError 会返回 HTTP 状态码和错误码。

基于同一网络构建。

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

Start building with Bird in minutes.