21.18. smtpd
— SMTP服务器¶
源代码: Lib/smtpd.py
此模块提供了几个类来实现SMTP(电子邮件)服务器。
存在几个服务器实现;一个是通用的无用的实现,可以被覆盖,而另外两个提供特定的邮件发送策略。
此外,SMTPChannel可以扩展为实现与SMTP客户端的非常具体的交互行为。
代码支持 RFC 5321,加上 RFC 1870 SIZE和 RFC 6531 SMTPUTF8扩展。
21.18.1. SMTPServer对象¶
-
class
smtpd.
SMTPServer
(localaddr, remoteaddr, data_size_limit=33554432, map=None, enable_SMTPUTF8=False, decode_data=False)¶ 创建一个新的
SMTPServer
对象,绑定到本地地址 localaddr。它将 remoteaddr 视为上游SMTP中继器。 localaddr 和 remoteaddr 都应该是 (主机,端口) 元组。对象从asyncore.dispatcher
继承,因此将在实例化时将自身插入到asyncore
的事件循环中。data_size_limit 指定将在
DATA
命令中接受的最大字节数。值None
或0
表示没有限制。map 是用于连接的套接字映射(最初为空的字典是一个合适的值)。如果未指定,则使用
asyncore
全局套接字映射。enable_SMTPUTF8 确定是否应该启用
SMTPUTF8
扩展(如 RFC 6531 中定义的)。默认值为False
。当True
,SMTPUTF8
被接受作为MAIL
命令的参数并且当存在时被传递到kwargs['mail_options']
列表中的process_message()
。 decode_data 和 enable_SMTPUTF8 不能同时设置为True
。decode_data 指定是否应使用UTF-8解码SMTP事务的数据部分。当 decode_data 为
False
(默认值)时,服务器通告8BITMIME
扩展(RFC 6152),接受BODY=8BITMIME
参数给MAIL
命令,当存在时将其传递给kwargs['mail_options']
列表中的process_message()
。 decode_data 和 enable_SMTPUTF8 不能同时设置为True
。-
process_message
(peer, mailfrom, rcpttos, data, **kwargs)¶ 引发
NotImplementedError
异常。覆盖这个在子类中做一些有用的消息。无论在构造函数中作为 remoteaddr 传递什么都将作为_remoteaddr
属性可用。 peer 是远程主机的地址,mailfrom 是包络发送者,rcpttos 是包络收件人,data 是包含电子邮件内容的字符串(应为 RFC 5321 格式)。如果 decode_data constructor关键字设置为
True
,则 data 参数将是一个unicode字符串。如果设置为False
,它将是一个字节对象。kwargs 是包含附加信息的字典。如果
decode_data=True
作为init参数,则它为空,否则它包含以下键:- mail_options:
MAIL
命令的所有接收的参数的列表(元素是大写字符串;例如:['BODY=8BITMIME', 'SMTPUTF8']
)。- rcpt_options:
与 mail_options 相同,但用于
RCPT
命令。目前没有支持RCPT TO
选项,因此现在这将始终是一个空列表。
process_message
的实现应该使用**kwargs
签名接受任意关键字参数,因为未来的功能增强可能会向kwargs字典添加键。返回
None
以请求正常的250 Ok
响应;否则返回 RFC 5321 格式的所需响应字符串。
-
channel_class
¶ 在子类中覆盖此项以使用自定义
SMTPChannel
来管理SMTP客户端。
3.4 新版功能: map 构造函数参数。
在 3.5 版更改: localaddr 和 remoteaddr 现在可以包含IPv6地址。
3.5 新版功能: decode_data 和 enable_SMTPUTF8 构造函数参数,当 decode_data 为
False
时,kwargs 参数为process_message()
。在 3.6 版更改: 默认情况下,decode_data 现在是
False
。-
21.18.2. DebuggingServer对象¶
-
class
smtpd.
DebuggingServer
(localaddr, remoteaddr)¶ 创建新的调试服务器。参数根据
SMTPServer
。消息将被丢弃,并打印在stdout上。
21.18.3. PureProxy对象¶
-
class
smtpd.
PureProxy
(localaddr, remoteaddr)¶ 创建一个新的纯代理服务器。参数根据
SMTPServer
。一切都将被传递到 remoteaddr。注意,运行这个有一个很好的机会,使你成为一个开放的中继,所以请小心。
21.18.4. MailmanProxy对象¶
-
class
smtpd.
MailmanProxy
(localaddr, remoteaddr)¶ 创建一个新的纯代理服务器。参数根据
SMTPServer
。一切都将被转发到 remoteaddr,除非本地mailman配置知道地址,在这种情况下它将通过邮递员处理。注意,运行这个有一个很好的机会,使你成为一个开放的中继,所以请小心。
21.18.5. SMTPChannel对象¶
-
class
smtpd.
SMTPChannel
(server, conn, addr, data_size_limit=33554432, map=None, enable_SMTPUTF8=False, decode_data=False)¶ 创建一个新的
SMTPChannel
对象,用于管理服务器和单个SMTP客户端之间的通信。conn 和 addr 是根据下面描述的实例变量。
data_size_limit 指定将在
DATA
命令中接受的最大字节数。值None
或0
表示没有限制。enable_SMTPUTF8 确定是否应该启用
SMTPUTF8
扩展(如 RFC 6531 中定义的)。默认值为False
。 decode_data 和 enable_SMTPUTF8 不能同时设置为True
。可以在 map 中指定字典,以避免使用全局套接字映射。
decode_data 指定是否应使用UTF-8解码SMTP事务的数据部分。默认值为
False
。 decode_data 和 enable_SMTPUTF8 不能同时设置为True
。要使用自定义SMTPChannel实现,您需要覆盖
SMTPServer
的SMTPServer.channel_class
。在 3.5 版更改: 添加 decode_data 和 enable_SMTPUTF8 参数。
在 3.6 版更改: 默认情况下,decode_data 现在是
False
。SMTPChannel
有以下实例变量:-
smtp_server
¶ 保存生成此频道的
SMTPServer
。
-
conn
¶ 保存连接到客户端的套接字对象。
-
addr
¶ 保存客户端的地址,
socket.accept
返回的第二个值
-
received_lines
¶ 保存从客户端接收的行字符串(使用UTF-8解码)的列表。线路的
"\r\n"
线结束翻译为"\n"
。
-
smtp_state
¶ 保持通道的当前状态。这将是最初的
COMMAND
,然后客户端发送“DATA”行之后的DATA
。
-
seen_greeting
¶ 在其“帮助”中保存由客户端发送的包含问候语的字符串。
-
mailfrom
¶ 保留一个字符串,其中包含来自客户端的“MAIL FROM:”行中标识的地址。
-
rcpttos
¶ 保存来自客户端的包含在“RCPT TO:”行中标识的地址的字符串列表。
-
received_data
¶ 保存包含在DATA状态期间由客户端发送的所有数据的字符串,直到但不包括终止
"\r\n.\r\n"
。
-
fqdn
¶ 保存
socket.getfqdn()
返回的服务器的完全限定域名。
SMTPChannel
通过在从客户端接收到命令行时调用名为smtp_<command>
的方法来操作。内置在基本SMTPChannel
类中的是用于处理以下命令(并适当地响应它们)的方法:命令
所采取的行动
HELO
接受客户端的问候语并将其存储在
seen_greeting
中。将服务器设置为基本命令模式。EHLO
接受客户端的问候语并将其存储在
seen_greeting
中。将服务器设置为扩展命令模式。NOOP
不采取任何行动。
放弃
干净地关闭连接。
邮件
接受“MAIL FROM:”语法,并将提供的地址存储为
mailfrom
。在扩展命令模式下,接受 RFC 1870 SIZE属性,并根据 data_size_limit 的值适当响应。RCPT
接受“RCPT TO:”语法,并将提供的地址存储在
rcpttos
列表中。RSET
重置
mailfrom
,rcpttos
和received_data
,但不是问候语。数据
将内部状态设置为
DATA
,并将来自客户端的其余行存储在received_data
中,直到接收到终止符"\r\n.\r\n"
。帮帮我
返回有关命令语法的最少信息
VRFY
返回代码252(服务器不知道地址是否有效)
EXPN
报告命令未实现。
-