smtplib — SMTP (简单邮件传输协议) 客户端

源代码: Lib/smtplib.py


smtplib 模块定义 SMTP 客户端会话对象,可以用于将邮件发送给采用 SMTP 或 ESMTP 监听器守护程序的任何 Internet 机器。对于 SMTP 和 ESMTP 操作的细节,请翻阅 RFC 821 (简单邮件传输协议) 和 RFC 1869 (SMTP 服务扩展)。

class smtplib. SMTP ( host='' , port=0 , local_hostname=None , [ timeout , ] source_address=None )

SMTP 实例封装 SMTP 连接。它拥有支持 SMTP 和 ESMTP 操作的全部技能方法。若有给出可选主机和端口参数,SMTP connect() 方法被调用采用这些参数在初始化期间。若指定, local_hostname 在 HELO/EHLO 命令中被用作本地主机的 FQDN (完全合格域名)。否则,查找本地主机名使用 socket.getfqdn() 。若 connect() 调用返回任何内容除成功代码外, SMTPConnectError 被引发。可选 timeout 参数指定超时 (以秒为单位) 为阻塞像连接尝试操作 (若未指定,将使用全局默认超时设置)。若超时到期, socket.timeout 被引发。可选 source_address 参数允许绑定具有多个网络接口的机器的某个特定源地址,和/或某个特定源 TCP 端口。它接受 2 元组 (主机,端口),将套接字绑定作为其源地址在连接之前。若省略 (或者若主机或端口为 '' 和/或 0 分别) 将使用 OS 默认行为。

对于正常使用,应该仅要求初始化/连接, sendmail() ,和 SMTP.quit() 方法。包括下文范例。

SMTP 类支持 with 语句。当像这样使用时,SMTP QUIT 命令被自动发出当 with 语句退出。如:

>>> from smtplib import SMTP
>>> with SMTP("domain.org") as smtp:
...     smtp.noop()
...
(250, b'Ok')
>>>
									

所有命令将引发 审计事件 smtplib.SMTP.send 采用自变量 self and data ,其中 data 是即将发送给远程主机的字节。

3.3 版改变: 支持 with 语句被添加。

3.3 版改变: 添加 source_address 自变量。

3.5 版新增: SMTPUTF8 扩展 ( RFC 6531 ) 现在支持。

3.9 版改变: timeout 参数被设为 0,它将引发 ValueError 以阻止非阻塞套接字的创建

class smtplib. SMTP_SSL ( host='' , port=0 , local_hostname=None , keyfile=None , certfile=None , [ timeout , ] context=None , source_address=None )

SMTP_SSL 实例行为准确如同实例化的 SMTP . SMTP_SSL 应该用于从连接开始就要求 SSL 的情况且使用 starttls() 不合适。若 host 未指定,使用本地主机。若 port 为 0,使用标准 SMTP-over-SSL 端口 465。可选自变量 local_hostname , timeout and source_address 拥有的含义如同它们在 SMTP 类。 context ,也是可选的,可以包含 SSLContext 并允许配置安全连接的各个方面。请阅读 安全注意事项 了解最佳实践。

keyfile and certfile 是传统替代对于 context ,且可以指向用于 SSL 连接的 PEM 格式私钥和证书链文件。

3.3 版改变: context 被添加。

3.3 版改变: 添加 source_address 自变量。

3.4 版改变: 类现在支持主机名校验采用 ssl.SSLContext.check_hostname and SNI (服务器名称指示) (见 ssl.HAS_SNI ).

从 3.6 版起弃用: keyfile and certfile 弃用代之 context 。请使用 ssl.SSLContext.load_cert_chain() 代替,或让 ssl.create_default_context() 为您选择系统的受信任 CA 证书。

3.9 版改变: timeout 参数被设为 0,它将引发 ValueError 以阻止非阻塞套接字的创建

