극심한 게으름에도 불구하고 Python에서 IMAP 서버를 어떻게 조롱합니까?
문제
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 서버로 시작할 것입니다.