This is a pre-production deployment of Warehouse, however changes made here WILL affect the production instance of PyPI.
Latest Version Dependencies status unknown Test status unknown Test coverage unknown
Project Description

About

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'))

Beware that the IMAP4.close() function is an IMAP function that is closing the selected mailbox, thus passing from SELECTED state to AUTH state. It does not close the TCP connection. The way to close TCP connection properly is to logout.

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 :

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

Logging

As said in the logging howto the logger is defined with

logger = logging.getLogger(__name__)

Where name is ‘aioimaplib.aioimaplib’. You can set the logger parameters, either by python API

aioimaplib_logger = logging.getLogger('aioimaplib.aioimaplib')
sh = logging.StreamHandler()
sh.setLevel(logging.DEBUG)
sh.setFormatter(logging.Formatter("%(asctime)s %(levelname)s [%(module)s:%(lineno)d] %(message)s"))
aioimaplib_logger.addHandler(sh)

Or loading config file (for example with logging.config.dictConfig(yaml.load(file))) with this piece of yaml file:

loggers:
...
  aioimaplib.aioimaplib:
    level: DEBUG
    handlers: [syslog]
    propagate: no
...

Tested with

  • dovecot 2.2.13 on debian Jessie
  • gmail with imap and SSL

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

  • 23/25 IMAP4rev1 commands are implemented from the main rfc3501. ‘STARTTLS’ and ‘AUTHENTICATE’ are still missing.
  • ‘COMPRESS’ from rfc4978
  • ‘SETACL’ ‘DELETEACL’ ‘GETACL’ ‘MYRIGHTS’ ‘LISTRIGHTS’ from ACL rfc4314
  • ‘GETQUOTA’: ‘GETQUOTAROOT’: ‘SETQUOTA’ from quota rfc2087
  • ‘SORT’ and ‘THREAD’ from the rfc5256
  • ‘ID’ from the rfc2971
  • ‘NAMESPACE’ from rfc2342
  • ‘CATENATE’ from rfc4469
  • 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.14

  • tests : extract Mail.create_binary for convenience

V0.5.13

  • fix : trailing whitespace bug causing “BAD Could not parse command” using gmail/IDLE
  • fix : stop adding a space for the prefix ‘UID ‘ -> ‘UID’

V0.5.12

  • fix : issue #12 Not properly buffering newlines for incomplete lines
  • fix : imapserver with status of an inexistant mailbox
  • fix : remove offset problem with strip() modifying length of read data
  • fix : remove ‘unknown data received’ logs if line is empty

V0.5.11

  • remove hard coded logging config
  • doc : added logging settings

V0.5.10

  • added rfc5032 ‘within’ function to server and tests for aiolib (it is only YOUNGER/OLDER arguments)

V0.5.9

  • pushing continuation in the queue when idled

V0.5.8

  • added a stop waiting server push function to interupt yield from queue.get

V0.5.7

  • server send still here every IDLE_STILL_HERE_PERIOD_SECONDS to client when idle
  • fix when server was lauched with main, loop is already running

V0.5.6

  • fix doc
  • fix imapserver main (needs a asyncio.loop.run_forever())

V0.5.5

  • fix issues with coroutines in uid command
  • documentation
  • remove PARTIAL, PROXYAUTH, SETANNOTATION and GETANNOTATION commands

V0.5.4

  • refactor: treating response as we read the imap server responses for a better reading
  • doc
  • removing tests from package
  • publish on pypi
  • added coverall

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
Release History

Release History

0.5.14

This version

History Node

TODO: Figure out how to actually get changelog content.

Changelog content for this version goes here.

Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Show More

0.5.13

History Node

TODO: Figure out how to actually get changelog content.

Changelog content for this version goes here.

Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Show More

0.5.12

History Node

TODO: Figure out how to actually get changelog content.

Changelog content for this version goes here.

Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Show More

0.5.11

History Node

TODO: Figure out how to actually get changelog content.

Changelog content for this version goes here.

Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Show More

0.5.9

History Node

TODO: Figure out how to actually get changelog content.

Changelog content for this version goes here.

Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Show More

0.5.8

History Node

TODO: Figure out how to actually get changelog content.

Changelog content for this version goes here.

Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Show More

0.5.7

History Node

TODO: Figure out how to actually get changelog content.

Changelog content for this version goes here.

Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Show More

0.5.6

History Node

TODO: Figure out how to actually get changelog content.

Changelog content for this version goes here.

Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Show More

0.5.5

History Node

TODO: Figure out how to actually get changelog content.

Changelog content for this version goes here.

Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Show More

0.5.4

History Node

TODO: Figure out how to actually get changelog content.

Changelog content for this version goes here.

Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Show More

0.5.3

History Node

TODO: Figure out how to actually get changelog content.

Changelog content for this version goes here.

Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Show More

Download Files

Download Files

TODO: Brief introduction on what you do with files - including link to relevant help section.

File Name & Checksum SHA256 Checksum Help Version File Type Upload Date
aioimaplib-0.5.14-py3-none-any.whl (344.7 kB) Copy SHA256 Checksum SHA256 3.4 Wheel Sep 14, 2016
aioimaplib-0.5.14.tar.gz (50.0 kB) Copy SHA256 Checksum SHA256 Source Sep 14, 2016

Supported By

WebFaction WebFaction Technical Writing Elastic Elastic Search Pingdom Pingdom Monitoring Dyn Dyn DNS HPE HPE Development Sentry Sentry Error Logging CloudAMQP CloudAMQP RabbitMQ Heroku Heroku PaaS Kabu Creative Kabu Creative UX & Design Fastly Fastly CDN DigiCert DigiCert EV Certificate Rackspace Rackspace Cloud Servers DreamHost DreamHost Log Hosting