class smtplib. LMTP ( host='' , port=LMTP_PORT , local_hostname=None , source_address=None [ , timeout ] )

LMTP 协议非常类似于 ESMTP,重点基于标准 SMTP 客户端。很大程度上基于标准 SMTP 客户端。LMTP 使用 Unix 套接字很常见,因此 connect() 方法必须支持这及常规 host:port 服务器。可选自变量 local_hostname 和 source_address 拥有相同含义如它们在 SMTP 类。要指定 Unix 套接字,必须使用绝对路径对于 host ,采用 / 开头。

支持使用常规 SMTP 机制进行身份验证。当使用 Unix 套接字时,LMTP 一般不支持或不要求任何身份验证,但具体情况可能有所不同。

3.9 版改变: 可选 timeout 参数被添加。

还定义了一些不错异常:

exception smtplib. SMTPException

子类化的 OSError 这是由此模块提供的所有其它异常的基异常类。

3.4 版改变: SMTPException 变为子类化的 OSError

exception smtplib. SMTPServerDisconnected

此异常被引发当服务器意外断开连接,或试图使用 SMTP 实例在将其连接到服务器之前。

exception smtplib. SMTPResponseException

包括 SMTP 错误代码的所有异常基类。某些实例会生成这些异常当 SMTP 服务器返回错误代码时。错误代码存储在 smtp_code 属性对于错误,和 smtp_error 属性被设为错误消息。

exception smtplib. SMTPSenderRefused

发件人地址被拒。除了设置的属性对于所有 SMTPResponseException 异常,这会将 sender 设为 SMTP 服务器被拒的字符串。

exception smtplib. SMTPRecipientsRefused

所有收件人地址被拒。可以访问每个收件人错误透过属性 recipients ,这是准确相同的字典排序如 SMTP.sendmail() 返回。

exception smtplib. SMTPDataError

SMTP 服务器拒绝接受消息数据。

exception smtplib. SMTPConnectError

发生错误在与服务器建立连接期间。

exception smtplib. SMTPHeloError

服务器拒绝我们的 HELO 消息。

exception smtplib. SMTPNotSupportedError

命令或选项试图不被服务器所支持。

3.5 版新增。

exception smtplib. SMTPAuthenticationError

SMTP 身份验证出错。服务器很可能不接受提供的用户名/口令组合。

另请参阅

RFC 821 - SMTP (简单邮件传输协议)

SMTP 协议定义。此文档涵盖 SMTP 模型、操作过程及协议细节。

RFC 1869 - ESMTP (SMTP 服务扩展)

SMTP 的 ESMTP 扩展定义。这描述采用新的命令扩展 SMTP 框架,支持动态探索由服务器提供的命令,和定义一些额外命令。

SMTP 对象

SMTP 实例具有下列方法:

SMTP. set_debuglevel ( level )

设置调试输出级别。值为 1 或 True for level 结果在连接的调试消息及发送到和接收自服务器的所有消息。值为 2 对于 level 结果在带时间戳的这些消息。

3.5 版改变: 添加调试级别 2。

SMTP. docmd ( cmd , args='' )

发送命令 cmd 到服务器。可选自变量 args 简单串联命令,以空格分隔。

这返回由数值响应代码和实际响应行组成的 2 元组 (多行响应会拼接成一长行)。

在正常操作中,明确调用此方法应该不必要。它用于实现其它方法,且可能对测试私有扩展很有用。

若丢失服务器连接当等待回复时, SMTPServerDisconnected 会被引发。

SMTP. connect ( host='localhost' , port=0 )

连接到给出端口的主机。默认连接到本地主机在标准 SMTP 25 端口。若主机名结尾带冒号 ( ':' ) 后紧跟数字,将剥离该后缀和将数字解释为要使用的端口号。构造函数会自动援引此方法,若有指定主机在实例化期间。返回服务器在其连接响应中发送的 2 元组 (响应代码和消息)。

