假设您在重写的类中处理消息,例如:
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看起来很稀疏。
答案 0 :(得分:5)
仅在the sources中记录(抱歉!),process_message
的规格包括:
此函数应返回None,for 正常的'250 Ok'响应;除此以外 它返回所需的响应字符串 RFC 821格式。
所以你可以“返回”554个坏收件人%s'%badrecipients“而不是使用raise
语句 - 不完全令人满意(没有正确解释好坏的混合,这是由RFC 821 应该返回'250 Ok',但也会稍后发送警告邮件)但它似乎确实是你正在寻找raise
的“立即反弹”效果。
答案 1 :(得分:1)
拒绝邮件的方法是返回一个包含process_message
方法错误代码的字符串; e.g。
return '550 No such user here'
然而,RFC 821不允许在传输消息数据后返回错误代码550(它应该在RCPT
命令之后返回),并且遗憾的是smtpd模块不容易提供在该阶段返回错误代码的方法。此外,smtpd.py使用auto-mangling“private”双下划线属性很难对其类进行子类化。
您可以使用以下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
答案 2 :(得分:0)
以下内容将丢弃邮件而不会退回邮件。
return '554-5.7.1'
问题:如果您拒绝邮件而没有退回邮件,则发件人MTA会尝试一次又一次重新发送邮件。
错误代码550
将使电子邮件退回,这是一个坏主意,因为您不想向垃圾邮件发送者任何有关您的邮件服务器的信息。小心点。
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