21.17. 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操作的完整系列的方法。如果给出了可选的主机和端口参数,则在初始化期间使用这些参数调用SMTPconnect()
方法。如果指定,local_hostname 将用作HELO/EHLO命令中本地主机的FQDN。否则,使用socket.getfqdn()
找到本地主机名。如果connect()
调用返回除成功代码以外的任何东西,则引发SMTPConnectError
。可选的 timeout 参数指定阻塞操作(如连接尝试)的超时(以秒为单位)(如果未指定,将使用全局默认超时设置)。如果超时到期,则提高socket.timeout
。可选的source_address参数允许绑定到具有多个网络接口和/或某个特定源TCP端口的机器中的某个特定源地址。它需要一个2元组(主机,端口),套接字绑定为其源地址,然后连接。如果省略(或者如果主机或端口分别是''
和/或0),将使用操作系统默认行为。对于正常使用,您只需要初始化/连接,
sendmail()
和quit()
方法。下面包含一个例子。SMTP
类支持with
语句。当这样使用时,当with
语句退出时,将自动发出SMTPQUIT
命令。例如。:>>> from smtplib import SMTP >>> with SMTP("domain.org") as smtp: ... smtp.noop() ... (250, b'Ok') >>>
在 3.3 版更改: 增加了对
with
声明的支持。在 3.3 版更改: source_address参数。
3.5 新版功能: 现在支持SMTPUTF8扩展(RFC 6531)。
-
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 为零,则使用标准的SMTP SSL over SSL端口(465)。可选参数 local_hostname,timeout 和 source_address 具有与它们在SMTP
类中相同的含义。 context 也是可选的,可以包含SSLContext
,并允许配置安全连接的各个方面。请阅读 安全注意事项 的最佳做法。keyfile 和 certfile 是 context 的传统替代,可以指向用于SSL连接的PEM格式的私钥和证书链文件。
在 3.3 版更改: 加入 context。
在 3.3 版更改: source_address参数。
在 3.4 版更改: 该类现在支持使用
ssl.SSLContext.check_hostname
和 服务器名称指示 进行主机名检查(请参阅ssl.HAS_SNI
)。3.6 版后已移除: keyfile 和 certfile 不赞成使用 context。请使用
ssl.SSLContext.load_cert_chain()
,或者让ssl.create_default_context()
为您选择系统的受信任的CA证书。
-
class
smtplib.
LMTP
(host='', port=LMTP_PORT, local_hostname=None, source_address=None)¶ LMTP协议非常类似于ESMTP,主要基于标准的SMTP客户端。通常使用Unix套接字为LMTP,所以我们的
connect()
方法必须支持,以及一个常规的主机:端口服务器。可选参数local_hostname和source_address具有与它们在SMTP
类中相同的含义。要指定Unix套接字,必须使用 host 的绝对路径,以“/”开头。支持使用常规SMTP机制的认证。当使用Unix套接字时,LMTP通常不支持或需要任何身份验证,但您的里程可能会有所不同。
一个很好的异常选择也被定义:
-
exception
smtplib.
SMTPException
¶ OSError
的子类,它是此模块提供的所有其他异常的基本异常类。在 3.4 版更改: SMTPException成为
OSError
的子类
-
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验证失败。很可能服务器不接受提供的用户名/密码组合。
参见
21.17.1. SMTP对象¶
SMTP
实例具有以下方法:
-
SMTP.
set_debuglevel
(level)¶ 设置调试输出电平。对于 level,值为1或
True
会导致连接的调试消息以及发送到服务器和从服务器接收的所有消息。 level 的值为2导致这些消息带有时间戳。在 3.5 版更改: 添加了调试级别2。
-
SMTP.
docmd
(cmd, args='')¶ 向服务器发送命令 cmd。可选参数 args 简单地连接到命令,用空格分隔。
这将返回由数字响应代码和实际响应行组成的2元组(多行响应合并为一个长行。)
在正常操作中,不必显式调用此方法。它用于实现其他方法,可能对测试专用扩展有用。
如果在等待答复时失去与服务器的连接,则会引发
SMTPServerDisconnected
。
-
SMTP.
connect
(host='localhost', port=0)¶ 连接到给定端口上的主机。默认值是在标准SMTP端口(25)连接到本地主机。如果主机名以冒号(
':'
)结尾,后跟一个数字,则该后缀将被删除,并将该数字解释为要使用的端口号。如果在实例化期间指定了主机,则此方法由构造函数自动调用。返回服务器在其连接响应中发送的响应代码和消息的2元组。
-
SMTP.
helo
(name='')¶ 使用
HELO
向SMTP服务器标识自己。 hostname参数默认为本地主机的完全限定域名。服务器返回的消息将作为对象的helo_resp
属性存储。在正常操作中,不必显式调用此方法。必要时,
sendmail()
将隐含地调用它。
-
SMTP.
ehlo
(name='')¶ 使用
EHLO
向ESMTP服务器标识自己。 hostname参数默认为本地主机的完全限定域名。检查ESMTP选项的响应,并将其存储以供has_extn()
使用。还设置几个信息属性:服务器返回的消息存储为ehlo_resp
属性,does_esmtp
设置为真或假,取决于服务器是否支持ESMTP,esmtp_features
将是包含SMTP服务扩展的名称的字典此服务器支持及其参数(如果有)。除非您希望在发送邮件之前使用
has_extn()
,否则不需要明确调用此方法。必要时,它将被sendmail()
隐式调用。
-
SMTP.
ehlo_or_helo_if_needed
()¶ 如果没有以前的
EHLO
或HELO
命令此会话,此方法调用ehlo()
和/或helo()
。它首先尝试ESMTPEHLO
。SMTPHeloError
服务器未正确回复
HELO
问候语。
-
SMTP.
verify
(address)¶ 使用SMTP
VRFY
检查此服务器上的地址的有效性。如果用户地址有效,则返回由代码250和完整 RFC 822 地址(包括人名)组成的元组。否则返回400或更大的SMTP错误代码和错误字符串。注解
许多网站禁用SMTP
VRFY
以挫败垃圾邮件发送者。
-
SMTP.
login
(user, password, *, initial_response_ok=True)¶ 登录需要验证的SMTP服务器。参数是要认证的用户名和密码。如果没有以前的
EHLO
或HELO
命令此会话,此方法首先尝试ESMTPEHLO
。如果身份验证成功,此方法将正常返回,或可能引发以下异常:SMTPHeloError
服务器未正确回复
HELO
问候语。SMTPAuthenticationError
服务器不接受用户名/密码组合。
SMTPNotSupportedError
服务器不支持
AUTH
命令。SMTPException
未找到合适的身份验证方法。
如果
smtplib
支持的每个认证方法如果被通告为由服务器支持,则依次尝试。有关支持的身份验证方法的列表,请参阅auth()
。 initial_response_ok 传递到auth()
。可选关键字参数 initial_response_ok 指定对于支持它的身份验证方法,可以与
AUTH
命令一起发送 RFC 4954 中指定的“初始响应”,而不是要求挑战/响应。在 3.5 版更改: 可能会引发
SMTPNotSupportedError
,并添加 initial_response_ok 参数。
-
SMTP.
auth
(mechanism, authobject, *, initial_response_ok=True)¶ 对指定的认证 mechanism 发出
SMTP
AUTH
命令,并通过 authobject 处理质询响应。mechanism 指定将哪个认证机制用作
AUTH
命令的参数;有效值是在esmtp_features
的auth
元素中列出的那些。authobject 必须是一个可调用对象接受可选的单个参数:
data = authobject(challenge = None)
如果可选的关键字参数 initial_response_ok 为真,
authobject()
将首先被调用没有参数。它可以返回 RFC 4954 “初始响应”字节,它将被编码并与AUTH
命令一起发送,如下所示。如果authobject()
不支持初始响应(例如,因为它需要挑战),则当用challenge=None
调用时应当返回None
。如果 initial_response_ok 为假,则authobject()
不会首先被调用None
。如果初始响应检查返回
None
,或者如果 initial_response_ok 为假,则将调用authobject()
来处理服务器的质询响应;它通过的 challenge 参数将是bytes
。它应该返回将被base64编码并发送到服务器的bytes
data。SMTP
类为CRAM-MD5
,PLAIN
和LOGIN
机制提供authobjects
;它们分别命名为SMTP.auth_cram_md5
,SMTP.auth_plain
和SMTP.auth_login
。它们都要求将SMTP
实例的user
和password
属性设置为适当的值。用户代码通常不需要直接调用
auth
,而是可以调用login()
方法,它将按照列出的顺序轮流尝试上述每个机制。auth
被暴露以促进未(或尚未)由smtplib
直接支持的认证方法的实现。3.5 新版功能.
-
SMTP.
starttls
(keyfile=None, certfile=None, context=None)¶ 将SMTP连接设置为TLS(传输层安全)模式。随后的所有SMTP命令将被加密。然后您应该再次呼叫
ehlo()
。如果提供了 keyfile 和 certfile,则将这些传递给
socket
模块的ssl()
功能。可选 context 参数是
ssl.SSLContext
对象;这是使用密钥文件和证书文件的替代方法,如果指定 keyfile 和 certfile 应为None
。如果没有以前的
EHLO
或HELO
命令此会话,此方法首先尝试ESMTPEHLO
。SMTPHeloError
服务器未正确回复
HELO
问候语。SMTPNotSupportedError
服务器不支持STARTTLS扩展。
RuntimeError
SSL/TLS支持不适用于您的Python解释器。
在 3.3 版更改: 加入 context。
在 3.4 版更改: 该方法现在支持使用
SSLContext.check_hostname
和 服务器名称指示符 进行主机名检查(请参阅HAS_SNI
)。在 3.5 版更改: 由于缺少STARTTLS支持而引起的错误现在是
SMTPNotSupportedError
子类,而不是基本SMTPException
。
-
SMTP.
sendmail
(from_addr, to_addrs, msg, mail_options=[], rcpt_options=[])¶ 发送邮件。所需的参数是 RFC 822 来自地址字符串,RFC 822 到地址字符串列表(裸字符串将被视为具有1个地址的列表)和消息字符串。呼叫者可以将要在
MAIL FROM
命令中使用的ESMTP选项(例如8bitmime
)的列表传递为 mail_options。应该与所有RCPT
命令一起使用的ESMTP选项(例如DSN
命令)可以作为 rcpt_options 传递。 (如果您需要对不同的收件人使用不同的ESMTP选项,则必须使用低级方法(例如mail()
,rcpt()
和data()
)来发送邮件。)注解
from_addr 和 to_addrs 参数用于构造传输代理使用的消息包络。
sendmail
不以任何方式修改消息头。msg 可以是包含ASCII范围中的字符的字符串,也可以是字节字符串。使用ascii编解码器将字符串编码为字节,并将单个
\r
和\n
字符转换为\r\n
字符。不修改字节字符串。如果没有以前的
EHLO
或HELO
命令此会话,此方法首先尝试ESMTPEHLO
。如果服务器执行ESMTP,消息大小和每个指定的选项将被传递给它(如果该选项在服务器发布的功能集中)。如果EHLO
失败,将尝试HELO
并抑制ESMTP选项。如果至少有一个收件人接受邮件,此方法将正常返回。否则会引发异常。也就是说,如果这个方法不引发异常,那么有人应该得到你的邮件。如果此方法不引发异常,它将返回一个字典,其中每个收件人的一个条目被拒绝。每个条目包含SMTP错误代码的元组和服务器发送的附带的错误消息。
如果
SMTPUTF8
包含在 mail_options 中,并且服务器支持它,则 from_addr 和 to_addrs 可能包含非ASCII字符。此方法可能会引发以下异常:
SMTPRecipientsRefused
所有收件人都被拒绝。没有人收到邮件。异常对象的
recipients
属性是一个字典,其中包含有关被拒绝的收件人的信息(例如至少一个收件人被接受时返回的收件人)。SMTPHeloError
服务器未正确回复
HELO
问候语。SMTPSenderRefused
服务器不接受 from_addr。
SMTPDataError
服务器回复了意外的错误代码(除了收件人拒绝)。
SMTPNotSupportedError
SMTPUTF8
在 mail_options 中给出,但服务器不支持。
除非另有说明,否则即使发生异常也将打开连接。
在 3.2 版更改: msg 可以是字节字符串。
在 3.5 版更改:
SMTPUTF8
支持已添加,如果指定了SMTPUTF8
但服务器不支持SMTPNotSupportedError
,则可能引发SMTPNotSupportedError
。
-
SMTP.
send_message
(msg, from_addr=None, to_addrs=None, mail_options=[], rcpt_options=[])¶ 这是一个方便的方法,用于用由
email.message.Message
对象表示的消息调用sendmail()
。参数具有与sendmail()
相同的含义,除了 msg 是Message
对象。如果 from_addr 是
None
或 to_addrs 是None
,则send_message
使用从 RFC 5322 中指定的从 msg 的报头提取的地址填充那些参数:如果 Sender 字段存在,则将 from_addr 设置为 Sender 字段,否则将其设置到 From 字段。 to_addrs 组合来自 msg 的 To,Cc 和 Bcc 字段的值(如果有的话)。如果消息中只出现一组 Resent-* 头,那么将忽略常规头,而是使用 Resent-* 头。如果消息包含多于一组 Resent-* 报头,则引发ValueError
,因为没有办法明确地检测最近的一组 Resent- 报头。send_message
使用BytesGenerator
以\r\n
作为 linesep 来序列化 msg,并且调用sendmail()
来发送结果消息。不管 from_addr 和 to_addrs 的值如何,send_message
不发送可能出现在 msg 中的任何 Bcc 或 Resent-Bcc 报头。如果 from_addr 和 to_addrs 中的任何地址包含非ASCII字符,并且服务器不通告SMTPUTF8
支持,则会引发SMTPNotSupported
错误。否则,将Message
与其utf8
属性设置为True
的policy
的克隆序列化,并将SMTPUTF8
和BODY=8BITMIME
添加到 mail_options。3.2 新版功能.
3.5 新版功能: 支持国际化地址(
SMTPUTF8
)。
-
SMTP.
quit
()¶ 终止SMTP会话并关闭连接。返回SMTP
QUIT
命令的结果。
还支持对应于标准SMTP/ESMTP命令 HELP
,RSET
,NOOP
,MAIL
,RCPT
和 DATA
的低级方法。通常这些不需要直接调用,因此在这里没有记录。有关详细信息,请参阅模块代码。
21.17.2. SMTP示例¶
此示例提示用户邮件信封(“收件人”和“发件人”地址)中所需的地址以及要递送的邮件。请注意,消息中包含的标头必须包含在输入的消息中;此示例不对 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
包的功能来构造电子邮件,然后您可以通过 send_message()
发送;见 email:示例。