1smtpd(n) Tcl SMTP Server Package smtpd(n)
2
3
4
5______________________________________________________________________________
6
8 smtpd - Tcl SMTP server implementation
9
11 package require Tcl 8.3
12
13 package require smtpd ?1.5?
14
15 ::smtpd::start ?myaddr? ?port?
16
17 ::smtpd::stop
18
19 ::smptd::configure ?option value? ?option value ...?
20
21 ::smtpd::cget ?option?
22
23______________________________________________________________________________
24
26 The smtpd package provides a simple Tcl-only server library for the
27 Simple Mail Transfer Protocol as described in RFC 821 (http://www.rfc-
28 editor.org/rfc/rfc821.txt) and RFC 2821 (http://www.rfc-edi‐
29 tor.org/rfc/rfc2821.txt). By default the server will bind to the
30 default network address and the standard SMTP port (25).
31
32 This package was designed to permit testing of Mail User Agent code
33 from a developers workstation. It does not attempt to deliver mail to
34 your mailbox. Instead users of this package are expected to write a
35 procedure that will be called when mail arrives. Once this procedure
36 returns, the server has nothing further to do with the mail.
37
39 On Unix platforms binding to the SMTP port requires root privileges. I
40 would not recommend running any script-based server as root unless
41 there is some method for dropping root privileges immediately after the
42 socket is bound. Under Windows platforms, it is not necessary to have
43 root or administrator privileges to bind low numbered sockets. However,
44 security on these platforms is weak anyway.
45
46 In short, this code should probably not be used as a permanently run‐
47 ning Mail Transfer Agent on an Internet connected server, even though
48 we are careful not to evaluate remote user input. There are many other
49 well tested and security audited programs that can be used as mail
50 servers for internet connected hosts.
51
53 This package uses the TLS package to handle the security for https urls
54 and other socket connections.
55
56 Policy decisions like the set of protocols to support and what ciphers
57 to use are not the responsibility of TLS, nor of this package itself
58 however. Such decisions are the responsibility of whichever applica‐
59 tion is using the package, and are likely influenced by the set of
60 servers the application will talk to as well.
61
62 For example, in light of the recent POODLE attack [http://googleonli‐
63 nesecurity.blogspot.co.uk/2014/10/this-poodle-bites-exploiting-
64 ssl-30.html] discovered by Google many servers will disable support for
65 the SSLv3 protocol. To handle this change the applications using TLS
66 must be patched, and not this package, nor TLS itself. Such a patch
67 may be as simple as generally activating tls1 support, as shown in the
68 example below.
69
70
71 package require tls
72 tls::init -tls1 1 ;# forcibly activate support for the TLS1 protocol
73
74 ... your own application code ...
75
76
78 ::smtpd::start ?myaddr? ?port?
79 Start the service listening on port or the default port 25. If
80 myaddr is given as a domain-style name or numerical dotted-quad
81 IP address then the server socket will be bound to that network
82 interface. By default the server is bound to all network inter‐
83 faces. For example:
84
85
86
87 set sock [::smtpd::start [info hostname] 0]
88
89
90 will bind to the hosts internet interface on the first available port.
91
92 At present the package only supports a single instance of a SMTP
93 server. This could be changed if required at the cost of making the
94 package a little more complicated to read. If there is a good reason
95 for running multiple SMTP services then it will only be necessary to
96 fix the options array and the ::smtpd::stopped variable usage.
97
98 As the server code uses fileevent(n) handlers to process the input on
99 sockets you will need to run the event loop. This means either you
100 should be running from within wish(1) or you should vwait(n) on the
101 ::smtpd::stopped variable which is set when the server is stopped.
102
103 ::smtpd::stop
104 Halt the server and release the listening socket. If the server
105 has not been started then this command does nothing. The
106 ::smtpd::stopped variable is set for use with vwait(n).
107
108 It should be noted that stopping the server does not disconnect
109 any currently active sessions as these are operating over an
110 independent channel. Only explicitly tracking and closing these
111 sessions, or exiting the server process will close down all the
112 running sessions. This is similar to the usual unix daemon prac‐
113 tice where the server performs a fork(2) and the client session
114 continues on the child process.
115
116 ::smptd::configure ?option value? ?option value ...?
117 Set configuration options for the SMTP server. Most values are
118 the name of a callback procedure to be called at various points
119 in the SMTP protocol. See the CALLBACKS section for details of
120 the procedures.
121
122 -banner text
123 Text of a custom banner message. The default banner is
124 "tcllib smtpd 1.5". Note that changing the banner does
125 not affect the bracketing text in the full greeting,
126 printing status 220, server-address, and timestamp.
127
128 -validate_host proc
129 Callback to authenticate new connections based on the ip-
130 address of the client.
131
132 -validate_sender proc
133 Callback to authenticate new connections based on the
134 senders email address.
135
136 -validate_recipient proc
137 Callback to validate and authorize a recipient email
138 address
139
140 -deliverMIME proc
141 Callback used to deliver mail as a mime token created by
142 the tcllib mime package.
143
144 -deliver proc
145 Callback used to deliver email. This option has no effect
146 if the -deliverMIME option has been set.
147
148 ::smtpd::cget ?option?
149 If no option is specified the command will return a list of all
150 options and their current values. If an option is specified it
151 will return the value of that option.
152
154 validate_host callback
155 This procedure is called with the clients ip address as soon as
156 a connection request has been accepted and before any protocol
157 commands are processed. If you wish to deny access to a specific
158 host then an error should be returned by this callback. For
159 example:
160
161
162
163 proc validate_host {ipnum} {
164 if {[string match "192.168.1.*" $ipnum]} {
165 error "go away!"
166 }
167 }
168
169
170 If access is denied the client will receive a standard message that
171 includes the text of your error, such as:
172
173
174
175 550 Access denied: I hate you.
176
177
178 As per the SMTP protocol, the connection is not closed but we wait for
179 the client to send a QUIT command. Any other commands cause a 503 Bad
180 Sequence error.
181
182 validate_sender callback
183 The validate_sender callback is called with the senders mail
184 address during processing of a MAIL command to allow you to
185 accept or reject mail based upon the declared sender. To reject
186 mail you should throw an error. For example, to reject mail from
187 user "denied":
188
189
190
191 proc validate_sender {address} {
192 eval array set addr [mime::parseaddress $address]
193 if {[string match "denied" $addr(local)]} {
194 error "mailbox $addr(local) denied"
195 }
196 return
197 }
198
199
200 The content of any error message will not be passed back to the client.
201
202 validate_recipient callback
203 The validate_recipient callback is similar to the vali‐
204 date_sender callback and permits you to verify a local mailbox
205 and accept mail for a local user address during RCPT command
206 handling. To reject mail, throw an error as above. The error
207 message is ignored.
208
209 deliverMIME callback
210 ] The deliverMIME callback is called once a mail message has
211 been successfully passed to the server. A mime token is con‐
212 structed from the sender, recipients and data and the users pro‐
213 cedure it called with this single argument. When the call
214 returns, the mime token is cleaned up so if the user wishes to
215 preserve the data she must make a copy.
216
217
218
219 proc deliverMIME {token} {
220 set sender [lindex [mime::getheader $token From] 0]
221 set recipients [lindex [mime::getheader $token To] 0]
222 set mail "From $sender [clock format [clock seconds]]"
223 append mail "\n" [mime::buildmessage $token]
224 puts $mail
225 }
226
227
228 deliver callback
229 The deliver callback is called once a mail message has been suc‐
230 cessfully passed to the server and there is no -deliverMIME
231 option set. The procedure is called with the sender, a list of
232 recipients and the text of the mail as a list of lines. For
233 example:
234
235
236
237 proc deliver {sender recipients data} {
238 set mail "From $sender [clock format [clock seconds]]"
239 append mail "\n" [join $data "\n"]
240 puts "$mail"
241 }
242
243
244 Note that the DATA command will return an error if no sender or recipi‐
245 ent has yet been defined.
246
248 ::smtpd::stopped
249 This variable is set to true during the ::smtpd::stop command to
250 permit the use of the vwait(n) command.
251
253 Written by Pat Thoyts mailto:patthoyts@users.sourceforge.net.
254
256 This software is distributed in the hope that it will be useful, but
257 WITHOUT ANY WARRANTY; without even the implied warranty of MER‐
258 CHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the file
259 "license.terms" for more details.
260
262 This document, and the package it describes, will undoubtedly contain
263 bugs and other problems. Please report such in the category smtpd of
264 the Tcllib Trackers [http://core.tcl.tk/tcllib/reportlist]. Please
265 also report any ideas for enhancements you may have for either package
266 and/or documentation.
267
268 When proposing code changes, please provide unified diffs, i.e the out‐
269 put of diff -u.
270
271 Note further that attachments are strongly preferred over inlined
272 patches. Attachments can be made by going to the Edit form of the
273 ticket immediately after its creation, and then using the left-most
274 button in the secondary navigation bar.
275
277 rfc 2821, rfc 821, services, smtp, smtpd, socket, vwait
278
280 Networking
281
283 Copyright (c) Pat Thoyts <patthoyts@users.sourceforge.net>
284
285
286
287
288tcllib 1.5 smtpd(n)