引发 审计事件 smtplib.connect 采用自变量 self , host , port .

SMTP. helo ( name='' )

标识自己到 SMTP 服务器使用 HELO 。主机名自变量默认为本地主机的完全合格域名。由服务器返回的消息被存储作为 helo_resp 属性对于对象。

在正常操作中,明确调用此方法应该不必要。它被隐式调用通过 sendmail() 当有必要时。

SMTP. ehlo ( name='' )

标识自己到 ESMTP 服务器使用 EHLO 。主机名自变量默认为本地主机的完全合格域名。审查 ESMTP 选项的响应并存储它们以供使用通过 has_extn() 。还设置了几个情报属性:由服务器返回的消息被存储作为 ehlo_resp 属性, does_esmtp 被设为 True 或 False 取决于服务器是否支持 ESMTP,和 esmtp_features 将是包含此服务器支持的 SMTP 服务扩展名称及其参数 (若有的话) 的字典。

除非希望使用 has_extn() 在发送邮件之前,明确调用此方法应该不必要。它被隐式调用通过 sendmail() 当有必要时。

SMTP. ehlo_or_helo_if_needed ( )

此方法调用 ehlo() and/or helo() 若先前没有 EHLO or HELO 命令此会话。它将尝试 ESMTP EHLO 首先。

SMTPHeloError

服务器没有正确回复 HELO 问候。

SMTP. has_extn ( name )

返回 True if name 在由服务器返回的一组 SMTP 服务扩展中, False 否则。大小写被忽略。

SMTP. verify ( address )

校验此服务器地址的有效性使用 SMTP VRFY 。返回的元组包含代码 250 和完整 RFC 822 地址 (包括人类姓名) 若用户地址有效。否则返回 400 或更大的 SMTP 错误代码和错误字符串。

注意

很多站点禁用 SMTP VRFY 为挫败垃圾邮件发送者。

SMTP. login ( user , password , * , initial_response_ok=True )

登录要求身份验证的 SMTP 服务器。参数是要进行身份验证的用户名和口令。若先前没有 EHLO or HELO 命令此会话,此方法将尝试 ESMTP EHLO 首先。此方法将正常返回若身份验证成功,或可能引发下列异常:

SMTPHeloError

服务器没有正确回复 HELO 问候。

SMTPAuthenticationError

服务器不接受用户名/口令组合。

SMTPNotSupportedError

AUTH 命令不被服务器支持。

SMTPException

模块未找到合适的身份验证方法。

每个身份验证方法的支持通过 smtplib 依次尝试若服务器有公布支持它们。见 auth() 了解身份验证支持的方法列表。 initial_response_ok 被传递给 auth() .

可选关键词自变量 initial_response_ok 对于支持它的身份验证方法,是否作为 initial response 有指定在 RFC 4954 可以被发送沿用 AUTH 命令,而不要求挑战/响应。

3.5 版改变: SMTPNotSupportedError 可以被引发,和 initial_response_ok 参数被添加。

SMTP. auth ( mechanism , authobject , * , initial_response_ok=True )

发出 SMTP AUTH 命令对于指定身份验证 mechanism ,和处理挑战响应凭借 authobject .

mechanism 指定使用哪种身份验证机制作为自变量对于 AUTH 命令;有效值列表于 auth 元素的 esmtp_features .

authobject 必须是接受可选单自变量的可调用对象:

data = authobject(challenge=None)

若可选关键词自变量 initial_response_ok 为 True, authobject() 将首先被调用没有自变量。它可以返回 RFC 4954 初始响应 ASCII str 将被编码并发送同 AUTH 命令见下文。若 authobject() 不支持初始响应 (如:因为它要求挑战),它应该返回 None 当被调用采用 challenge=None 。若 initial_response_ok 为 False,那么 authobject() 不会首先被调用采用 None .

