blob: df67de943398e8c7308fe2ede7080e49ec70c55c [file] [log] [blame]
Georg Brandl116aa622007-08-15 14:28:22 +00001:mod:`smtpd` --- SMTP Server
2============================
3
4.. module:: smtpd
5 :synopsis: A SMTP server implementation in Python.
6
7.. moduleauthor:: Barry Warsaw <barry@zope.com>
8.. sectionauthor:: Moshe Zadka <moshez@moshez.org>
9
10
11
12
Richard Jones803ef8a2010-07-24 09:51:40 +000013This module offers several classes to implement SMTP (email) servers.
14
15Several server implementations are present; one is a generic
Georg Brandl116aa622007-08-15 14:28:22 +000016do-nothing implementation, which can be overridden, while the other two offer
17specific mail-sending strategies.
18
Richard Jones803ef8a2010-07-24 09:51:40 +000019Additionally the SMTPChannel may be extended to implement very specific
20interaction behaviour with SMTP clients.
Georg Brandl116aa622007-08-15 14:28:22 +000021
22SMTPServer Objects
23------------------
24
25
26.. class:: SMTPServer(localaddr, remoteaddr)
27
28 Create a new :class:`SMTPServer` object, which binds to local address
29 *localaddr*. It will treat *remoteaddr* as an upstream SMTP relayer. It
30 inherits from :class:`asyncore.dispatcher`, and so will insert itself into
31 :mod:`asyncore`'s event loop on instantiation.
32
Benjamin Petersone41251e2008-04-25 01:59:09 +000033 .. method:: process_message(peer, mailfrom, rcpttos, data)
Georg Brandl116aa622007-08-15 14:28:22 +000034
Benjamin Petersone41251e2008-04-25 01:59:09 +000035 Raise :exc:`NotImplementedError` exception. Override this in subclasses to
36 do something useful with this message. Whatever was passed in the
37 constructor as *remoteaddr* will be available as the :attr:`_remoteaddr`
38 attribute. *peer* is the remote host's address, *mailfrom* is the envelope
39 originator, *rcpttos* are the envelope recipients and *data* is a string
40 containing the contents of the e-mail (which should be in :rfc:`2822`
41 format).
Georg Brandl116aa622007-08-15 14:28:22 +000042
Richard Jones803ef8a2010-07-24 09:51:40 +000043 .. attribute:: channel_class
44
45 Override this in subclasses to use a custom :class:`SMTPChannel` for
46 managing SMTP clients.
47
Georg Brandl116aa622007-08-15 14:28:22 +000048
49DebuggingServer Objects
50-----------------------
51
52
53.. class:: DebuggingServer(localaddr, remoteaddr)
54
55 Create a new debugging server. Arguments are as per :class:`SMTPServer`.
56 Messages will be discarded, and printed on stdout.
57
58
59PureProxy Objects
60-----------------
61
62
63.. class:: PureProxy(localaddr, remoteaddr)
64
65 Create a new pure proxy server. Arguments are as per :class:`SMTPServer`.
66 Everything will be relayed to *remoteaddr*. Note that running this has a good
67 chance to make you into an open relay, so please be careful.
68
69
70MailmanProxy Objects
71--------------------
72
73
74.. class:: MailmanProxy(localaddr, remoteaddr)
75
76 Create a new pure proxy server. Arguments are as per :class:`SMTPServer`.
77 Everything will be relayed to *remoteaddr*, unless local mailman configurations
78 knows about an address, in which case it will be handled via mailman. Note that
79 running this has a good chance to make you into an open relay, so please be
80 careful.
81
Richard Jones803ef8a2010-07-24 09:51:40 +000082SMTPChannel Objects
83-------------------
84
85.. class:: SMTPChannel(server, conn, addr)
86
87 Create a new :class:`SMTPChannel` object which manages the communication
88 between the server and a single SMTP client.
89
90 To use a custom SMTPChannel implementation you need to override the
91 :attr:`SMTPServer.channel_class` of your :class:`SMTPServer`.
92
93 The :class:`SMTPChannel` has the following instance variables:
94
95 .. attribute:: smtp_server
96
97 Holds the :class:`SMTPServer` that spawned this channel.
98
99 .. attribute:: conn
100
101 Holds the socket object connecting to the client.
102
103 .. attribute:: addr
104
105 Holds the address of the client, the second value returned by
106 socket.accept()
107
108 .. attribute:: received_lines
109
110 Holds a list of the line strings (decoded using UTF-8) received from
111 the client. The lines have their "\r\n" line ending translated to "\n".
112
113 .. attribute:: smtp_state
114
115 Holds the current state of the channel. This will be either
116 :attr:`COMMAND` initially and then :attr:`DATA` after the client sends
117 a "DATA" line.
118
119 .. attribute:: seen_greeting
120
121 Holds a string containing the greeting sent by the client in its "HELO".
122
123 .. attribute:: mailfrom
124
125 Holds a string containing the address identified in the "MAIL FROM:" line
126 from the client.
127
128 .. attribute:: rcpttos
129
130 Holds a list of strings containing the addresses identified in the
131 "RCPT TO:" lines from the client.
132
133 .. attribute:: received_data
134
135 Holds a string containing all of the data sent by the client during the
136 DATA state, up to but not including the terminating "\r\n.\r\n".
137
138 .. attribute:: fqdn
139
140 Holds the fully-qualified domain name of the server as returned by
141 ``socket.getfqdn()``.
142
143 .. attribute:: peer
144
145 Holds the name of the client peer as returned by ``conn.getpeername()``
146 where ``conn`` is :attr:`conn`.
147
148 The :class:`SMTPChannel` operates by invoking methods named ``smtp_<command>``
149 upon reception of a command line from the client. Built into the base
150 :class:`SMTPChannel` class are methods for handling the following commands
151 (and responding to them appropriately):
152
153 ======== ===================================================================
154 Command Action taken
155 ======== ===================================================================
156 HELO Accepts the greeting from the client and stores it in
157 :attr:`seen_greeting`.
158 NOOP Takes no action.
159 QUIT Closes the connection cleanly.
160 MAIL Accepts the "MAIL FROM:" syntax and stores the supplied address as
161 :attr:`mailfrom`.
162 RCPT Accepts the "RCPT TO:" syntax and stores the supplied addresses in
163 the :attr:`rcpttos` list.
164 RSET Resets the :attr:`mailfrom`, :attr:`rcpttos`, and
165 :attr:`received_data`, but not the greeting.
166 DATA Sets the internal state to :attr:`DATA` and stores remaining lines
167 from the client in :attr:`received_data` until the terminator
168 "\r\n.\r\n" is received.
169 ======== ===================================================================