ZetCode

Python smtplib

最后修改于 2024 年 1 月 29 日

Python smtplib 教程展示了如何使用 smtplib 模块在 Python 中发送电子邮件。为了发送电子邮件,我们使用了 Python 开发服务器、Mailtrap 在线服务和共享虚拟主机邮件服务器。

SMTP

简单邮件传输协议 (SMTP) 是一种用于电子邮件传输的通信协议。它是互联网标准,于 1982 年首次由 RFC 821 定义,并于 2008 年由 RFC 5321 更新以增加扩展 SMTP 功能。邮件服务器和其他消息传输代理使用 SMTP 发送和接收邮件消息。

smtplib 模块

smtplib 是一个使用简单邮件传输协议 (SMTP) 发送电子邮件的 Python 库。smtplib 是一个内置模块;我们不需要安装它。它抽象了 SMTP 的所有复杂性。

邮件服务器

要实际发送电子邮件,我们需要访问邮件服务器。Python 自带一个简单的开发邮件服务器。Mailslurper 是一个易于使用的本地开发服务器。共享虚拟主机提供商允许我们访问邮件服务器。我们可以在账户中找到相关详细信息。

注意: 避免使用 Gmail,因为它是一个高度安全的服务器,而且使其工作起来相当复杂。事实上,互联网上演示如何使用 Gmail 服务器发送电子邮件的示例,几乎(如果不是全部)都无法正常工作。请改用开发服务器或共享虚拟主机服务器。

最后,我们可以使用 Web 服务。有 MailTrap 或 MailSlurp 等开发 Web 服务,或 Mailgun 或 Mandrill 等生产服务。

使用 Python 内置邮件服务器

$ python -m smtpd -c DebuggingServer -n localhost:1025

我们在端口 1025 上启动 Python 内置邮件服务器。

built_in.py
#!/usr/bin/python

import smtplib
from email.mime.text import MIMEText

sender = 'admin@example.com'
receivers = ['info@example.com']


port = 1025
msg = MIMEText('This is test mail')

msg['Subject'] = 'Test mail'
msg['From'] = 'admin@example.com'
msg['To'] = 'info@example.com'

with smtplib.SMTP('localhost', port) as server:

    # server.login('username', 'password')
    server.sendmail(sender, receivers, msg.as_string())
    print("Successfully sent email")

我们向本地开发邮件服务器发送一个简单的文本消息。

sender = 'admin@example.com'
receivers = ['info@example.com']

我们提供发件人和收件人。example.com 是一个专门用于文档中说明性示例的域名。

msg = MIMEText('This is test mail')

msg['Subject'] = 'Test mail'
msg['From'] = 'admin@example.com'
msg['To'] = 'info@example.com'

MimeText 用于发送文本邮件。我们提供主题、发件人和收件人选项。

with smtplib.SMTP('localhost', port) as server:
...

SMTP 类管理与 SMTP 服务器的连接。

# server.login('username', 'password')

由于我们使用本地开发服务器,因此无需登录。

server.sendmail(sender, receivers, msg.as_string())

电子邮件使用 sendmail 发送。

$ python -m smtpd -c DebuggingServer -n localhost:1025
---------- MESSAGE FOLLOWS ----------
b'Content-Type: text/plain; charset="us-ascii"'
b'MIME-Version: 1.0'
b'Content-Transfer-Encoding: 7bit'
b'Subject: Test mail'
b'From: admin@example.com'
b'To: info@example.com'
b'X-Peer: ::1'
b''
b'This is test mail'
------------ END MESSAGE ------------

发送电子邮件后,我们会收到此消息。

发送邮件到 Mailtrap

Mailtrap 提供免费套餐,允许我们每月发送 500 封邮件。设置 Mailtrap 非常简单。如果我们有 Github 或 Google 账户,只需要几秒钟。

必要的凭据在设置页面提供。此外,还有一些简短的代码示例,展示了如何使用该服务,包括 smtplibDjangoFlask

mailtrap_simple.py
#!/usr/bin/python

import smtplib
from email.mime.text import MIMEText

sender = 'admin@example.com'
receiver = 'info@example.com'

msg = MIMEText('This is test mail')

msg['Subject'] = 'Test mail'
msg['From'] = 'admin@example.com'
msg['To'] = 'info@example.com'

user = 'username'
password = 'passoword'

with smtplib.SMTP("smtp.mailtrap.io", 2525) as server:

    server.login(user, password)
    server.sendmail(sender, receiver, msg.as_string())
    print("mail successfully sent")

