smtpd-SMTP 服务器

源代码: Lib/smtpd.py


该模块提供了几个类来实现 SMTP(电子邮件)服务器。

See also

推荐使用aiosmtpd软件包替代此模块。它基于asyncio,并提供了更简单的 API。 smtpd应该被视为已弃用。

存在几种服务器实施方式。一种是通用的什么都不做的实现,可以将其重写,而其他两种则提供特定的邮件发送策略。

另外,可以扩展 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的事件循环中。
  • data_size_limit *指定DATA命令将接受的最大字节数。值None0表示没有限制。

  • map *是用于连接的套接字 Map(最初为空的字典是合适的值)。如果未指定,则使用asyncore全局套接字 Map。

  • enable_SMTPUTF8 *确定是否应启用SMTPUTF8extensions(在 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(默认值)时,服务器将发布8BITMIMEextensions( 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 构造函数关键字设置为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。消息将被丢弃,并在标准输出上打印。

PureProxy Objects

    • class * smtpd. PureProxy(* localaddr remoteaddr *)
    • 创建一个新的纯代理服务器。参数根据SMTPServer。一切都会中继到* remoteaddr *。请注意,运行此命令很有可能使您进入开放继电器,因此请小心。

MailmanProxy Objects

    • class * smtpd. MailmanProxy(* localaddr remoteaddr *)
    • 创建一个新的纯代理服务器。参数根据SMTPServer。除 nonlocal 邮递员配置知道地址,否则所有内容都将中继到* remoteaddr *,在这种情况下,它将pass邮递员处理。请注意,运行此命令很有可能使您进入开放继电器,因此请小心。

SMTPChannel Objects

    • class * smtpd. SMTPChannel(* server conn addr data_size_limit = 33554432 map = None enable_SMTPUTF8 = False decode_data = False *)
    • 创建一个新的SMTPChannel对象,该对象 Management 服务器和单个 SMTPClient 端之间的通信。
  • conn addr *与下面描述的实例变量相同。

  • data_size_limit *指定DATA命令将接受的最大字节数。值None0表示没有限制。

  • enable_SMTPUTF8 *确定是否应启用SMTPUTF8extensions(在 RFC 6531中定义)。默认值为False。 * decode_data enable_SMTPUTF8 *不能同时设置为True

可以在* map *中指定字典,以避免使用全局套接字 Map。

  • decode_data *指定是否应使用 UTF-8 解码 SMTP 事务的数据部分。默认值为False。 * decode_data enable_SMTPUTF8 *不能同时设置为True

要使用自定义 SMTPChannel 实现,您需要覆盖SMTPServerSMTPServer.channel_class

在版本 3.5 中进行了更改:添加了* decode_data enable_SMTPUTF8 *参数。

在版本 3.6 中更改:默认情况下,* decode_data *现在为False

SMTPChannel具有以下实例变量:

  • smtp_server

  • conn

    • 保存连接到 Client 端的套接字对象。
  • addr

    • 存放 Client 的地址,即socket.accept返回的第二个值
  • received_lines

    • 包含从 Client 端收到的行字符串列表(使用 UTF-8 解码)。这些行的"\r\n"行末尾翻译为"\n"
  • 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"
  • fqdn

  • peer

    • 保留conn.getpeername()返回的 Client 端对等方的名称,其中connconn

SMTPChannelpass从 Client 端接收到命令行来调用名为smtp_<command>的方法来进行操作。内置在SMTPChannel类中的是用于处理以下命令(并适当响应它们)的方法:

CommandAction taken
HELO接受来自 Client 的问候并将其存储在seen_greeting中。将服务器设置为基本命令模式。
EHLO接受来自 Client 的问候并将其存储在seen_greeting中。将服务器设置为扩展命令模式。
NOOP不采取任何措施。
QUIT干净地关闭连接。
MAIL接受“ MAIL FROM:”语法,并将提供的地址存储为mailfrom。在扩展命令模式下,接受 RFC 1870 SIZE 属性,并根据* data_size_limit *的值进行适当响应。
RCPT接受“ RCPT TO:”语法,并将提供的地址存储在rcpttos列表中。
RSET重置mailfromrcpttosreceived_data,但不重置问候语。
DATA将内部状态设置为DATA,并将来自 Client 端的剩余行存储在received_data中,直到接收到终止符"\r\n.\r\n"
HELP返回有关命令语法的最少信息
VRFY返回代码 252(服务器不知道该地址是否有效)
EXPN报告该命令未实现。