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 都被养大了。可选的 超时 参数指定阻塞操作(如连接尝试)的超时时间(以秒为单位)(如果未指定,将使用全局默认超时设置)。如果超时到期, TimeoutError 都被养大了。可选的SOURCE_ADDRESS参数允许绑定到具有多个网络接口的计算机中的某个特定源地址,和/或绑定到某个特定源TCP端口。它在连接之前将套接字要绑定到的2元组(主机、端口)作为其源地址。如果省略(或如果主机或端口 '' 和/或0)将使用OS默认行为。

对于正常使用,只需要初始化/连接, sendmail()SMTP.quit() 方法。下面包含一个示例。

这个 SMTP 类支持 with 语句。当这样使用时,SMTP QUITwith 语句退出。例如。::

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

提出一个 auditing event smtplib.send 带着论据 selfdata .

在 3.3 版更改: 支持 with 语句已添加。

在 3.3 版更改: 已添加源地址参数。

3.5 新版功能: smtputf8扩展 (RFC 6531 )现在支持。

在 3.9 版更改: 如果 超时 参数设置为零,它将引发 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 应该用于需要从连接开始到使用 starttls() 不合适。如果 host 未指定,将使用本地主机。如果 port 为零,将使用标准的通过SSL端口(465)的SMTP。可选参数 local_hostnametimeoutsource_address 和他们在 SMTP 类。 context ,也是可选的,可以包含 SSLContext 并允许配置安全连接的各个方面。请阅读 安全注意事项 最佳实践。

关键文件证书文件 是传统的替代品 context ,并可以指向用于SSL连接的PEM格式的私钥和证书链文件。

在 3.3 版更改: context 加入。

在 3.3 版更改: 已添加源地址参数。

