Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(1223)

Delta Between Two Patch Sets: Lib/test/test_smtpd.py

Issue 8739: Update to smtpd.py to RFC 5321
Left Patch Set: Created 2 years, 7 months ago
Right Patch Set: Created 1 year, 2 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « Lib/smtpd.py ('k') | Lib/test/test_smtplib.py » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 from unittest import TestCase 1 import unittest
2 from test import support, mock_socket 2 from test import support, mock_socket
3 import socket 3 import socket
4 import io 4 import io
5 import smtpd 5 import smtpd
6 import asyncore 6 import asyncore
7 7
8 8
9 class DummyServer(smtpd.SMTPServer): 9 class DummyServer(smtpd.SMTPServer):
10 def __init__(self, localaddr, remoteaddr): 10 def __init__(self, localaddr, remoteaddr):
11 smtpd.SMTPServer.__init__(self, localaddr, remoteaddr) 11 smtpd.SMTPServer.__init__(self, localaddr, remoteaddr)
12 self.messages = [] 12 self.messages = []
13 13
14 def process_message(self, peer, mailfrom, rcpttos, data): 14 def process_message(self, peer, mailfrom, rcpttos, data):
15 self.messages.append((peer, mailfrom, rcpttos, data)) 15 self.messages.append((peer, mailfrom, rcpttos, data))
16 if data == 'return status': 16 if data == 'return status':
17 return '250 Okish' 17 return '250 Okish'
18 18
19 19
20 class DummyDispatcherBroken(Exception): 20 class DummyDispatcherBroken(Exception):
21 pass 21 pass
22 22
23 23
24 class BrokenDummyServer(DummyServer): 24 class BrokenDummyServer(DummyServer):
25 def listen(self, num): 25 def listen(self, num):
26 raise DummyDispatcherBroken() 26 raise DummyDispatcherBroken()
27 27
28 28
29 class SMTPDServerTest(TestCase): 29 class SMTPDServerTest(unittest.TestCase):
30 def setUp(self): 30 def setUp(self):
31 smtpd.socket = asyncore.socket = mock_socket 31 smtpd.socket = asyncore.socket = mock_socket
32 32
33 def test_process_message_unimplemented(self): 33 def test_process_message_unimplemented(self):
34 server = smtpd.SMTPServer('a', 'b') 34 server = smtpd.SMTPServer('a', 'b')
35 conn, addr = server.accept() 35 conn, addr = server.accept()
36 channel = smtpd.SMTPChannel(server, conn, addr) 36 channel = smtpd.SMTPChannel(server, conn, addr)
37 37
38 def write_line(line): 38 def write_line(line):
39 channel.socket.queue_recv(line) 39 channel.socket.queue_recv(line)
40 channel.handle_read() 40 channel.handle_read()
41 41
42 write_line(b'MAIL From:eggs@example') 42 write_line(b'MAIL From:eggs@example')
43 write_line(b'RCPT To:spam@example') 43 write_line(b'RCPT To:spam@example')
44 write_line(b'DATA') 44 write_line(b'DATA')
45 self.assertRaises(NotImplementedError, write_line, b'spam\r\n.\r\n') 45 self.assertRaises(NotImplementedError, write_line, b'spam\r\n.\r\n')
46 46
47 def tearDown(self): 47 def tearDown(self):
48 asyncore.close_all() 48 asyncore.close_all()
49 asyncore.socket = smtpd.socket = socket 49 asyncore.socket = smtpd.socket = socket
50 50
51 51
52 class SMTPDChannelTest(TestCase): 52 class SMTPDChannelTest(unittest.TestCase):
53 def setUp(self): 53 def setUp(self):
54 smtpd.socket = asyncore.socket = mock_socket 54 smtpd.socket = asyncore.socket = mock_socket
55 self.old_debugstream = smtpd.DEBUGSTREAM
55 self.debug = smtpd.DEBUGSTREAM = io.StringIO() 56 self.debug = smtpd.DEBUGSTREAM = io.StringIO()
56 self.server = DummyServer('a', 'b') 57 self.server = DummyServer('a', 'b')
57 conn, addr = self.server.accept() 58 conn, addr = self.server.accept()
58 self.channel = smtpd.SMTPChannel(self.server, conn, addr) 59 self.channel = smtpd.SMTPChannel(self.server, conn, addr)
59 60
60 def tearDown(self): 61 def tearDown(self):
61 asyncore.close_all() 62 asyncore.close_all()
62 asyncore.socket = smtpd.socket = socket 63 asyncore.socket = smtpd.socket = socket
64 smtpd.DEBUGSTREAM = self.old_debugstream
63 65
64 def write_line(self, line): 66 def write_line(self, line):
65 self.channel.socket.queue_recv(line) 67 self.channel.socket.queue_recv(line)
66 self.channel.handle_read() 68 self.channel.handle_read()
67 69
68 def test_broken_connect(self): 70 def test_broken_connect(self):
69 self.assertRaises(DummyDispatcherBroken, BrokenDummyServer, 'a', 'b') 71 self.assertRaises(DummyDispatcherBroken, BrokenDummyServer, 'a', 'b')
70 72
71 def test_server_accept(self): 73 def test_server_accept(self):
72 self.server.handle_accept() 74 self.server.handle_accept()
73 75
74 def test_missing_data(self): 76 def test_missing_data(self):
75 self.write_line(b'') 77 self.write_line(b'')
76 self.assertEqual(self.channel.socket.last, 78 self.assertEqual(self.channel.socket.last,
77 b'500 Error: bad syntax\r\n') 79 b'500 Error: bad syntax\r\n')
78 80
79 def test_EHLO(self): 81 def test_EHLO(self):
80 self.write_line(b'EHLO test.example') 82 self.write_line(b'EHLO test.example')
81 self.assertEqual(self.channel.socket.last, b'250 HELP\r\n') 83 self.assertEqual(self.channel.socket.last, b'250 HELP\r\n')
82 84
83 def test_EHLO_bad_syntax(self): 85 def test_EHLO_bad_syntax(self):
84 self.write_line(b'EHLO') 86 self.write_line(b'EHLO')
85 self.assertEqual(self.channel.socket.last, 87 self.assertEqual(self.channel.socket.last,
86 b'501 Syntax: EHLO hostname\r\n') 88 b'501 Syntax: EHLO hostname\r\n')
87 89
88 def test_EHLO_duplicate(self): 90 def test_EHLO_duplicate(self):
89 self.write_line(b'EHLO test.example') 91 self.write_line(b'EHLO test.example')
90 self.write_line(b'EHLO test.example') 92 self.write_line(b'EHLO test.example')
91 self.assertEqual(self.channel.socket.last, 93 self.assertEqual(self.channel.socket.last,
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
130 self.write_line(b'HELO') 132 self.write_line(b'HELO')
131 self.assertEqual(self.channel.socket.last, 133 self.assertEqual(self.channel.socket.last,
132 b'501 Syntax: HELO hostname\r\n') 134 b'501 Syntax: HELO hostname\r\n')
133 135
134 def test_HELO_duplicate(self): 136 def test_HELO_duplicate(self):
135 self.write_line(b'HELO test.example') 137 self.write_line(b'HELO test.example')
136 self.write_line(b'HELO test.example') 138 self.write_line(b'HELO test.example')
137 self.assertEqual(self.channel.socket.last, 139 self.assertEqual(self.channel.socket.last,
138 b'503 Duplicate HELO/EHLO\r\n') 140 b'503 Duplicate HELO/EHLO\r\n')
139 141
142 def test_HELO_extensions_not_enabled(self):
143 self.extended_smtp = False
144 self.write_line(b'HELO test.example')
145 self.write_line(b'MAIL from:<foo@example.com> SIZE=1234')
146 self.assertEqual(self.channel.socket.last,
147 b'501 Syntax: MAIL FROM:<address>\r\n')
148
149 def test_no_HELO_EHLO_defaults_to_HELO(self):
150 self.write_line(b'MAIL FROM:<eggs@example> SIZE=10')
151 self.assertEqual(self.channel.socket.last,
152 b'501 Syntax: MAIL FROM:<address>\r\n')
153
154 def test_MAIL_allows_space_after_colon(self):
155 self.write_line(b'HELO test.example')
156 self.write_line(b'MAIL from: <foo@example.com>')
157 self.assertEqual(self.channel.socket.last,
158 b'250 OK\r\n')
159
160 def test_extended_MAIL_allows_space_after_colon(self):
161 self.write_line(b'EHLO test.example')
162 self.write_line(b'MAIL from: <foo@example.com> size=20')
163 self.assertEqual(self.channel.socket.last,
164 b'250 OK\r\n')
165
140 def test_NOOP(self): 166 def test_NOOP(self):
141 self.write_line(b'NOOP') 167 self.write_line(b'NOOP')
142 self.assertEqual(self.channel.socket.last, b'250 OK\r\n') 168 self.assertEqual(self.channel.socket.last, b'250 OK\r\n')
143 169
144 def test_NOOP_bad_syntax(self): 170 def test_NOOP_bad_syntax(self):
145 self.write_line(b'NOOP hi') 171 self.write_line(b'NOOP hi')
146 self.assertEqual(self.channel.socket.last, 172 self.assertEqual(self.channel.socket.last,
147 b'501 Syntax: NOOP\r\n') 173 b'501 Syntax: NOOP\r\n')
148
149 def test_8BITMIME(self):
150 self.write_line(b'8BITMIME')
151 self.assertEqual(self.channel.socket.last, b'250 OK\r\n')
152
153 def test_8BITMIME_syntax(self):
154 self.write_line(b'8BITMIME ON')
155 self.assertEqual(self.channel.socket.last, b'501 Syntax: 8BITMIME\r\n')
156 174
157 def test_QUIT(self): 175 def test_QUIT(self):
158 self.write_line(b'QUIT') 176 self.write_line(b'QUIT')
159 self.assertEqual(self.channel.socket.last, b'221 Bye\r\n') 177 self.assertEqual(self.channel.socket.last, b'221 Bye\r\n')
160 178
161 def test_QUIT_arg_ignored(self): 179 def test_QUIT_arg_ignored(self):
162 self.write_line(b'QUIT bye bye') 180 self.write_line(b'QUIT bye bye')
163 self.assertEqual(self.channel.socket.last, b'221 Bye\r\n') 181 self.assertEqual(self.channel.socket.last, b'221 Bye\r\n')
164 182
165 def test_bad_state(self): 183 def test_bad_state(self):
166 self.channel.smtp_state = 'BAD STATE' 184 self.channel.smtp_state = 'BAD STATE'
167 self.write_line(b'HELO') 185 self.write_line(b'HELO')
168 self.assertEqual(self.channel.socket.last, 186 self.assertEqual(self.channel.socket.last,
169 b'451 Internal confusion\r\n') 187 b'451 Internal confusion\r\n')
170 188
189 def test_command_too_long(self):
190 self.write_line(b'HELO test.example')
191 self.write_line(b'MAIL from:<' +
192 b'a' * self.channel.command_size_limit +
193 b'@example>')
194 self.assertEqual(self.channel.socket.last,
195 b'500 Error: line too long\r\n')
196
197 def test_MAIL_command_limit_extended_with_SIZE(self):
198 self.write_line(b'EHLO test.example')
199 fill_len = self.channel.command_size_limit - len('MAIL from:<@example>')
200 self.write_line(b'MAIL from:<' +
201 b'a' * fill_len +
202 b'@example> SIZE=1234')
203 self.assertEqual(self.channel.socket.last, b'250 OK\r\n')
204
205 self.write_line(b'MAIL from:<' +
206 b'a' * (fill_len + 26) +
207 b'@example> SIZE=1234')
208 self.assertEqual(self.channel.socket.last,
209 b'500 Error: line too long\r\n')
210
211 def test_data_longer_than_default_data_size_limit(self):
212 # Hack the default so we don't have to generate so much data.
213 self.channel.data_size_limit = 1048
214 self.write_line(b'MAIL From:eggs@example')
215 self.write_line(b'RCPT To:spam@example')
216 self.write_line(b'DATA')
217 self.write_line(b'A' * self.channel.data_size_limit +
218 b'A\r\n.')
219 self.assertEqual(self.channel.socket.last,
220 b'552 Error: Too much mail data\r\n')
221
222 def test_MAIL_ok_without_HELO_EHLO(self):
223 # This actually violates the RFC, but we haven't historically
224 # enforced this, and old mail servers didn't either.
225 self.write_line(b'MAIL FROM:<eggs@example>')
226 self.assertEqual(self.channel.socket.last,
227 b'250 OK\r\n')
228
229 def test_MAIL_size_parameter(self):
230 self.write_line(b'EHLO test.example')
231 self.write_line(b'MAIL FROM:<eggs@example> SIZE=512')
232 self.assertEqual(self.channel.socket.last,
233 b'250 OK\r\n')
234
235 def test_MAIL_invalid_size_parameter(self):
236 self.write_line(b'EHLO test.example')
237 self.write_line(b'MAIL FROM:<eggs@example> SIZE=invalid')
238 self.assertEqual(self.channel.socket.last,
239 b'501 Syntax: MAIL FROM:<address> [SP <mail-parameters>]\r\n')
240
241 def test_MAIL_RCPT_unknown_parameters(self):
242 self.write_line(b'EHLO test.example')
243 self.write_line(b'MAIL FROM:<eggs@example> ham=green')
244 self.assertEqual(self.channel.socket.last,
245 b'555 MAIL FROM parameters not recognized or not implemented\r\n')
246
247 self.write_line(b'MAIL FROM:<eggs@example>')
248 self.write_line(b'RCPT TO:<eggs@example> ham=green')
249 self.assertEqual(self.channel.socket.last,
250 b'555 RCPT TO parameters not recognized or not implemented\r\n')
251
252 def test_MAIL_size_parameter_larger_than_default_data_size_limit(self):
253 self.channel.data_size_limit = 1048
254 self.write_line(b'EHLO test.example')
255 self.write_line(b'MAIL FROM:<eggs@example> SIZE=2096')
256 self.assertEqual(self.channel.socket.last,
257 b'552 Error: message size exceeds fixed maximum message size\r\n')
258
171 def test_need_MAIL(self): 259 def test_need_MAIL(self):
172 self.write_line(b'RCPT to:spam@example') 260 self.write_line(b'RCPT to:spam@example')
173 self.assertEqual(self.channel.socket.last, 261 self.assertEqual(self.channel.socket.last,
174 b'503 Error: need MAIL command\r\n') 262 b'503 Error: need MAIL command\r\n')
175 263
176 def test_MAIL_syntax(self): 264 def test_MAIL_syntax(self):
265 self.write_line(b'EHLO test.example')
177 self.write_line(b'MAIL from eggs@example') 266 self.write_line(b'MAIL from eggs@example')
178 self.assertEqual(self.channel.socket.last, 267 self.assertEqual(self.channel.socket.last,
179 b'501 Syntax: MAIL FROM:<address>\r\n') 268 b'501 Syntax: MAIL FROM:<address> [SP <mail-parameters>]\r\n')
180 269
181 def test_MAIL_missing_from(self): 270 def test_MAIL_missing_from(self):
271 self.write_line(b'EHLO test.example')
182 self.write_line(b'MAIL from:') 272 self.write_line(b'MAIL from:')
183 self.assertEqual(self.channel.socket.last, 273 self.assertEqual(self.channel.socket.last,
184 b'501 Syntax: MAIL FROM:<address>\r\n') 274 b'501 Syntax: MAIL FROM:<address> [SP <mail-parameters>]\r\n')
185 275
186 def test_MAIL_chevrons(self): 276 def test_MAIL_chevrons(self):
277 self.write_line(b'EHLO test.example')
187 self.write_line(b'MAIL from:<eggs@example>') 278 self.write_line(b'MAIL from:<eggs@example>')
188 self.assertEqual(self.channel.socket.last, b'250 OK\r\n') 279 self.assertEqual(self.channel.socket.last, b'250 OK\r\n')
189 280
281 def test_MAIL_empty_chevrons(self):
282 self.write_line(b'EHLO test.example')
283 self.write_line(b'MAIL from:<>')
284 self.assertEqual(self.channel.socket.last, b'250 OK\r\n')
285
286 # Parsing of quoted localpart of email addresses requires a full parser
287 # implementation, and will need to wait for email 6 package. See RFC 3696
288 # for valid addresses the server needs to be able to parse.
289 @unittest.expectedFailure
290 def test_MAIL_quoted_localpart(self):
291 self.write_line(b'EHLO test.example')
292 self.write_line(b'MAIL from:<"Fred Blogs"@example.com>')
293 self.assertEqual(self.channel.socket.last, b'250 OK\r\n')
294 self.write_line(b'RSET')
295 self.write_line(b'MAIL from:<Abc\>def@example.com>')
296 self.assertEqual(self.channel.socket.last, b'250 OK\r\n')
297
190 def test_nested_MAIL(self): 298 def test_nested_MAIL(self):
299 self.write_line(b'EHLO test.example')
191 self.write_line(b'MAIL from:eggs@example') 300 self.write_line(b'MAIL from:eggs@example')
192 self.write_line(b'MAIL from:spam@example') 301 self.write_line(b'MAIL from:spam@example')
193 self.assertEqual(self.channel.socket.last, 302 self.assertEqual(self.channel.socket.last,
194 b'503 Error: nested MAIL command\r\n') 303 b'503 Error: nested MAIL command\r\n')
195 304
196 def test_VRFY(self): 305 def test_VRFY(self):
197 self.write_line(b'VRFY eggs@example') 306 self.write_line(b'VRFY eggs@example')
198 self.assertEqual(self.channel.socket.last, 307 self.assertEqual(self.channel.socket.last,
199 b'252 Cannot VRFY user, but will accept message and attempt ' + \ 308 b'252 Cannot VRFY user, but will accept message and attempt ' + \
200 b'delivery\r\n') 309 b'delivery\r\n')
201 310
202 def test_VRFY_syntax(self): 311 def test_VRFY_syntax(self):
203 self.write_line(b'VRFY') 312 self.write_line(b'VRFY')
204 self.assertEqual(self.channel.socket.last, 313 self.assertEqual(self.channel.socket.last,
205 b'501 Syntax: VRFY <address>\r\n') 314 b'501 Syntax: VRFY <address>\r\n')
206 315
207 def test_EXPN_not_implemented(self): 316 def test_EXPN_not_implemented(self):
208 self.write_line(b'EXPN') 317 self.write_line(b'EXPN')
209 self.assertEqual(self.channel.socket.last, 318 self.assertEqual(self.channel.socket.last,
210 b'502 EXPN not implemented\r\n') 319 b'502 EXPN not implemented\r\n')
211 320
212 def test_need_RCPT(self): 321 def test_need_RCPT(self):
322 self.write_line(b'EHLO test.example')
213 self.write_line(b'MAIL From:eggs@example') 323 self.write_line(b'MAIL From:eggs@example')
214 self.write_line(b'DATA') 324 self.write_line(b'DATA')
215 self.assertEqual(self.channel.socket.last, 325 self.assertEqual(self.channel.socket.last,
216 b'503 Error: need RCPT command\r\n') 326 b'503 Error: need RCPT command\r\n')
217 327
218 def test_RCPT_syntax(self): 328 def test_RCPT_syntax(self):
329 self.write_line(b'EHLO test.example')
219 self.write_line(b'MAIL From:eggs@example') 330 self.write_line(b'MAIL From:eggs@example')
220 self.write_line(b'RCPT to eggs@example') 331 self.write_line(b'RCPT to eggs@example')
221 self.assertEqual(self.channel.socket.last, 332 self.assertEqual(self.channel.socket.last,
222 b'501 Syntax: RCPT TO: <address>\r\n') 333 b'501 Syntax: RCPT TO:<address> [SP <mail-parameters>]\r\n')
334
335 self.write_line(b'RCPT to:<eggs@example>')
336 self.assertEqual(self.channel.socket.last, b'250 OK\r\n')
223 337
224 def test_data_dialog(self): 338 def test_data_dialog(self):
339 self.write_line(b'EHLO test.example')
225 self.write_line(b'MAIL From:eggs@example') 340 self.write_line(b'MAIL From:eggs@example')
226 self.assertEqual(self.channel.socket.last, b'250 OK\r\n') 341 self.assertEqual(self.channel.socket.last, b'250 OK\r\n')
227 self.write_line(b'RCPT To:spam@example') 342 self.write_line(b'RCPT To:spam@example')
228 self.assertEqual(self.channel.socket.last, b'250 OK\r\n') 343 self.assertEqual(self.channel.socket.last, b'250 OK\r\n')
229 344
230 self.write_line(b'DATA') 345 self.write_line(b'DATA')
231 self.assertEqual(self.channel.socket.last, 346 self.assertEqual(self.channel.socket.last,
232 b'354 End data with <CR><LF>.<CR><LF>\r\n') 347 b'354 End data with <CR><LF>.<CR><LF>\r\n')
233 self.write_line(b'data\r\nmore\r\n.') 348 self.write_line(b'data\r\nmore\r\n.')
234 self.assertEqual(self.channel.socket.last, b'250 OK\r\n') 349 self.assertEqual(self.channel.socket.last, b'250 OK\r\n')
235 self.assertEqual(self.server.messages, 350 self.assertEqual(self.server.messages,
236 [('peer', 'eggs@example', ['spam@example'], 'data\nmore')]) 351 [('peer', 'eggs@example', ['spam@example'], 'data\nmore')])
237 352
238 def test_DATA_syntax(self): 353 def test_DATA_syntax(self):
354 self.write_line(b'EHLO test.example')
239 self.write_line(b'MAIL From:eggs@example') 355 self.write_line(b'MAIL From:eggs@example')
240 self.write_line(b'RCPT To:spam@example') 356 self.write_line(b'RCPT To:spam@example')
241 self.write_line(b'DATA spam') 357 self.write_line(b'DATA spam')
242 self.assertEqual(self.channel.socket.last, b'501 Syntax: DATA\r\n') 358 self.assertEqual(self.channel.socket.last, b'501 Syntax: DATA\r\n')
243 359
244 def test_data_transparency_section_4_5_2(self): 360 def test_data_transparency_section_4_5_2(self):
361 self.write_line(b'EHLO test.example')
245 self.write_line(b'MAIL From:eggs@example') 362 self.write_line(b'MAIL From:eggs@example')
246 self.write_line(b'RCPT To:spam@example') 363 self.write_line(b'RCPT To:spam@example')
247 self.write_line(b'DATA') 364 self.write_line(b'DATA')
248 self.write_line(b'..\r\n.\r\n') 365 self.write_line(b'..\r\n.\r\n')
249 self.assertEqual(self.channel.received_data, '.') 366 self.assertEqual(self.channel.received_data, '.')
250 367
251 def test_multiple_RCPT(self): 368 def test_multiple_RCPT(self):
369 self.write_line(b'EHLO test.example')
252 self.write_line(b'MAIL From:eggs@example') 370 self.write_line(b'MAIL From:eggs@example')
253 self.write_line(b'RCPT To:spam@example') 371 self.write_line(b'RCPT To:spam@example')
254 self.write_line(b'RCPT To:ham@example') 372 self.write_line(b'RCPT To:ham@example')
255 self.write_line(b'DATA') 373 self.write_line(b'DATA')
256 self.write_line(b'data\r\n.') 374 self.write_line(b'data\r\n.')
257 self.assertEqual(self.server.messages, 375 self.assertEqual(self.server.messages,
258 [('peer', 'eggs@example', ['spam@example','ham@example'], 'data')]) 376 [('peer', 'eggs@example', ['spam@example','ham@example'], 'data')])
259 377
260 def test_manual_status(self): 378 def test_manual_status(self):
261 # checks that the Channel is able to return a custom status message 379 # checks that the Channel is able to return a custom status message
380 self.write_line(b'EHLO test.example')
262 self.write_line(b'MAIL From:eggs@example') 381 self.write_line(b'MAIL From:eggs@example')
263 self.write_line(b'RCPT To:spam@example') 382 self.write_line(b'RCPT To:spam@example')
264 self.write_line(b'DATA') 383 self.write_line(b'DATA')
265 self.write_line(b'return status\r\n.') 384 self.write_line(b'return status\r\n.')
266 self.assertEqual(self.channel.socket.last, b'250 Okish\r\n') 385 self.assertEqual(self.channel.socket.last, b'250 Okish\r\n')
267 386
268 def test_RSET(self): 387 def test_RSET(self):
388 self.write_line(b'EHLO test.example')
269 self.write_line(b'MAIL From:eggs@example') 389 self.write_line(b'MAIL From:eggs@example')
270 self.write_line(b'RCPT To:spam@example') 390 self.write_line(b'RCPT To:spam@example')
271 self.write_line(b'RSET') 391 self.write_line(b'RSET')
272 self.assertEqual(self.channel.socket.last, b'250 OK\r\n') 392 self.assertEqual(self.channel.socket.last, b'250 OK\r\n')
273 self.write_line(b'MAIL From:foo@example') 393 self.write_line(b'MAIL From:foo@example')
274 self.write_line(b'RCPT To:eggs@example') 394 self.write_line(b'RCPT To:eggs@example')
275 self.write_line(b'DATA') 395 self.write_line(b'DATA')
276 self.write_line(b'data\r\n.') 396 self.write_line(b'data\r\n.')
277 self.assertEqual(self.server.messages, 397 self.assertEqual(self.server.messages,
278 [('peer', 'foo@example', ['eggs@example'], 'data')]) 398 [('peer', 'foo@example', ['eggs@example'], 'data')])
279 399
280 def test_RSET_syntax(self): 400 def test_RSET_syntax(self):
281 self.write_line(b'RSET hi') 401 self.write_line(b'RSET hi')
282 self.assertEqual(self.channel.socket.last, b'501 Syntax: RSET\r\n') 402 self.assertEqual(self.channel.socket.last, b'501 Syntax: RSET\r\n')
283 403
284 def test_unknown_command(self): 404 def test_unknown_command(self):
285 self.write_line(b'UNKNOWN_CMD') 405 self.write_line(b'UNKNOWN_CMD')
286 self.assertEqual(self.channel.socket.last, 406 self.assertEqual(self.channel.socket.last,
287 b'500 Error: command "UNKNOWN_CMD" not ' + \ 407 b'500 Error: command "UNKNOWN_CMD" not ' + \
288 b'recognized\r\n') 408 b'recognized\r\n')
289 409
290 def test_attribute_deprecations(self): 410 def test_attribute_deprecations(self):
291 with support.check_warnings(('', PendingDeprecationWarning)): 411 with support.check_warnings(('', DeprecationWarning)):
292 spam = self.channel._SMTPChannel__server 412 spam = self.channel._SMTPChannel__server
293 with support.check_warnings(('', PendingDeprecationWarning)): 413 with support.check_warnings(('', DeprecationWarning)):
294 self.channel._SMTPChannel__server = 'spam' 414 self.channel._SMTPChannel__server = 'spam'
295 with support.check_warnings(('', PendingDeprecationWarning)): 415 with support.check_warnings(('', DeprecationWarning)):
296 spam = self.channel._SMTPChannel__line 416 spam = self.channel._SMTPChannel__line
297 with support.check_warnings(('', PendingDeprecationWarning)): 417 with support.check_warnings(('', DeprecationWarning)):
298 self.channel._SMTPChannel__line = 'spam' 418 self.channel._SMTPChannel__line = 'spam'
299 with support.check_warnings(('', PendingDeprecationWarning)): 419 with support.check_warnings(('', DeprecationWarning)):
300 spam = self.channel._SMTPChannel__state 420 spam = self.channel._SMTPChannel__state
301 with support.check_warnings(('', PendingDeprecationWarning)): 421 with support.check_warnings(('', DeprecationWarning)):
302 self.channel._SMTPChannel__state = 'spam' 422 self.channel._SMTPChannel__state = 'spam'
303 with support.check_warnings(('', PendingDeprecationWarning)): 423 with support.check_warnings(('', DeprecationWarning)):
304 spam = self.channel._SMTPChannel__greeting 424 spam = self.channel._SMTPChannel__greeting
305 with support.check_warnings(('', PendingDeprecationWarning)): 425 with support.check_warnings(('', DeprecationWarning)):
306 self.channel._SMTPChannel__greeting = 'spam' 426 self.channel._SMTPChannel__greeting = 'spam'
307 with support.check_warnings(('', PendingDeprecationWarning)): 427 with support.check_warnings(('', DeprecationWarning)):
308 spam = self.channel._SMTPChannel__mailfrom 428 spam = self.channel._SMTPChannel__mailfrom
309 with support.check_warnings(('', PendingDeprecationWarning)): 429 with support.check_warnings(('', DeprecationWarning)):
310 self.channel._SMTPChannel__mailfrom = 'spam' 430 self.channel._SMTPChannel__mailfrom = 'spam'
311 with support.check_warnings(('', PendingDeprecationWarning)): 431 with support.check_warnings(('', DeprecationWarning)):
312 spam = self.channel._SMTPChannel__rcpttos 432 spam = self.channel._SMTPChannel__rcpttos
313 with support.check_warnings(('', PendingDeprecationWarning)): 433 with support.check_warnings(('', DeprecationWarning)):
314 self.channel._SMTPChannel__rcpttos = 'spam' 434 self.channel._SMTPChannel__rcpttos = 'spam'
315 with support.check_warnings(('', PendingDeprecationWarning)): 435 with support.check_warnings(('', DeprecationWarning)):
316 spam = self.channel._SMTPChannel__data 436 spam = self.channel._SMTPChannel__data
317 with support.check_warnings(('', PendingDeprecationWarning)): 437 with support.check_warnings(('', DeprecationWarning)):
318 self.channel._SMTPChannel__data = 'spam' 438 self.channel._SMTPChannel__data = 'spam'
319 with support.check_warnings(('', PendingDeprecationWarning)): 439 with support.check_warnings(('', DeprecationWarning)):
320 spam = self.channel._SMTPChannel__fqdn 440 spam = self.channel._SMTPChannel__fqdn
321 with support.check_warnings(('', PendingDeprecationWarning)): 441 with support.check_warnings(('', DeprecationWarning)):
322 self.channel._SMTPChannel__fqdn = 'spam' 442 self.channel._SMTPChannel__fqdn = 'spam'
323 with support.check_warnings(('', PendingDeprecationWarning)): 443 with support.check_warnings(('', DeprecationWarning)):
324 spam = self.channel._SMTPChannel__peer 444 spam = self.channel._SMTPChannel__peer
325 with support.check_warnings(('', PendingDeprecationWarning)): 445 with support.check_warnings(('', DeprecationWarning)):
326 self.channel._SMTPChannel__peer = 'spam' 446 self.channel._SMTPChannel__peer = 'spam'
327 with support.check_warnings(('', PendingDeprecationWarning)): 447 with support.check_warnings(('', DeprecationWarning)):
328 spam = self.channel._SMTPChannel__conn 448 spam = self.channel._SMTPChannel__conn
329 with support.check_warnings(('', PendingDeprecationWarning)): 449 with support.check_warnings(('', DeprecationWarning)):
330 self.channel._SMTPChannel__conn = 'spam' 450 self.channel._SMTPChannel__conn = 'spam'
331 with support.check_warnings(('', PendingDeprecationWarning)): 451 with support.check_warnings(('', DeprecationWarning)):
332 spam = self.channel._SMTPChannel__addr 452 spam = self.channel._SMTPChannel__addr
333 with support.check_warnings(('', PendingDeprecationWarning)): 453 with support.check_warnings(('', DeprecationWarning)):
334 self.channel._SMTPChannel__addr = 'spam' 454 self.channel._SMTPChannel__addr = 'spam'
335 455
336 456
337 class SMTPDChannelWithDataSizeLimitTest(TestCase): 457 class SMTPDChannelWithDataSizeLimitTest(unittest.TestCase):
338 458
339 def setUp(self): 459 def setUp(self):
340 smtpd.socket = asyncore.socket = mock_socket 460 smtpd.socket = asyncore.socket = mock_socket
341 self.debug = smtpd.DEBUGSTREAM = io.StringIO() 461 self.debug = smtpd.DEBUGSTREAM = io.StringIO()
342 self.server = DummyServer('a', 'b') 462 self.server = DummyServer('a', 'b')
343 conn, addr = self.server.accept() 463 conn, addr = self.server.accept()
344 # Set DATA size limit to 32 bytes for easy testing 464 # Set DATA size limit to 32 bytes for easy testing
345 self.channel = smtpd.SMTPChannel(self.server, conn, addr) 465 self.channel = smtpd.SMTPChannel(self.server, conn, addr, 32)
346 self.channel.size_limit = 32
347 466
348 def tearDown(self): 467 def tearDown(self):
349 asyncore.socket = smtpd.socket = socket 468 asyncore.socket = smtpd.socket = socket
350 469
351 def write_line(self, line): 470 def write_line(self, line):
352 self.channel.socket.queue_recv(line) 471 self.channel.socket.queue_recv(line)
353 self.channel.handle_read() 472 self.channel.handle_read()
354 473
355 def test_data_limit_dialog(self): 474 def test_data_limit_dialog(self):
356 self.write_line(b'MAIL From:eggs@example') 475 self.write_line(b'MAIL From:eggs@example')
(...skipping 13 matching lines...) Expand all
370 self.write_line(b'MAIL From:eggs@example') 489 self.write_line(b'MAIL From:eggs@example')
371 self.assertEqual(self.channel.socket.last, b'250 OK\r\n') 490 self.assertEqual(self.channel.socket.last, b'250 OK\r\n')
372 self.write_line(b'RCPT To:spam@example') 491 self.write_line(b'RCPT To:spam@example')
373 self.assertEqual(self.channel.socket.last, b'250 OK\r\n') 492 self.assertEqual(self.channel.socket.last, b'250 OK\r\n')
374 493
375 self.write_line(b'DATA') 494 self.write_line(b'DATA')
376 self.assertEqual(self.channel.socket.last, 495 self.assertEqual(self.channel.socket.last,
377 b'354 End data with <CR><LF>.<CR><LF>\r\n') 496 b'354 End data with <CR><LF>.<CR><LF>\r\n')
378 self.write_line(b'This message is longer than 32 bytes\r\n.') 497 self.write_line(b'This message is longer than 32 bytes\r\n.')
379 self.assertEqual(self.channel.socket.last, 498 self.assertEqual(self.channel.socket.last,
380 b'552 Too much mail data\r\n') 499 b'552 Error: Too much mail data\r\n')
381 500
382 501
383 def test_main(): 502 def test_main():
384 support.run_unittest(SMTPDServerTest, SMTPDChannelTest, 503 support.run_unittest(SMTPDServerTest, SMTPDChannelTest,
385 SMTPDChannelWithDataSizeLimitTest) 504 SMTPDChannelWithDataSizeLimitTest)
386 505
387 if __name__ == "__main__": 506 if __name__ == "__main__":
388 test_main() 507 test_main()
389
LEFTRIGHT

RSS Feeds Recent Issues | This issue
This is Rietveld cbc36f91f3f7