2009-06-22 67 views
1

比方說,你在被覆蓋的類處理消息,如:如何拒絕smtpd.SMTPServer.process_message中的收件人?

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似乎很稀疏。

回答

5

由於只有在the sources記載(!對不起),process_message的規格包括:

這個函數應返回無,用於 普通的`250 OK「響應;否則返回 它以RFC 821格式返回所需的響應字符串 。

,所以你可以「迴歸‘554個壞收件人%s’的%badrecipients」,而不是使用raise聲明 - 不完全令人滿意(不正確地考慮好和壞的混合,其中由RFC 821 應該返回一個'250 Ok',但稍後也會發送一個警告郵件),但它似乎是您要用那raise尋找的「立即反彈」效果。

+1

+1的鏈接來源 – nalply 2011-05-17 07:45:13

1

拒絕郵件的方法是從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 
相關問題