在 3.4 版更改: 类现在支持主机名检查 ssl.SSLContext.check_hostname服务器名称指示 (见 ssl.HAS_SNI

3.6 版后已移除: 关键文件证书文件 被否决,赞成 context . 请使用 ssl.SSLContext.load_cert_chain() 相反,还是让 ssl.create_default_context() 为您选择系统的可信CA证书。

在 3.9 版更改: 如果 超时 参数设置为零,它将引发 ValueError 防止创建非阻塞套接字

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

与esmtp非常相似的lmtp协议主要基于标准的smtp客户机。在lmtp中使用unix套接字是很常见的,因此 connect() 方法必须和常规的主机:端口服务器一样支持它。可选参数local_hostname和source_address的含义与 SMTP 类。要指定Unix套接字,必须使用绝对路径 host ,以“/”开头。

使用常规的SMTP机制支持身份验证。使用Unix套接字时,lmtp通常不支持或不需要任何身份验证,但您的里程数可能会有所不同。

在 3.9 版更改: 可选的 超时 已添加参数。

还定义了一个很好的例外选择:

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的模型、操作过程和协议详细信息。

RFC 1869 -SMTP服务扩展

SMTP的ESMTP扩展的定义。这描述了使用新命令扩展SMTP的框架,支持动态发现服务器提供的命令,并定义了一些附加命令。

SMTP对象

SMTP 实例具有以下方法:

SMTP.set_debuglevel(level)

设置调试输出级别。值为1或 True 对于 level 为连接和从服务器发送和接收的所有消息生成调试消息。值为2 level 导致这些消息被时间戳。

在 3.5 版更改: 添加了调试级别2。

SMTP.docmd(cmd, args='')

发送命令 cmd 到服务器。可选参数 args 只是连接到命令,用空格分隔。

这将返回一个由数字响应代码和实际响应行组成的2元组(多行响应合并为一条长线)。

在正常操作中,不需要显式调用此方法。它用于实现其他方法,可能对测试私有扩展很有用。

如果在等待答复时与服务器的连接丢失, SMTPServerDisconnected 将被引发。

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

连接到给定端口上的主机。默认值是在标准SMTP端口(25)上连接到本地主机。如果主机名以冒号结尾 (':' )后面跟着一个数字,这个后缀将被去掉,这个数字被解释为要使用的端口号。如果在实例化期间指定了主机,则构造函数将自动调用此方法。返回服务器在其连接响应中发送的响应代码和消息的2元组。

提出一个 auditing event smtplib.connect 带着论据 selfhostport .

SMTP.helo(name='')

在SMTP服务器上使用 HELO . host name参数默认为本地主机的完全限定域名。服务器返回的消息存储为 helo_resp 对象的属性。

在正常操作中,不需要显式调用此方法。它将由 sendmail() 必要时。

SMTP.ehlo(name='')

在ESMTP服务器上使用 EHLO . host name参数默认为本地主机的完全限定域名。检查ESMTP选项的响应,并将其存储以供使用 has_extn() . 还设置了几个信息属性:服务器返回的消息存储为 ehlo_resp 属性, does_esmtp 设置为 TrueFalse 取决于服务器是否支持ESMTP,以及 esmtp_features 将是包含此服务器支持的SMTP服务扩展名及其参数(如果有)的字典。

除非你想用 has_extn() 在发送邮件之前,不需要显式调用此方法。它将由 sendmail() 必要时。

SMTP.ehlo_or_helo_if_needed()

此方法调用 ehlo() 和/或 helo() 如果以前没有 EHLOHELO 命令此会话。它尝试ESMTP EHLO 第一。

SMTPHeloError

服务器没有正确答复 HELO 招呼。

SMTP.has_extn(name)

返回 True 如果 name 在服务器返回的一组SMTP服务扩展中, False 否则。忽略案例。

SMTP.verify(address)

使用SMTP检查此服务器上地址的有效性 VRFY . 返回由代码250和完整的 RFC 822 地址(包括人名),如果用户地址有效。否则,返回一个大于或等于400的SMTP错误代码和一个错误字符串。

注解

许多站点禁用SMTP VRFY 为了阻止垃圾邮件发送者。

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

登录需要身份验证的SMTP服务器。参数是要进行身份验证的用户名和密码。如果以前没有 EHLOHELO 命令此会话,此方法尝试esmtp EHLO 第一。如果验证成功,此方法将正常返回,或者可能引发以下异常:

SMTPHeloError

服务器没有正确答复 HELO 招呼。

SMTPAuthenticationError

服务器不接受用户名/密码组合。

SMTPNotSupportedError

这个 AUTH 服务器不支持命令。

SMTPException

找不到合适的身份验证方法。

支持的每个身份验证方法 smtplib 如果按服务器支持的方式发布,则依次尝试。见 auth() 获取支持的身份验证方法列表。 initial_response_ok 传递给 auth() .

可选关键字参数 initial_response_ok 指定对于支持它的身份验证方法,是否如中指定的“初始响应” RFC 4954 可以随 AUTH 命令,而不是要求挑战/响应。

在 3.5 版更改: SMTPNotSupportedError 可能会被引发, initial_response_ok 已添加参数。

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

发行一个 SMTP AUTH 用于指定身份验证的命令 机制 ,并通过 Auto对象 .

机制 指定要用作的参数的身份验证机制 AUTH 命令;有效值是 auth 元素 esmtp_features .

Auto对象 必须是接受可选单个参数的可调用对象:

数据=AuthObject(挑战=无)

if可选关键字参数 initial_response_ok 是真的, authobject() 将在没有参数的情况下首先调用。它可以返回 RFC 4954 “初始响应”ASCII str 它将被编码并与 AUTH 命令如下。如果 authobject() 不支持初始响应(例如,因为它需要一个挑战),它应该返回 None 当与调用时 challenge=None . 如果 initial_response_ok 是假的,那么 authobject() 不会先调用给 None .

如果初始响应检查返回 None ,或者,如果 initial_response_ok authobject() 将被调用以处理服务器的质询响应;将 挑战 传递的参数将是 bytes . 它应该返回ASCII str data 它将被base64编码并发送到服务器。

这个 SMTP 类提供 authobjects 对于 CRAM-MD5PLAINLOGIN 机制;它们被命名为 SMTP.auth_cram_md5SMTP.auth_plainSMTP.auth_login 分别。他们都要求 userpassword 的属性 SMTP 实例被设置为适当的值。

用户代码通常不需要调用 auth 直接,但可以调用 login() 方法,将按列出的顺序依次尝试上述每个机制。 auth 是为了方便实现认证方法而公开的,这些方法还没有(或还没有)得到直接支持 smtplib .

3.5 新版功能.

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

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

如果 关键文件证书文件 它们用于创建 ssl.SSLContext .

可选的 context 参数是 ssl.SSLContext 对象;这是使用keyfile和certfile的替代方法,如果同时指定了这两者 关键文件证书文件 应该是 None .

如果以前没有 EHLOHELO 命令此会话,此方法尝试esmtp EHLO 第一。

3.6 版后已移除: 关键文件证书文件 被否决,赞成 context . 请使用 ssl.SSLContext.load_cert_chain() 相反,还是让 ssl.create_default_context() 为您选择系统的可信CA证书。

SMTPHeloError

服务器没有正确答复 HELO 招呼。

SMTPNotSupportedError

服务器不支持StartTLS扩展。

RuntimeError

您的python解释器不支持ssl/tls。

在 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个地址的列表)和消息字符串。调用者可以传递ESMTP选项列表(例如 8bitmime )用于 MAIL FROM 命令作为 mail_options . ESMTP选项(例如 DSN 命令)应与所有 RCPT 命令可以作为 rcpt_options . (如果需要对不同的收件人使用不同的ESMTP选项,则必须使用低级方法,例如 mail()rcpt()data() 发送消息。)