此示例将一封简单的邮件发送到 Mailtrap 账户。

server.login(user, password)

用户名和密码在设置页面提供;它们由随机字符组成,例如 24h328df3e32。

发送带附件的电子邮件

当我们有附件或想提供相同内容的替代版本(例如纯文本/HTML 版本)时,会使用 MIMEMultipart

words.txt
falcon
blue
sky
cloud

我们有一个简单的文本文件。

mailtrap_attachment.py
#!/usr/bin/python

import smtplib
from os.path import basename
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.application import MIMEApplication

sender = 'admin@example.com'
receiver = 'info@example.com'

msg = MIMEMultipart()

msg['Subject'] = 'Test mail with attachment'
msg['From'] = 'admin@example.com'
msg['To'] = 'info@example.com'

filename = 'words.txt'
with open(filename, 'r') as f:
    part = MIMEApplication(f.read(), Name=basename(filename))

part['Content-Disposition'] = 'attachment; filename="{}"'.format(basename(filename))
msg.attach(part)

user = 'username'
password = 'password'

with smtplib.SMTP("smtp.mailtrap.io", 2525) as server:

    server.login(user, password)
    server.sendmail(sender, receiver, msg.as_string())
    print("Successfully sent email")

此示例将一个带文本文件附件的电子邮件发送到 Mailtrap。

filename = 'words.txt'
with open(filename, 'r') as f:
    part = MIMEApplication(f.read(), Name=basename(filename))

我们读取文本文件的内容。

part['Content-Disposition'] = 'attachment; filename="{}"'.format(basename(filename))
msg.attach(part)

附件使用 attach 方法添加。

带 STARTTLS 的 Mailtrap

Mailtrap 不支持任何 SMTP 端口上的 SSL,它只支持 STARTTLS。如果我们尝试使用 SSL,我们会收到以下错误消息

ssl.SSLError: [SSL: WRONG_VERSION_NUMBER] wrong version number (_ssl.c:1045)

所谓的机会性 TLS(传输层安全)是纯文本通信协议中的一种扩展。它提供了一种将纯文本连接升级为加密(TLS 或 SSL)连接的方法,而不是为加密通信使用单独的端口。多个协议使用名为 STARTTLS 的命令来实现此目的。它主要用作对抗被动监控的对策。

mailtrap_secured.py
#!/usr/bin/python

import smtplib

from email.mime.text import MIMEText

port = 465

sender = 'admin@example.com'
receiver = 'info@example.com'

msg = MIMEText('Secured test mail')

msg['Subject'] = 'Test mail'
msg['From'] = 'admin@example.com'
msg['To'] = 'info@example.com'

user = 'username'
password = 'password'

with smtplib.SMTP("smtp.mailtrap.io", port) as server:

    server.starttls() # Secure the connection

    server.login(user, password)
    server.sendmail(sender, receiver, msg.as_string())
    print("mail successfully sent")

此示例将电子邮件通过机会性 TLS 发送到 Mailtrap 账户。

server.starttls() # Secure the connection

starttls 将与 SMTP 服务器的连接置于 TLS 模式。

通过 SSL 发送邮件

以下示例通过 SSL 发送电子邮件。这里使用了(来自 websupport.sk 的)虚拟主机 SMTP 服务器。

send_mail_ssl.py
#!/usr/bin/python

import smtplib, ssl
from email.mime.text import MIMEText

sender = 'admin@example.com'
receivers = ['info@example.com']

port = 465
user = 'admin@example.com'
password = 'password'

msg = MIMEText('This is test mail')

msg['Subject'] = 'Test mail'
msg['From'] = 'admin@example.com'
msg['To'] = 'info@example.com'

context = ssl.create_default_context()

with smtplib.SMTP_SSL("smtp.websupport.sk", port, context=context) as server:

    server.login(user, password)
    server.sendmail(sender, receivers, msg.as_string())
    print('mail successfully sent')

SMTP_SSL 通过 SSL 加密的套接字进行连接。

来源

Python smtplib — SMTP 协议客户端

在本文中,我们使用了 Python smtplib 模块来发送电子邮件。

作者

我叫 Jan Bodnar,是一位热情的程序员,拥有丰富的编程经验。我自 2007 年以来一直在撰写编程文章。迄今为止,我已撰写了 1,400 多篇文章和 8 本电子书。我在教授编程方面拥有超过十年的经验。

列出所有 Python 教程