On this page
smtpd-SMTP 服务器
源代码: Lib/smtpd.py
该模块提供了几个类来实现 SMTP(电子邮件)服务器。
存在几种服务器实施方式。一种是通用的什么都不做的实现,可以将其重写,而其他两种则提供特定的邮件发送策略。
另外,可以扩展 SMTPChannel 以实现与 SMTPClient 端的非常特定的交互行为。
该代码支持 RFC 5321,以及 RFC 1870 SIZE 和 RFC 6531 SMTPUTF8extensions。
SMTPServer Objects
-
- class *
smtpd.
SMTPServer
(* localaddr , remoteaddr , data_size_limit = 33554432 , map = None , enable_SMTPUTF8 = False , decode_data = False *)
- 创建一个新的SMTPServer对象,该对象绑定到本地地址* localaddr 。它将 remoteaddr *视为上游 SMTP 中继器。 * localaddr 和 remoteaddr *应该都是(host, port)Tuples。该对象继承自asyncore.dispatcher,因此将在实例化时将自身插入asyncore的事件循环中。
- class *
data_size_limit *指定
DATA
命令将接受的最大字节数。值None
或0
表示没有限制。map *是用于连接的套接字 Map(最初为空的字典是合适的值)。如果未指定,则使用asyncore全局套接字 Map。
enable_SMTPUTF8 *确定是否应启用
SMTPUTF8
extensions(在 RFC 6531中定义)。默认值为False
。当True
时,将SMTPUTF8
接受为MAIL
命令的参数,当存在时将SMTPUTF8
传递给kwargs['mail_options']
列表中的process_message()。 * decode_data 和 enable_SMTPUTF8 *不能同时设置为True
。decode_data 指定是否应使用 UTF-8 解码 SMTP 事务的数据部分。当 decode_data *为
False
(默认值)时,服务器将发布8BITMIME
extensions( 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格式)。
- 引发NotImplementedError异常。在子类中重写此内容,以对此消息执行一些有用的操作。无论在构造函数中作为* remoteaddr *传递的内容,都可以用作
如果* decode_data 构造函数关键字设置为True
,则 data *参数将是 unicode 字符串。如果将其设置为False
,它将是一个字节对象。
- kwargs *是包含其他信息的字典。如果将
decode_data=True
作为 init 参数给出,则为空,否则包含以下键:
Note
mail_options :
a list of all received parameters to the
MAIL
command (the elements are uppercase strings; example:['BODY=8BITMIME', 'SMTPUTF8']
).rcpt_options :
与* mail_options *相同,但适用于
RCPT
命令。当前不支持RCPT TO
选项,因此,此列表始终为空。
process_message
的实现应使用**kwargs
签名来接受任意关键字参数,因为将来的Function增强可能会向 kwargs 字典添加键。
返回None
以请求正常的250 Ok
响应;否则,以 RFC 5321格式返回所需的响应字符串。
channel_class
- 在子类中对此进行重写,以使用自定义SMTPChannel来 ManagementSMTPClient 端。
3.4 版中的新Function:* map *构造函数参数。
在版本 3.5 中进行了更改:* localaddr 和 remoteaddr *现在可能包含 IPv6 地址。
3.5 版中的新增Function:* decode_data 和 enable_SMTPUTF8 构造函数参数,以及 decode_data 为False
时对process_message()的 kwargs *参数。
在版本 3.6 中更改:默认情况下,* decode_data *现在为False
。
DebuggingServer Objects
-
- class *
smtpd.
DebuggingServer
(* localaddr , remoteaddr *)
- 创建一个新的调试服务器。参数根据SMTPServer。消息将被丢弃,并在标准输出上打印。
- class *
PureProxy Objects
-
- class *
smtpd.
PureProxy
(* localaddr , remoteaddr *)
- 创建一个新的纯代理服务器。参数根据SMTPServer。一切都会中继到* remoteaddr *。请注意,运行此命令很有可能使您进入开放继电器,因此请小心。
- class *
MailmanProxy Objects
-
- class *
smtpd.
MailmanProxy
(* localaddr , remoteaddr *)
- 创建一个新的纯代理服务器。参数根据SMTPServer。除 nonlocal 邮递员配置知道地址,否则所有内容都将中继到* remoteaddr *,在这种情况下,它将pass邮递员处理。请注意,运行此命令很有可能使您进入开放继电器,因此请小心。
- class *
SMTPChannel Objects
-
- class *
smtpd.
SMTPChannel
(* server , conn , addr , data_size_limit = 33554432 , map = None , enable_SMTPUTF8 = False , decode_data = False *)
- 创建一个新的SMTPChannel对象,该对象 Management 服务器和单个 SMTPClient 端之间的通信。
- class *
conn 和 addr *与下面描述的实例变量相同。
data_size_limit *指定
DATA
命令将接受的最大字节数。值None
或0
表示没有限制。enable_SMTPUTF8 *确定是否应启用
SMTPUTF8
extensions(在 RFC 6531中定义)。默认值为False
。 * decode_data 和 enable_SMTPUTF8 *不能同时设置为True
。
可以在* map *中指定字典,以避免使用全局套接字 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
- 保留产生此 Channels 的SMTPServer。
conn
- 保存连接到 Client 端的套接字对象。
addr
- 存放 Client 的地址,即socket.accept返回的第二个值
received_lines
- 包含从 Client 端收到的行字符串列表(使用 UTF-8 解码)。这些行的
"\r\n"
行末尾翻译为"\n"
。
- 包含从 Client 端收到的行字符串列表(使用 UTF-8 解码)。这些行的
smtp_state
- 保持通道的当前状态。最初是
COMMAND
,然后在 Client 端发送“ DATA”行之后是DATA
。
- 保持通道的当前状态。最初是
seen_greeting
- 包含一个字符串,该字符串包含 Client 端在其“ HELO”中发送的问候语。
mailfrom
- 包含一个字符串,该字符串包含来自 Client 端的“ MAIL FROM:”行中标识的地址。
rcpttos
- 包含一个字符串列表,其中包含来自 Client 端的“ RCPT TO:”行中标识的地址。
received_data
- 包含一个字符串,该字符串包含 Client 端在 DATA 状态期间发送的所有数据,直到但不包括终止符
"\r\n.\r\n"
。
- 包含一个字符串,该字符串包含 Client 端在 DATA 状态期间发送的所有数据,直到但不包括终止符
fqdn
- 保留socket.getfqdn()返回的服务器的标准域名。
peer
- 保留
conn.getpeername()
返回的 Client 端对等方的名称,其中conn
为conn。
- 保留
SMTPChannelpass从 Client 端接收到命令行来调用名为smtp_<command>
的方法来进行操作。内置在SMTPChannel类中的是用于处理以下命令(并适当响应它们)的方法:
Command | Action taken |
---|---|
HELO | 接受来自 Client 的问候并将其存储在seen_greeting中。将服务器设置为基本命令模式。 |
EHLO | 接受来自 Client 的问候并将其存储在seen_greeting中。将服务器设置为扩展命令模式。 |
NOOP | 不采取任何措施。 |
QUIT | 干净地关闭连接。 |
接受“ MAIL FROM:”语法,并将提供的地址存储为mailfrom。在扩展命令模式下,接受 RFC 1870 SIZE 属性,并根据* data_size_limit *的值进行适当响应。 | |
RCPT | 接受“ RCPT TO:”语法,并将提供的地址存储在rcpttos列表中。 |
RSET | 重置mailfrom,rcpttos和received_data,但不重置问候语。 |
DATA | 将内部状态设置为DATA ,并将来自 Client 端的剩余行存储在received_data中,直到接收到终止符"\r\n.\r\n" 。 |
HELP | 返回有关命令语法的最少信息 |
VRFY | 返回代码 252(服务器不知道该地址是否有效) |
EXPN | 报告该命令未实现。 |