21.18. smtpd - SMTP服务器

源代码: Lib / smtpd.py

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

存在几个服务器实现;一个是通用的无用的实现,可以被覆盖,而另外两个提供特定的邮件发送策略。

此外,SMTPChannel可以扩展为实现与SMTP客户端的非常具体的交互行为。

代码支持 RFC 5321以及 RFC 1870 SIZE和 RFC 6531 SMTPUTF8扩展。

21.18.1. SMTPServer Objects

class smtpd.SMTPServer(localaddr, remoteaddr, data_size_limit=33554432, map=None, enable_SMTPUTF8=False, decode_data=True)

创建一个新的SMTPServer对象,并绑定到本地地址localaddr它将remoteadd作为上游的SMTP中继。它继承自asyncore.dispatcher,并在实例化时将自身插入到asyncore的事件循环。

data_size_limit指定将在DATA命令中接受的最大字节数。None0的值表示无限制。

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

enable_SMTPUTF8确定是否应启用SMTPUTF8扩展(如 RFC 6531中定义)。默认值为False如果设置为True,则decode_data必须为False(否则会引发错误)。True时,SMTPUTF8被接受作为MAIL命令的参数,并且当存在时传递到process_message()kwargs['mail_options']列表中。

decode_data指定是否应使用UTF-8解码SMTP事务的数据部分。出于向后兼容性的原因,默认值为True,但在Python 3.6中将更改为False;明确指定关键字值以避免DeprecationWarningWhen decode_data is set to False the server advertises the 8BITMIME extension (RFC 6152), accepts the BODY=8BITMIME parameter to the MAIL command, and when present passes it to process_message() in the kwargs['mail_options'] list.

process_message(peer, mailfrom, rcpttos, data, **kwargs)

引发NotImplementedError异常。在子类中重写此方法以对邮件做一些有用的事情。无论传递给构造函数的是什么remoteaddr,它将作为_remoteaddr属性提供。对等体是远程主机的地址,mailfrom是包络发起者,rcpttos是包络收件人,数据包含电子邮件内容的字符串(应为 RFC 5321格式)。

如果decode_data构造函数关键字设置为True,则数据参数将是Unicode字符串。如果设置为False,它将是一个字节对象。

kwargs是包含附加信息的字典。除非将decode_data=Falseenable_SMTPUTF8=True中的至少一个作为init参数给出,否则它为空,在这种情况下,它包含以下键:

mail_options:
a list of all received parameters to the MAIL command (the elements are uppercase strings; example: ['BODY=8BITMIME', 'SMTPUTF8']).
rcpt_options:
same as mail_options but for the RCPT command. Currently no RCPT TO options are supported, so for now this will always be an empty list.

process_message的实现应使用**kwargs声明接受任意关键字参数,因为未来的功能增强可能会向kwargs字典添加键。

返回None以请求正常的250 确定响应;否则返回 RFC 5321格式的所需响应字符串。

channel_class

在子类中覆盖此项,以使用自定义SMTPChannel来管理SMTP客户端。

版本3.4中的新功能: 映射构造函数参数。

在3.5版本中更改: localaddrremoteaddr现在可以包含IPv6地址。

New in version 3.5: the decode_data and enable_SMTPUTF8 constructor arguments, and the kwargs argument to process_message() when one or more of these is specified.

21.18.2. DebuggingServer Objects

class smtpd.DebuggingServer(localaddr, remoteaddr)

创建一个新的调试服务器。参数与SMTPServer相同。邮件将被丢弃,并打印到标准输出。

21.18.3. PureProxy Objects

class smtpd.PureProxy(localaddr, remoteaddr)

创建一个新的纯代理服务器。参数与SMTPServer相同。一切都将传送到remoteaddr注意运行该对象和容易令你变成一个开放中继,所以请小心。

21.18.4. MailmanProxy Objects

class smtpd.MailmanProxy(localaddr, remoteaddr)

创建一个新的纯代理服务器。参数与SMTPServer相同。一切都将传送到remoteaddr,除非当地邮差配置知道一个地址,在这种情况下它将通过邮递员处理。注意运行该对象和容易令你变成一个开放中继,所以请小心。

21.18.5. SMTPChannel Objects

class smtpd.SMTPChannel(server, conn, addr, data_size_limit=33554432, map=None, enable_SMTPUTF8=False, decode_data=True)

创建一个新的SMTPChannel对象,用于管理服务器和单个SMTP客户端之间的通信。

connaddr是根据下面描述的实际变量。

data_size_limit指定将在DATA命令中接受的最大字节数。None0的值表示无限制。

enable_SMTPUTF8确定是否应启用SMTPUTF8扩展(如 RFC 6531中定义)。默认值为False如果enable_SMTPUTF8decode_data同时设置为True,则会产生ValueError

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

decode_data指定是否应使用UTF-8解码SMTP事务的数据部分。出于向后兼容性的原因,默认值为True,但会在Python 3.6中更改为False明确指定关键字值,以避免DeprecationWarning

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

在版本3.5中已更改:添加了decode_dataenable_SMTPUTF8参数。

SMTPChannel具有以下实例变量:

smtp_server

保留产生此频道的SMTPServer

conn

保存连接到客户端的套接字对象。

addr

保存客户端的地址,socket.accept返回的第二个值

received_lines

保存从客户端接收的行字符串(使用UTF-8解码)的列表。这些线将它们的"\r\n"线结束翻译为"\n"

smtp_state

保持通道的当前状态。This will be either COMMAND initially and then DATA after the client sends a “DATA” line.

seen_greeting

保存客户端在其“HELO”中发送的包含问候语的字符串。

mailfrom

保留一个字符串,其中包含来自客户端的“MAIL FROM:”行中标识的地址。

rcpttos

保存来自客户端的包含在“RCPT TO:”行中标识的地址的字符串列表。

received_data

保存包含客户端在DATA状态期间发送的所有数据的字符串,但不包括终止"\r\n.\r\n"

fqdn

保存由socket.getfqdn()返回的服务器的完全限定域名。

peer

保留conn.getpeername()返回的客户端对等体的名称,其中connconn

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重置mailfromrcpttosreceived_data,但不是问候语。
数据将内部状态设置为DATA,并在received_data中存储来自客户端的剩余行,直到终止符"\r\n.\r\n"
帮帮我返回有关命令语法的最少信息
VRFY返回代码252(服务器不知道地址是否有效)
EXPN报告命令未实现。