68
68
# These error codes are now obsolete. The LMTP protocol now uses enhanced error codes
69
ERR_451 = '451 Requested action aborted: error in processing'
70
ERR_501 = '501 Message has defects'
71
ERR_502 = '502 Error: command HELO not implemented'
72
# ERR_550 = config.LMTP_ERR_550
69
#ERR_451 = '451 Requested action aborted: error in processing'
70
#ERR_501 = '501 Message has defects'
71
#ERR_502 = '502 Error: command HELO not implemented'
72
#ERR_550 = config.LMTP_ERR_550
74
74
# Enhanced error codes
141
141
self._fqdn = socket.getfqdn()
142
142
self._peer = conn.getpeername()
143
143
self.set_terminator('\r\n')
144
self.push('220 '+EERR_200+' '+self._fqdn+' '+__version__)
144
self.push('220 %s %s' % (self._fqdn, __version__))
147
147
# smtp_HELO pushs an error if the HELO command is used
148
148
def smtp_HELO(self, arg):
149
self.push('501 '+EERR_551+'. Use: LHLO command')
149
self.push('501 '+EERR_551+' Use: LHLO command')
152
152
# smtp_EHLO pushs an error if the EHLO command is used
153
153
def smtp_EHLO(self, arg):
154
self.push('501 '+EERR_551+'. Use: LHLO command')
154
self.push('501 '+EERR_551+' Use: LHLO command')
157
157
def smtp_LHLO(self, arg):
158
158
"""HELO is not a valid LMTP command."""
160
self.push('501 '+EERR_554+'. Syntax: lhlo hostname')
160
self.push('501 '+EERR_554+' Syntax: lhlo hostname')
162
162
if self._greeting:
163
self.push('503 '+EERR_551+'. Duplicate LHLO')
163
self.push('503 '+EERR_551+' Duplicate LHLO')
166
166
self._greeting = arg
167
self.push('250 '+EERR_200+' '+self._fqdn)
168
self.push('250 '+EERR_200+' PIPELINING')
169
self.push('250 '+EERR_200+' ENHANCEDSTATUSCODES')
167
# Don't forget '-' after the status code on each line
168
# except for the last line, if there is a multiline response
169
self.push('250-%s' % self._fqdn)
170
# Use following line when Pipelining is supported
171
#self.push('250-PIPELINING')
172
self.push('250 ENHANCEDSTATUSCODES')
171
174
def smtp_MAIL(self, arg):
172
175
if self.LHLO == False:
173
self.push('503 '+EERR_551+'. Need LHLO command')
176
self.push('503 '+EERR_551+' Need LHLO command')
175
178
address = self._getaddr('FROM:', arg) if arg else None
177
self.push('501 '+EERR_554+'. Syntax: MAIL FROM:<address>')
180
self.push('501 '+EERR_554+' Syntax: MAIL FROM:<address>')
179
182
if self._mailfrom:
180
self.push('503 '+EERR_551+'. Nested MAIL command')
183
self.push('503 '+EERR_551+' Nested MAIL command')
182
185
self._mailfrom = address
183
self.push('250 '+EERR_200+' Ok')
186
self.push('250 '+EERR_200+' Ok Sender address accepted')
186
189
def smtp_RCPT(self, arg):
187
190
if not self._mailfrom:
188
self.push('503 '+EERR_551+'. Need MAIL command')
191
self.push('503 '+EERR_551+' Need MAIL command')
190
193
address = self._getaddr('TO:', arg) if arg else None
192
self.push('501 '+EERR_554+'. Syntax: RCPT TO:<address>')
195
self.push('501 '+EERR_554+' Syntax: RCPT TO:<address>')
197
# Call rcpttocheck to check if list address has syntax errors
198
if self.rcpttocheck(address) == 'EERR_513':
199
self.push('550 '+EERR_513+' Syntax: list@domain')
194
201
# Call rcpttocheck to check if list address is a known address.
195
202
if self.rcpttocheck(address) == 'EERR_511':
196
self.push('550 '+EERR_511)
198
# Call rcpttocheck to check if list address has syntax errors
199
if self.rcpttocheck(address) == 'EERR_513':
200
self.push('550 '+EERR_513)
203
self.push('550 '+EERR_511+': '+address)
203
206
listname = self.listname(address)
213
216
self.push('550 '+EERR_572+', the subaddresses -leave and -unsubscribe can not be used by unauthorised senders')
215
218
self._rcpttos.append(address)
216
self.push('250 '+EERR_200+' Ok')
219
self.push('250 '+EERR_200+' Ok Recipient address accepted')
218
221
def smtp_DATA(self, arg):
219
222
if not self._rcpttos:
220
self.push('503 '+EERR_551+'. Need RCPT command')
223
self.push('503 '+EERR_551+' Need a valid recipient')
223
226
self.push('501 '+EERR_554+' Syntax: DATA')
229
232
def smtp_RSET(self, arg):
231
self.push('501 Syntax: RSET')
234
self.push('501 '+EERR_554+' Syntax: RSET')
233
236
# Resets the sender, recipients, and data, but not the greeting
234
237
self._mailfrom = None
235
238
self._rcpttos = []
237
240
self._state = self.COMMAND
238
self.push('250 '+EERR_200+' Reset Ok')
241
self.push('250 '+EERR_200+' Ok Reset')
240
243
def smtp_NOOP(self, arg):
242
self.push('501 '+EERR_554+'. Syntax: NOOP')
245
self.push('501 '+EERR_554+' Syntax: NOOP')
244
247
self.push('250 '+EERR_200+' Ok')
289
292
arg = line[i+1:].strip()
290
293
method = getattr(self, 'smtp_' + command, None)
292
self.push('500 '+EERR_551+'. Command "%s" not implemented' % command)
295
self.push('500 '+EERR_551+' Command "%s" not implemented' % command)
297
300
if self._state != self.DATA:
298
self.push('451 '+EERR_450+'. Internal confusion')
301
self.push('451 '+EERR_450+' Internal confusion')
300
303
# Remove extraneous carriage returns and de-transparency according
301
304
# to RFC 821, Section 4.5.2.