Skip to main content

Python asyncio IMAP4rev1 client library

Project description

About

Build status https://coveralls.io/repos/github/bamthomas/aioimaplib/badge.svg

This library is inspired by imaplib and imaplib2 from Piers Lauder, Nicolas Sebrecht, Sebastian Spaeth. Some utilities functions are taken from imaplib/imaplib2 thanks to them.

The aim is to port the imaplib with asyncio, to benefit from the sleep or treat model.

It runs with python 3.4 and 3.5.

Example

import asyncio
from aioimaplib import aioimaplib


@asyncio.coroutine
def check_mailbox(host, user, password):
    imap_client = aioimaplib.IMAP4_SSL(host=host)
    yield from imap_client.wait_hello_from_server()

    yield from imap_client.login(user, password)

    res, data = yield from imap_client.select()
    print('there is %s messages INBOX' % data[0])

    yield from imap_client.logout()


if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(check_mailbox('my.imap.server', 'user', 'pass'))

IDLE command

The RFC2177 is implemented, to be able to wait for new mail messages without using CPU. The responses are pushed in an async queue, and it is possible to read them in real time. To leave the IDLE mode, it is necessary to send a “DONE” command to the server.

@asyncio.coroutine
def wait_for_new_message(host, user, password):
    imap_client = aioimaplib.IMAP4_SSL(host=host)
    yield from imap_client.wait_hello_from_server()

    yield from imap_client.login(user, password)
    yield from imap_client.select()

    asyncio.async(imap_client.idle())
    while True:
        msg = yield from imap_client.wait_server_push()
        print('--> received from server: %s' % msg)
        if 'EXISTS' in msg:
            imap_client.idle_done()
            break

    yield from imap_client.logout()

if __name__ == '__main__':
        loop = asyncio.get_event_loop()
        loop.run_until_complete(wait_for_new_message('my.imap.server', 'user', 'pass'))

Threading

The IMAP4ClientProtocol class is not thread safe, it uses asyncio.Event and asyncio.Condition that are not thread safe, and state change for pending commands is not locked.

It is possible to use threads but each IMAP4ClientProtocol instance should run in the same thread :

images/thread_imap_protocol.png

Each color rectangle is an IMAP4ClientProtocol instance piece of code executed by the thread asyncio loop until it reaches a yield, waiting on I/O.

For example, it is possible to launch 4 mono-threaded mail-fetcher processes on a 4 cores server with supervisor, and use a distribution function like len(email) % (process_num) or whatever to share equally a mail account list between the 4 processes.

IMAP command concurrency

IMAP protocol allows to run some commands in parallel. Four rules are implemented to ensure responses consistency:

  1. if a sync command is running, the following requests (sync or async) must wait

  2. if an async command is running, same async commands (or with the same untagged response type) must wait

  3. async commands can be executed in parallel

  4. sync command must wait pending async commands to finish

Tested with

  • dovecot 2.2.13 on debian Jessie

Develop

Developers are welcome ! If you want to improve it, fix bugs, test it with other IMAP servers, give feedback, thank you for it.

To develop, just run:

virtualenv --python=python3.4 venv
source venv/bin/activate
python setup.py develop
pip install -r dev-requirements.txt
nosetests

To add a imaplib or imaplib2 command you can :

  • add the function to the testing imapserver with a new imaplib or imaplib2 server test, i.e. test_imapserver_imaplib.py or test_imapserver_imaplib2.py respectively;

  • then add the function to the aioimaplib doing almost the same test than above but the async way in test_aioimaplib.py.

Not unit tested

  • PREAUTH

  • SSL

TODO

  • STARTTLS command

  • AUTHENTICATE command

  • other commands listed in the aioimaplib Commands list

  • tests with other servers

If it goes wrong

Sometimes you break things and you don’t understand what’s going on (I always do). For this library I have two related tools:

  • ngrep on the imap test port : sudo ngrep -d lo port 12345

  • activate debug logs changing INFO to DEBUG at the top of the mock server and the aioimaplib

Changes

V0.5.3

  • fix aioimaplib bug when receiving chunked fetch data

  • do not abort when receiving unsollicited data from server

V0.5.2

  • build CI environment

  • license GPL v3.0

V0.5.1

  • added APPEND command

  • fix usernames can have ‘@’ for mockimapserver

  • server can handle SEARCH with CHARSET opt parameter (but ignores it)

V0.5

  • added 11 new imap commands

  • added imap command synchronizing

  • refactor

  • documentation

V0.1

  • init project with mockimapserver

  • project files

  • 11 imap commands

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

aioimaplib-0.5.3.tar.gz (33.6 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

aioimaplib-0.5.3-py3.4.egg (62.7 kB view details)

Uploaded Egg

aioimaplib-0.5.3-py3-none-any.whl (29.7 kB view details)

Uploaded Python 3

File details

Details for the file aioimaplib-0.5.3.tar.gz.

File metadata

  • Download URL: aioimaplib-0.5.3.tar.gz
  • Upload date:
  • Size: 33.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No

File hashes

Hashes for aioimaplib-0.5.3.tar.gz
Algorithm Hash digest
SHA256 e3d8989d908c7183d06e475563605b664931693911a6410c6f24de24c1857db5
MD5 d9a8964a3defbd1fbd1f82d1338e13c5
BLAKE2b-256 5dd4a00d1b730eda95a179b253ec409aea60b497cf64391311219c4edefd6f52

See more details on using hashes here.

File details

Details for the file aioimaplib-0.5.3-py3.4.egg.

File metadata

File hashes

Hashes for aioimaplib-0.5.3-py3.4.egg
Algorithm Hash digest
SHA256 4d88a39a5d140a7cb3d5bcda29a9d2a8a4cea94dfeaaf85539d1974e204ccc33
MD5 fa6e63dba9a1ee0a5aef327716c4c76a
BLAKE2b-256 c33e31a8ad3212b55e2dae85d024398e2a9bf5d806fea21a77489ff475529475

See more details on using hashes here.

File details

Details for the file aioimaplib-0.5.3-py3-none-any.whl.

File metadata

File hashes

Hashes for aioimaplib-0.5.3-py3-none-any.whl
Algorithm Hash digest
SHA256 4c0d877f7ba5a2e1f863fc815a74abcb8f1615e9b029543f680edd9bbba6e216
MD5 ddcb90b64df9cd80cbf9008bad2d25b7
BLAKE2b-256 2c67bedfdf83c8595241acb9f2ab0c95a54d8c12d192fba52565c54cdd18edef

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page