smtpd — SMTP Server¶
Source code:Lib/smtpd.py
This module offers several classes to implement SMTP (email) servers.
See also
Theaiosmtpd package is a recommendedreplacement for this module. It is based onasyncio and provides amore straightforward API.smtpd should be considered deprecated.
Several server implementations are present; one is a genericdo-nothing implementation, which can be overridden, while the other two offerspecific mail-sending strategies.
Additionally the SMTPChannel may be extended to implement very specificinteraction behaviour with SMTP clients.
The code supportsRFC 5321, plus theRFC 1870 SIZE andRFC 6531SMTPUTF8 extensions.
SMTPServer Objects¶
- class
smtpd.SMTPServer(localaddr,remoteaddr,data_size_limit=33554432,map=None,enable_SMTPUTF8=False,decode_data=False)¶ Create a new
SMTPServerobject, which binds to local addresslocaladdr. It will treatremoteaddr as an upstream SMTP relayer. Bothlocaladdr andremoteaddr should be a(host, port)tuple. The object inherits fromasyncore.dispatcher, and so willinsert itself intoasyncore’s event loop on instantiation.data_size_limit specifies the maximum number of bytes that will beaccepted in a
DATAcommand. A value ofNoneor0means nolimit.map is the socket map to use for connections (an initially emptydictionary is a suitable value). If not specified the
asyncoreglobal socket map is used.enable_SMTPUTF8 determines whether the
SMTPUTF8extension (as definedinRFC 6531) should be enabled. The default isFalse.WhenTrue,SMTPUTF8is accepted as a parameter to theMAILcommand and when present is passed toprocess_message()in thekwargs['mail_options']list.decode_data andenable_SMTPUTF8cannot be set toTrueat the same time.decode_data specifies whether the data portion of the SMTP transactionshould be decoded using UTF-8. Whendecode_data is
False(thedefault), the server advertises the8BITMIMEextension (RFC 6152), accepts theBODY=8BITMIMEparameter totheMAILcommand, and when present passes it toprocess_message()in thekwargs['mail_options']list.decode_data andenable_SMTPUTF8cannot be set toTrueat the same time.process_message(peer,mailfrom,rcpttos,data,**kwargs)¶Raise a
NotImplementedErrorexception. Override this in subclasses todo something useful with this message. Whatever was passed in theconstructor asremoteaddr will be available as the_remoteaddrattribute.peer is the remote host’s address,mailfrom is the envelopeoriginator,rcpttos are the envelope recipients anddata is a stringcontaining the contents of the e-mail (which should be inRFC 5321format).If thedecode_data constructor keyword is set to
True, thedataargument will be a unicode string. If it is set toFalse, itwill be a bytes object.kwargs is a dictionary containing additional information. It is emptyif
decode_data=Truewas given as an init argument, otherwiseit contains the following keys:- mail_options:
a list of all received parameters to the
MAILcommand (the elements are uppercase strings; example:['BODY=8BITMIME','SMTPUTF8']).- rcpt_options:
same asmail_options but for the
RCPTcommand.Currently noRCPTTOoptions are supported, so for nowthis will always be an empty list.
Implementations of
process_messageshould use the**kwargssignature to accept arbitrary keyword arguments, since future featureenhancements may add keys to the kwargs dictionary.Return
Noneto request a normal250Okresponse; otherwisereturn the desired response string inRFC 5321 format.
channel_class¶Override this in subclasses to use a custom
SMTPChannelformanaging SMTP clients.
New in version 3.4:Themap constructor argument.
Changed in version 3.5:localaddr andremoteaddr may now contain IPv6 addresses.
New in version 3.5:Thedecode_data andenable_SMTPUTF8 constructor parameters, and thekwargs parameter to
process_message()whendecode_data isFalse.Changed in version 3.6:decode_data is now
Falseby default.
DebuggingServer Objects¶
- class
smtpd.DebuggingServer(localaddr,remoteaddr)¶ Create a new debugging server. Arguments are as per
SMTPServer.Messages will be discarded, and printed on stdout.
PureProxy Objects¶
- class
smtpd.PureProxy(localaddr,remoteaddr)¶ Create a new pure proxy server. Arguments are as per
SMTPServer.Everything will be relayed toremoteaddr. Note that running this has a goodchance to make you into an open relay, so please be careful.
MailmanProxy Objects¶
- class
smtpd.MailmanProxy(localaddr,remoteaddr)¶ Create a new pure proxy server. Arguments are as per
SMTPServer.Everything will be relayed toremoteaddr, unless local mailman configurationsknows about an address, in which case it will be handled via mailman. Note thatrunning this has a good chance to make you into an open relay, so please becareful.
SMTPChannel Objects¶
- class
smtpd.SMTPChannel(server,conn,addr,data_size_limit=33554432,map=None,enable_SMTPUTF8=False,decode_data=False)¶ Create a new
SMTPChannelobject which manages the communicationbetween the server and a single SMTP client.conn andaddr are as per the instance variables described below.
data_size_limit specifies the maximum number of bytes that will beaccepted in a
DATAcommand. A value ofNoneor0means nolimit.enable_SMTPUTF8 determines whether the
SMTPUTF8extension (as definedinRFC 6531) should be enabled. The default isFalse.decode_data andenable_SMTPUTF8 cannot be set toTrueat the sametime.A dictionary can be specified inmap to avoid using a global socket map.
decode_data specifies whether the data portion of the SMTP transactionshould be decoded using UTF-8. The default is
False.decode_data andenable_SMTPUTF8 cannot be set toTrueat the sametime.To use a custom SMTPChannel implementation you need to override the
SMTPServer.channel_classof yourSMTPServer.Changed in version 3.5:Thedecode_data andenable_SMTPUTF8 parameters were added.
Changed in version 3.6:decode_data is now
Falseby default.The
SMTPChannelhas the following instance variables:smtp_server¶Holds the
SMTPServerthat spawned this channel.
conn¶Holds the socket object connecting to the client.
addr¶Holds the address of the client, the second value returned by
socket.accept
received_lines¶Holds a list of the line strings (decoded using UTF-8) received fromthe client. The lines have their
"\r\n"line ending translated to"\n".
smtp_state¶Holds the current state of the channel. This will be either
COMMANDinitially and thenDATAafter the client sendsa “DATA” line.
seen_greeting¶Holds a string containing the greeting sent by the client in its “HELO”.
mailfrom¶Holds a string containing the address identified in the “MAIL FROM:” linefrom the client.
rcpttos¶Holds a list of strings containing the addresses identified in the“RCPT TO:” lines from the client.
received_data¶Holds a string containing all of the data sent by the client during theDATA state, up to but not including the terminating
"\r\n.\r\n".
fqdn¶Holds the fully-qualified domain name of the server as returned by
socket.getfqdn().
The
SMTPChanneloperates by invoking methods namedsmtp_<command>upon reception of a command line from the client. Built into the baseSMTPChannelclass are methods for handling the following commands(and responding to them appropriately):Command
Action taken
HELO
Accepts the greeting from the client and stores it in
seen_greeting. Sets server to base command mode.EHLO
Accepts the greeting from the client and stores it in
seen_greeting. Sets server to extended command mode.NOOP
Takes no action.
QUIT
Closes the connection cleanly.
MAIL
Accepts the “MAIL FROM:” syntax and stores the supplied address as
mailfrom. In extended command mode, accepts theRFC 1870 SIZE attribute and responds appropriately based on thevalue ofdata_size_limit.RCPT
Accepts the “RCPT TO:” syntax and stores the supplied addresses inthe
rcpttoslist.RSET
Resets the
mailfrom,rcpttos, andreceived_data, but not the greeting.DATA
Sets the internal state to
DATAand stores remaining linesfrom the client inreceived_datauntil the terminator"\r\n.\r\n"is received.HELP
Returns minimal information on command syntax
VRFY
Returns code 252 (the server doesn’t know if the address is valid)
EXPN
Reports that the command is not implemented.