Python smtpd ライブラリに SMTP AUTH サポートを追加…メソッドをオーバーライドできませんか?

StackOverflow https://stackoverflow.com/questions/1138425

  •  16-09-2019
  •  | 
  •  

質問

そこで、Python smtpd SMTPServer クラスを拡張して、SMTP AUTH 接続を処理できるようにしたいと思いました。十分にシンプルに見えました...

したがって、次のように始めればよさそうです。

def smtp_EHLO(self, arg):
    print 'got in arg: ', arg
    # do stuff here...

しかし、何らかの理由で、それは決して呼び出されません。Python smtpd ライブラリは、次のように他の同様のメソッドを呼び出します。

        method = None
        i = line.find(' ')
        if i < 0:
            command = line.upper()
            arg = None
        else:
            command = line[:i].upper()
            arg = line[i+1:].strip()
        method = getattr(self, 'smtp_' + command, None)

私のメソッドが呼び出されないのはなぜですか?

その後、おそらく found_terminator(self) 全体をオーバーライドできるのではないかと考えました。という方法ですが、それもうまくいかないようです。

 def found_terminator(self):
     # I add this to my child class and it never gets called... 

私は何か愚かなことをしているのでしょうか、それとも...?今日はまだ完全に目覚めていないだけかもしれません...

import smtpd
import asyncore

class CustomSMTPServer(smtpd.SMTPServer):

    def smtp_EHLO(self, arg):

        print 'got in arg: ', arg

    def process_message(self, peer, mailfrom, rcpttos, data):
        print 'Receiving message from:', peer
        print 'Message addressed from:', mailfrom
        print 'Message addressed to  :', rcpttos
        print 'Message length        :', len(data)
        print 'HERE WE ARE MAN!'
        return

    # Implementation of base class abstract method
    def found_terminator(self):
        print 'THIS GOT CALLED RIGHT HERE!'

        line = EMPTYSTRING.join(self.__line)
        print >> DEBUGSTREAM, 'Data:', repr(line)
        self.__line = []
        if self.__state == self.COMMAND:
            if not line:
                self.push('500 Error: bad syntax')
                return
            method = None
            i = line.find(' ')
            if i < 0:
                command = line.upper()
                arg = None
            else:
                command = line[:i].upper()
                arg = line[i+1:].strip()
            method = getattr(self, 'smtp_' + command, None)

            print 'looking for: ', command
            print 'method is: ', method

            if not method:
                self.push('502 Error: command "%s" not implemented' % command)
                return
            method(arg)
            return
        else:
            if self.__state != self.DATA:
                self.push('451 Internal confusion')
                return
            # Remove extraneous carriage returns and de-transparency according
            # to RFC 821, Section 4.5.2.
            data = []
            for text in line.split('\r\n'):
                if text and text[0] == '.':
                    data.append(text[1:])
                else:
                    data.append(text)
            self.__data = NEWLINE.join(data)
            status = self.__server.process_message(self.__peer,
                                                   self.__mailfrom,
                                                   self.__rcpttos,
                                                   self.__data)
            self.__rcpttos = []
            self.__mailfrom = None
            self.__state = self.COMMAND
            self.set_terminator('\r\n')
            if not status:
                self.push('250 Ok')
            else:
                self.push(status)

server = CustomSMTPServer(('127.0.0.1', 1025), None)

asyncore.loop()
役に立ちましたか?

解決

あなたはSMTPChannelを拡張する必要がある - smtp_verbメソッドが実装されているところです。 SMTPServerのあなたの拡張機能は、ちょうどチャンネルの独自のサブクラスを返す必要があります。

他のヒント

TL&DR: SMTPChannel に機能を追加するには、関数を宣言し、それを smtpd.SMTPChannel に直接追加するだけです。

説明:

SMTPChannel クラスは、ユーザーが開いているポート (通常はポート 25) に入力したコマンドに応答するように設計されています。どのコマンドに応答できるかを検索する方法は、関数の利用可能な属性をすべて検査する「イントロスペクション」に基づいています。

SMTPChannel 内の関数に注意してください。 必要 「smtp_」で始めます。たとえば、HELP に応答したい場合は、smtpd.SMTPChannel.smtp_HELP を作成します。

以下の関数は、イントロスペクションの詳細を示すソースコードからのものです。

class SMTPChannel(asynchat.async_chat):
  method = getattr(self, 'smtp_' + command, None)

コードザットワークス

ステップ1:呼び出される関数を宣言します

def smtp_HELP(self,arg):
  self.push("[8675309] GPT Answers to HELP")

ステップ2:smtpd.SMTPChannel に以下の関数を追加します。

class FakeSMTPServer(smtpd.SMTPServer):

"""A Fake smtp server"""
        smtpd.SMTPChannel.smtp_HELP = smtp_HELP

ステップ 3:localhost 25 に Telnet してテストしてみる

Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 vics-imac.fios-router.home ESMTP Sendmail 6.7.4 Sunday 17 March 2019
HELP
[8675309] GPT Answers to HELP
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top