若初始响应校验返回 None ,或者若 initial_response_ok 为 False, authobject() 将被调用以处理服务器的挑战响应; challenge 传递自变量将为 bytes 。它应该返回 ASCII str data 将是 base64 编码并发送给服务器。

SMTP 类提供 authobjects CRAM-MD5 , PLAIN ,和 LOGIN 机制;它们名为 SMTP.auth_cram_md5 , SMTP.auth_plain ,和 SMTP.auth_login 分别。它们都要求 user and password 特性对于 SMTP 实例被设为适当值。

用户代码通常不需要调用 auth 直接,相反可以调用 login() 方法,将按列出次序依次尝试上述每种机制。 auth 的暴露能促进不 (或尚未) 直接支持的身份验证方法的实现通过 smtplib .

3.5 版新增。

SMTP. starttls ( keyfile=None , certfile=None , context=None )

将 SMTP 连接置于 TLS (传输层安全) 模式。随后的所有 SMTP 命令将被加密。然后应该调用 ehlo() 再次。

keyfile and certfile 有提供,使用它们创建 ssl.SSLContext .

可选 context 参数为 ssl.SSLContext 对象;这是使用 keyfile 和 certfile 的替代,若指定 keyfile and certfile 应该为 None .

若先前没有 EHLO or HELO 命令此会话,此方法将尝试 ESMTP EHLO 首先。

从 3.6 版起弃用: keyfile and certfile 弃用代之 context 。请使用 ssl.SSLContext.load_cert_chain() 代替,或让 ssl.create_default_context() 为您选择系统的受信任 CA 证书。

SMTPHeloError

服务器没有正确回复 HELO 问候。

SMTPNotSupportedError

服务器不支持 STARTTLS 扩展。

RuntimeError

SSL/TLS 支持不可用于 Python 解释器。

3.3 版改变: context 被添加。

3.4 版改变: 方法现在支持主机名校验采用 SSLContext.check_hostname and SNI (服务器名称指示器) (见 HAS_SNI ).

3.5 版改变: 由于缺乏 STARTTLS 支持而引发的错误现在为 SMTPNotSupportedError 子类而不是基 SMTPException .

SMTP. sendmail ( from_addr , to_addrs , msg , mail_options=() , rcpt_options=() )

发送邮件。要求自变量为 RFC 822 from_addr 字符串,列表的 RFC 822 to_addr 字符串 (裸字符串将被视为具有 1 地址的列表) 和消息字符串。调用者可以传递 ESMTP 选项列表 (譬如 8bitmime ) 以用于 MAIL FROM 命令作为 mail_options 。ESMTP 选项 (譬如 DSN 命令) 应该用于所有 RCPT 命令可以传递作为 rcpt_options 。(若需要对不同收件人使用不同 ESMTP 选项,就必须使用低级方法,譬如 mail() , rcpt() and data() 以发送消息。)

注意

from_addr and to_addrs 参数用于构造传输代理所使用的消息信封。 sendmail 不会以任何方式修改消息 Header 头。

msg 可以是包含 ASCII 范围字符的字符串,或字节字符串。使用 ASCII 编解码器将字符串编码成字节,和单独 \r and \n 字符被转换成 \r\n 字符。不修改字节字符串。

若先前没有 EHLO or HELO 命令此会话,此方法将尝试 ESMTP EHLO 首先。若服务器执行 ESMTP,将把消息大小和每个指定选项传递给它 (若选项在服务器公布的特征集中)。若 EHLO 失败, HELO 将尝试并抑制 ESMTP 选项。

此方法将正常返回若至少一收件人接受邮件。否则会引发异常。也就是说,若此方法不引发异常,那么有人应该收到邮件。若此方法未引发异常,返回对于每个被拒绝的收件人是一条目的字典。每一条目包含元组 (SMTP 错误码,由服务器发送伴随的错误消息)。

SMTPUTF8 有包括在 mail_options ,且服务器支持它, from_addr and to_addrs 可能包含非 ASCII 字符。