注解

这个 from_addrto_addrs 参数用于构造传输代理使用的消息信封。 sendmail 不以任何方式修改邮件头。

msg 可以是包含ASCII范围内字符的字符串,也可以是字节字符串。使用ASCII编解码器将字符串编码为字节,然后 \r\n 字符转换为 \r\n 字符。未修改字节字符串。

如果以前没有 EHLOHELO 命令此会话,此方法尝试esmtp EHLO 第一。如果服务器执行ESMTP,则消息大小和每个指定的选项都将传递给它(如果该选项在功能集中,则服务器将进行广告)。如果 EHLO 失败, HELO 将尝试并取消ESMTP选项。

如果至少有一个收件人接受了邮件,则此方法将正常返回。否则将引发异常。也就是说,如果此方法没有引发异常,那么应该有人收到您的邮件。如果此方法不引发异常,则返回字典,每个被拒绝的收件人都有一个条目。每个条目都包含一个由SMTP错误代码和服务器发送的附带错误消息组成的元组。

如果 SMTPUTF8 包含在 mail_options ,服务器支持它, from_addrto_addrs 可以包含非ASCII字符。

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

SMTPRecipientsRefused

所有收件人都被拒绝。没人收到邮件。这个 recipients exception对象的属性是一个字典,其中包含有关被拒绝的收件人的信息(就像至少一个收件人被接受时返回的字典)。

SMTPHeloError

服务器没有正确答复 HELO 招呼。

SMTPSenderRefused

服务器没有接受 from_addr .

SMTPDataError

服务器以意外错误代码(而不是拒绝收件人)答复。

SMTPNotSupportedError

SMTPUTF8 是在 mail_options 但服务器不支持。

除非另有说明,否则即使在引发异常之后,连接也将打开。

在 3.2 版更改: msg 可以是字节字符串。

在 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_addrNoneto_addrsNonesend_message 用从头中提取的地址填充这些参数 msg 如中所述 RFC 5322 : from_addr 设置为 Sender 字段(如果存在),否则为 From 字段。 to_addrs 组合的值(如果有) ToCcBcc 字段来自 msg . 如果只有一套 Resent-* 邮件中会出现邮件头,忽略常规邮件头,并且 Resent-* 而是使用头。如果消息包含多组 Resent-* 标题,A ValueError 是引发的,因为无法明确检测最新的 Resent- 标题。

send_message 序列化 msg 使用 BytesGenerator 具有 \r\n 作为 linesep 和调用 sendmail() 传送产生的信息。不管 from_addrto_addrssend_message 不传输任何 BccResent-Bcc 可能出现在 msg . 如果 from_addrto_addrs 包含非ASCII字符,服务器不公布 SMTPUTF8 支持 SMTPNotSupported 出现错误。否则 Message 使用其复制进行序列化 policyutf8 属性设置为 TrueSMTPUTF8BODY=8BITMIME 被添加到 mail_options .

3.2 新版功能.

3.5 新版功能: 支持国际化地址 (SMTPUTF8

SMTP.quit()

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

与标准的smtp/esmtp命令对应的低级方法 HELPRSETNOOPMAILRCPTDATA 也支持。通常,这些不需要直接调用,因此这里不记录它们。有关详细信息,请参阅模块代码。

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 实例 .