극심한 게으름에도 불구하고 Python에서 IMAP 서버를 어떻게 조롱합니까?

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

  •  20-08-2019
  •  | 
  •  

문제

IMAP 서버를 조롱하는 쉬운 방법이 있는지 궁금합니다. imaplib 모듈) 파이썬에서, 없이 많은 일을하고 있습니다.

기존 솔루션이 있습니까? 이상적으로는 기존 IMAP 서버에 연결하고 덤프를하고 Mock Server가 실제 사서함/이메일 구조를 실행하도록 할 수 있습니다.

게으름에 대한 약간의 배경 : 나는 내가 쓰고있는이 작은 대본이 시간이 지남에 따라 성장할 것이라는 불쾌한 느낌을 가지고 있습니다. 처럼 적절한 테스트 환경을 만들려면 ~ 아니다 시간이 지남에 따라 성장하면 모의 서버를 실행하기 위해 많은 일을하고 싶지 않습니다.

도움이 되었습니까?

해결책

지난번에 시도했을 때 Twisted에서 IMAP 서버를 작성하는 것이 매우 쉽다는 것을 알았습니다. IMAP 서버 작성을 지원하며 유연성이 엄청납니다.

다른 팁

한 번의 테스트에 실제로 얼마나 필요한가? 실제 서버의 복잡성 순서로 무언가를 구축하기 시작하여 모든 테스트에서 사용할 수 있도록 이미 잘못되었습니다. 한 번의 테스트가 필요한 비트를 조롱합니다.

모의 구현을 공유하기 위해 그렇게 열심히 노력하지 마십시오. 그것들은 자산이 아니라 버려진 비트 n 피스입니다.

Python 3에서 내 요구에 대한 편리한 것을 찾지 못했기 때문에 (Twisted의 메일 부분은 Python 3에서 실행되지 않습니다), 나는 당신이 원하는 경우 개선 할 수있는 Asyncio와 함께 작은 모의를 사용했습니다.

asyncio.protocol을 확장하는 improtocol을 정의했습니다. 그런 다음 다음과 같은 서버를 시작합니다.

factory = loop.create_server(lambda: ImapProtocol(mailbox_map), 'localhost', 1143)
server = loop.run_until_complete(factory)

Mailbox_map은 맵의 맵입니다 : 이메일 -> 사서함 -> 메시지 세트. 따라서 모든 메시지/사서함이 메모리에 있습니다.

클라이언트가 연결할 때마다 새로운 IMPortocol 인스턴스가 생성됩니다. 그런 다음 IMAPTROTOCOL은 각 클라이언트에 대한 실행 및 답변으로 기능/로그인/Fetch/Select/Search/Store를 구현합니다.

class ImapHandler(object):
    def __init__(self, mailbox_map):
        self.mailbox_map = mailbox_map
        self.user_login = None
        # ...

    def connection_made(self, transport):
        self.transport = transport
        transport.write('* OK IMAP4rev1 MockIMAP Server ready\r\n'.encode())

    def data_received(self, data):
        command_array = data.decode().rstrip().split()
        tag = command_array[0]
        self.by_uid = False
        self.exec_command(tag, command_array[1:])

    def connection_lost(self, error):
        if error:
            log.error(error)
        else:
            log.debug('closing')
            self.transport.close()
        super().connection_lost(error)

    def exec_command(self, tag, command_array):
        command = command_array[0].lower()
        if not hasattr(self, command):
            return self.error(tag, 'Command "%s" not implemented' % command)
        getattr(self, command)(tag, *command_array[1:])

    def capability(self, tag, *args):
        # code for it...
    def login(self, tag, *args):
        # code for it...

그런 다음 테스트에서 설정 중에 서버를 시작합니다.

self.loop = asyncio.get_event_loop()
self.server = self.loop.run_until_complete(self.loop.create_server(create_imap_protocol, 'localhost', 12345))

새 메시지를 시뮬레이션하려면 :

imap_receive(Mail(to='dest@fakemail.org', mail_from='exp@pouet.com', subject='hello'))

그리고 파열시 중지하십시오.

self.server.close()
asyncio.wait_for(self.server.wait_closed(), 1)

cf https://github.com/bamthomas/aioimaplib/blob/master/aioimaplib/tests/imapserver.py


편집하다: 서버의 버그가 정지되었고 asyncio.protocol으로 다시 작성하고 변경 사항을 반영하기 위해 답을 수정했습니다.

나는 시도한 적이 없지만, 내가해야한다면, 기존 SMTP 서버로 시작할 것입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top