Как мне издеваться над сервером IMAP в Python, несмотря на крайнюю лень? - PullRequest
11 голосов
/ 09 декабря 2008

Мне любопытно узнать, есть ли простой способ подделки IMAP-сервера (например, модуля imaplib) в Python, без , выполняющего много работы.

Есть ли уже существующее решение? В идеале я мог бы подключиться к существующему серверу IMAP, создать дамп и запустить фиктивный сервер из реальной структуры почтового ящика / электронной почты.

Немного предыстории лени: у меня неприятное ощущение, что этот маленький скрипт, который я пишу, со временем вырастет и хотел бы *1009*, чтобы создать надлежащую среду тестирования, но, учитывая, что это может не растет со временем, я не хочу много работать, чтобы запустить фиктивный сервер.

Ответы [ 4 ]

10 голосов
/ 09 декабря 2008

В прошлый раз, когда я пытался, мне было довольно легко написать IMAP-сервер на витой. Он поставляется с поддержкой написания серверов IMAP, и вы обладаете огромной гибкостью.

7 голосов
/ 09 декабря 2008

Сколько из этого вам действительно нужно для одного теста? Если вы начинаете строить что-то на уровне сложности реального сервера, чтобы вы могли использовать его во всех своих тестах, вы уже ошиблись. Просто издевайтесь над битами, в которых нуждается каждый.

Не пытайтесь так усердно поделиться ложной реализацией. Они должны быть не активами, а отбрасываемыми битами.

5 голосов
/ 18 февраля 2016

Так как я не нашел что-то удобное в python 3 для своих нужд (почтовая часть twisted не работает в python 3), я сделал небольшой макет с asyncio, который вы можете улучшить, если хотите:

Я определил ImapProtocol, который расширяет asyncio.Protocol. Затем запустите сервер следующим образом:

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

mailbox_map - это карта карты: электронная почта -> карта почтовых ящиков -> набор сообщений. Таким образом, все сообщения / почтовые ящики находятся в памяти.

Каждый раз, когда клиент подключается, создается новый экземпляр ImapProtocol. Затем ImapProtocol выполняется и отвечает для каждого клиента, реализуя возможность / login / 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)

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


РЕДАКТИРОВАТЬ : у меня была остановка сервера с ошибкой, я переписал его с помощью asyncio.Protocol и изменил ответ, чтобы отразить изменения

1 голос
/ 09 декабря 2008

Я никогда не пробовал, но, если бы пришлось, я бы начал с существующего SMTP-сервера.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...