The way to reject a message is to return a string with the error code from your process_message
method; e.g.
return '550 No such user here'
However, RFC 821 doesn't allow error code 550 to be returned after the message data has been transfered (it should be returned after the RCPT
command), and the smtpd module unfortunately doesn't provide an easy way to return an error code at that stage. Furthermore, smtpd.py makes it difficult to subclass its classes by using auto-mangling "private" double-underscore attributes.
You may be able to use the following custom subclasses of smtpd classes, but I haven't tested this code:
class RecipientValidatingSMTPChannel(smtpd.SMTPChannel):
def smtp_RCPT(self, arg):
print >> smtpd.DEBUGSTREAM, '===> RCPT', arg
if not self._SMTPChannel__mailfrom:
self.push('503 Error: need MAIL command')
return
address = self._SMTPChannel__getaddr('TO:', arg)
if not address:
self.push('501 Syntax: RCPT TO: <address>')
return
if self._SMTPChannel__server.is_valid_recipient(address):
self._SMTPChannel__rcpttos.append(address)
print >> smtpd.DEBUGSTREAM, 'recips:', self._SMTPChannel__rcpttos
self.push('250 Ok')
else:
self.push('550 No such user here')
class MailProcessorServer(smtpd.SMTPServer):
def handle_accept(self):
conn, addr = self.accept()
print >> smtpd.DEBUGSTREAM, 'Incoming connection from %s' % repr(addr)
channel = RecipientValidatingSMTPChannel(self, conn, addr)
def is_valid_recipient(self, address):
# insert your own tests here, return True if it's valid
return False