Question

Je suis curieux de savoir s’il existe un moyen simple de se moquer d’un serveur IMAP (module imaplib) en Python, sans faire beaucoup de travail.

Existe-t-il une solution préexistante? Idéalement, je pourrais me connecter au serveur IMAP existant, effectuer un cliché et laisser le serveur fictif s'exécuter à partir de la structure de messagerie / courrier électronique réelle.

Quelques antécédents dans la paresse: j'ai la désagréable impression que ce petit script que j'écris grandira avec le temps et voudrait créer un environnement de test approprié, mais > ne pas grandir avec le temps, je ne veux pas faire beaucoup de travail pour que le serveur fictif fonctionne.

Était-ce utile?

La solution

J'ai trouvé assez facile d'écrire un serveur IMAP dans Twed la dernière fois que j'ai essayé. Il prend en charge l’écriture de serveurs IMAP et vous offre une grande flexibilité.

Autres conseils

De combien en avez-vous vraiment besoin pour un test? Si vous commencez à construire quelque chose dans l’ordre de complexité d’un serveur réel pour pouvoir l’utiliser lors de tous vos tests, vous vous êtes déjà trompé. Il suffit de se moquer des bits dont tout le monde a besoin.

Ne prenez pas la peine d’essayer si fort de partager une implémentation fictive. Ils ne sont pas censés être des actifs, mais des éléments inutiles à jeter.

Comme je ne trouvais pas quelque chose qui convenait à python 3 pour mes besoins (la partie mail de twisted n’est pas exécutée en python 3), j’ai fait une petite maquette en asyncio que vous pouvez améliorer si vous le souhaitez:

J'ai défini un ImapProtocol qui étend asyncio.Protocol. Puis lancez un serveur comme celui-ci:

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

mailbox_map est une carte de la carte: email - > carte des boîtes aux lettres - > ensemble de messages. Tous les messages / boîtes aux lettres sont donc en mémoire.

Chaque fois qu'un client se connecte, une nouvelle instance d'ImapProtocol est créée. Ensuite, ImapProtocol s’exécute et répond pour chaque client en implémentant la fonctionnalité / 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...

Ensuite, lors de mes tests, je lance le serveur lors de l'installation avec:

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

Lorsque je veux simuler un nouveau message:

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

Et arrêtez-le au moment du démontage:

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

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

ÉDITER : le serveur s'est arrêté de bugs, je l'ai réécrit avec asyncio.Protocol et je modifie la réponse en fonction des modifications apportées

.

Je n'ai jamais essayé, mais si je devais le faire, je commencerais par le serveur SMTP existant.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top