# Python `smtplib`教程

> 原文： [http://zetcode.com/python/smtplib/](http://zetcode.com/python/smtplib/)

Python `smtplib`教程展示了如何使用`smtplib`模块在 Python 中发送电子邮件。 要发送电子邮件，我们使用 Python 开发服务器，Mailtrap 在线服务和共享的网络托管邮件服务器。

## SMTP

简单邮件传输协议（SMTP）是用于电子邮件传输的通信协议。它是一个互联网标准，该标准于 1982 年由 RFC 821 首次定义，并于 2008 年由 RFC 5321 更新为扩展 SMTP 添加。 邮件服务器和其他邮件传输代理使用 SMTP 发送和接收邮件。

## `smtplib`模块

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

## 邮件服务器

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

> **注意**：避免使用 Gmail，因为它是高度安全的服务器，并且使其工作非常复杂。 实际上，互联网上的大多数（如果不是全部）示例演示了如何通过 Gmail 服务器发送电子邮件，这些示例都无法正常工作。 而是使用开发服务器或共享的虚拟主机服务器。

最后，我们可以使用 Web 服务。 有开发 Web 服务（例如 MailTrap 或 MailSlurp）或生产服务（例如 Mailgun 或 Mandrill）。

## 使用 Python 内置邮件服务器

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

```

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

`built_in.py`

```py
#!/usr/bin/env 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")

```

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

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

```

我们提供发送者和接收者。 `example.com`是专门用于文档中的说明性示例的域名。

```py
msg = MIMEText('This is test mail')

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

```

`MimeText`用于发送文本电子邮件。 我们提供主题，从选项到选项。

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

```

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

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

```

由于我们使用本地开发服务器，因此不必登录。

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

```

电子邮件带有`sendmail()`发送。

```py
$ 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 帐户，则只需几秒钟。

设置页面中提供了必要的凭据。 另外，还有一些简短的代码示例显示了如何使用服务，包括`smtplib`，`Django`或`Flask`。

`mailtrap_simple.py`

```py
#!/usr/bin/env 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 帐户。

```py
server.login(user, password)

```

用户名和密码在设置页面中给出； 它们由随机字符组成，例如 24h328df3e32。

## 发送带有附件的电子邮件

当我们有附件或要提供相同内容的替代版本（例如纯文本/ HTML 版本）时，将使用`MIMEMultipart`。

`words.txt`

```py
falcon
blue
sky
cloud

```

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

`mailtrap_attachment.py`

```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 发送带有文本文件附件的电子邮件。

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

```

我们阅读了文本文件的内容。

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

```

附件通过`attach()`方法添加。

## 使用 STARTTLS 的邮件陷阱

Mailtrap 在任何 SMTP 端口上都不支持 SSL，它仅支持`STARTTLS`。 如果我们尝试使用 SSL，则会收到以下错误消息：

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

```

所谓的机会 TLS （传输层安全性）是纯文本通信协议的扩展。 它提供了一种将纯文本连接升级为加密（TLS 或 SSL）连接的方法，而不是使用单独的端口进行加密通信。 为此，一些协议使用名为`STARTTLS`的命令。 它主要旨在作为被动监视的对策。

`mailtrap_secured.py`

```py
#!/usr/bin/env 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 帐户。

```py
server.starttls() # Secure the connection

```

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

## 通过 SSL 发送邮件

以下示例通过 SSL 发送电子邮件。 使用了 Web 托管 SMTP 服务器（来自 websupport.sk）。

`send_mail_ssl.py`

```py
#!/usr/bin/env 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`模块发送电子邮件。

您可能也对以下相关教程感兴趣： [Django 电子邮件教程](/django/email/)， [Python Jinja 教程](/python/jinja/)和 [Python 教程](/lang/python/)，或列出[所有 Python 教程](/all/#python)。