假设您在重写的类中处理消息,例如:
class MailProcessorServer(smtpd.SMTPServer):
def process_message(self, peer, sender, rcpttos, data):
badrecipients = []
for rcpt in rcpttos:
badrecipients.append(rcpt)
#Here I want to warn the sender via a bounced email
# that the recipient does not exist
raise smtplib.SMTPRecipientsRefused(badrecipients)
#but this just crashes the process and eventually the sender times out,
# not good enough
我只想立即回复发件人。相反,发送服务(比如GMail)最终会放弃,并在几小时后警告用户。 documentation看起来很稀疏。
正如the sources中记载的那样(对不起!),process_message
的规格包括:
对于正常的“250 Ok”响应,此函数应返回None;否则它以RFC 821格式返回所需的响应字符串。
所以你可以“返回'554个坏收件人%s'%badrecipients”而不是使用那个raise
声明 - 不完全令人满意(没有正确解释好坏的混合,RFC 821应该返回'250 Ok '但也会在稍后发送警告邮件)但它似乎确实是你正在寻找的raise
“立即反弹”效果。
拒绝消息的方法是返回一个包含process_message
方法错误代码的字符串;例如
return '550 No such user here'
但是,RFC 821不允许在传输消息数据后返回错误代码550(它应该在RCPT
命令之后返回),并且遗憾的是smtpd模块不提供返回错误代码的简单方法。那个阶段。此外,smtpd.py通过使用自动修改“私有”双下划线属性使其类的子类化变得困难。
您可以使用以下smtpd类的自定义子类,但我还没有测试过这段代码:
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
以下将丢弃邮件而不反弹。
return '554-5.7.1'
问题:如果您在没有弹跳的情况下拒绝邮件,发件人MTA将尝试一次又一次地重新发送邮件。
错误代码550
将退回电子邮件,这可能是一个坏主意,因为您不希望给予spamer任何有关您的邮件服务器的信息。小心一点。
return '550'
这两个错误都会引发smtplib.SMTPException
。这是我用来处理这些异常的简化代码。
try:
if bounce:
return '550 Bad address'
else:
self.send_and_quit(sender, recipients, data)
except smtplib.SMTPException as e:
raise e
except Exception as e:
# Catch any other exception
logging.error(traceback.format_exc())
if not isinstance(e, smtplib.SMTPException):
self.send_and_quit(sender, recipients, data)
else:
raise e