此方法可能引发下列异常:

SMTPRecipientsRefused

所有收件人被拒绝。没有人收到邮件。 recipients 属性对于异常对象是包含有关被拒绝收件人信息的字典 (像某一返回的,当至少一收件人接受时)。

SMTPHeloError

服务器没有正确回复 HELO 问候。

SMTPSenderRefused

服务器不接受 from_addr .

SMTPDataError

服务器回复的意外错误代码 (除收件人拒绝外)。

SMTPNotSupportedError

SMTPUTF8 给定在 mail_options 但服务器不支持。

除非另有说明,连接会被打开即使引发异常。

3.2 版改变: msg 可以是 byte 字符串。

3.5 版改变: SMTPUTF8 支持被添加,和 SMTPNotSupportedError 可能被引发若 SMTPUTF8 有指定但服务器不支持。

SMTP. send_message ( msg , from_addr=None , to_addrs=None , mail_options=() , rcpt_options=() )

这是方便方法为调用 sendmail() 采用的消息表示通过 email.message.Message 对象。自变量有相同含义如同 sendmail() ,除了 msg Message 对象。

from_addr is None or to_addrs is None , send_message 填充这些自变量采用的提取地址来自 Header 头对于 msg 作为指定在 RFC 5322 : from_addr 被设为 Sender 字段若存在,否则被设为 From 字段。 to_addrs 组合值 (若有的话) 对于 To , Cc ,和 Bcc 字段从 msg 。若恰好有一组 Resent-* 头出现在消息中,常规 Header 头被忽略和 Resent-* 头被使用以取而代之。若消息包含多组 Resent-* 头, ValueError 被引发,由于没有办法明确检测到最近一组 Resent- 头。

send_message 序列化 msg 使用 BytesGenerator with \r\n 作为 linesep ,和调用 sendmail() 以传输结果消息。不管值 from_addr and to_addrs , send_message 不传输任何 Bcc or Resent-Bcc 头可能出现在 msg 。若任何地址在 from_addr and to_addrs 包含非 ASCII 字符和服务器未公布 SMTPUTF8 支持, SMTPNotSupported 错误被引发。否则 Message 被序列化具有克隆的其 policy 采用 utf8 属性设置为 True ,和 SMTPUTF8 and BODY=8BITMIME 被添加到 mail_options .

3.2 版新增。

3.5 版新增: 支持国际化地址 ( SMTPUTF8 ).

SMTP. quit ( )

终止 SMTP 会话并关闭连接。 返回的结果源于 SMTP QUIT 命令。

低级方法对应标准 SMTP/ESMTP 命令 HELP , RSET , NOOP , MAIL , RCPT ,和 DATA 也支持。通常不需要直接调用这些,所以这里未文档化它们。有关细节,请翻阅模块代码。

SMTP 范例

此范例提示用户输入消息信封所需的地址(To 和 From 地址) 和要交付的消息。注意,要包括在消息中的 Header 头还必须包括在键入消息中;此范例不做任何处理对于 RFC 822 头。尤其,To 和 From 地址必须明确包括在消息头中。

import smtplib
def prompt(prompt):
    return input(prompt).strip()
fromaddr = prompt("From: ")
toaddrs  = prompt("To: ").split()
print("Enter message, end with ^D (Unix) or ^Z (Windows):")
# Add the From: and To: headers at the start!
msg = ("From: %s\r\nTo: %s\r\n\r\n"
       % (fromaddr, ", ".join(toaddrs)))
while True:
    try:
        line = input()
    except EOFError:
        break
    if not line:
        break
    msg = msg + line
print("Message length is", len(msg))
server = smtplib.SMTP('localhost')
server.set_debuglevel(1)
server.sendmail(fromaddr, toaddrs, msg)
server.quit()
								

注意

通常,想要使用 email 包的特征来构造 Email 消息,那么可以发送它凭借 send_message() ;见 Email:范例 .