All Projects → bamthomas → aioimaplib

bamthomas / aioimaplib

Licence: GPL-3.0 License
Python asyncio IMAP4rev1 client library

Programming Languages

python
139335 projects - #7 most used programming language
shell
77523 projects

Projects that are alternatives of or similar to aioimaplib

i2plib
🐍 i2plib: A modern asynchronous library for building I2P applications
Stars: ✭ 23 (-70.13%)
Mutual labels:  asyncio
waio
Is a pretty simple and fully asynchronous framework for WhatsApp Business API written in Python 3.7 with asyncio and aiohttp.
Stars: ✭ 18 (-76.62%)
Mutual labels:  asyncio
aiolimiter
An efficient implementation of a rate limiter for asyncio.
Stars: ✭ 121 (+57.14%)
Mutual labels:  asyncio
pomp
Screen scraping and web crawling framework
Stars: ✭ 61 (-20.78%)
Mutual labels:  asyncio
dokku-posteio
Poste.io plugin for Dokku
Stars: ✭ 27 (-64.94%)
Mutual labels:  imap
aiodogstatsd
An asyncio-based client for sending metrics to StatsD with support of DogStatsD extension
Stars: ✭ 26 (-66.23%)
Mutual labels:  asyncio
imapd
IMAP server (library) to serve emails to an email client, written in pure PHP.
Stars: ✭ 45 (-41.56%)
Mutual labels:  imap
docker-sogo
Run sogo in a docker container.
Stars: ✭ 20 (-74.03%)
Mutual labels:  imap
aiohttp-jwt
aiohttp middleware and helper utils for working with JSON web token.
Stars: ✭ 70 (-9.09%)
Mutual labels:  asyncio
aiosqlite3
sqlite3 on asyncio use loop.run_in_executor proxy
Stars: ✭ 21 (-72.73%)
Mutual labels:  asyncio
yggmail
End-to-end encrypted email for the mesh networking age
Stars: ✭ 72 (-6.49%)
Mutual labels:  imap
deeppyer
Image deepfryer written in Python.
Stars: ✭ 36 (-53.25%)
Mutual labels:  asyncio
fastapi-boilerplate
FastAPI boilerplate for real world production
Stars: ✭ 145 (+88.31%)
Mutual labels:  asyncio
dvhb-hybrid
A package to mix django and asyncio in one application
Stars: ✭ 45 (-41.56%)
Mutual labels:  asyncio
rigor
HTTP-based DSL for for validating RESTful APIs
Stars: ✭ 65 (-15.58%)
Mutual labels:  asyncio
python-insteonplm
Python 3 asyncio module for interfacing with Insteon Powerline modems
Stars: ✭ 34 (-55.84%)
Mutual labels:  asyncio
sanic-url-shortener
Example of how to use Sanic and asyncpg (PostgreSQL)
Stars: ✭ 16 (-79.22%)
Mutual labels:  asyncio
wot-py
WoTPy is an experimental implementation of a W3C Web of Things runtime
Stars: ✭ 22 (-71.43%)
Mutual labels:  asyncio
Sharingan
We will try to find your visible basic footprint from social media as much as possible - 😤 more sites is comming soon
Stars: ✭ 13 (-83.12%)
Mutual labels:  asyncio
automate-home
Yet another python home automation (iot) project. Because a smart light is more than just on or off.
Stars: ✭ 59 (-23.38%)
Mutual labels:  asyncio

About

Build status

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.5, 3.6, 3.7, 3.8, 3.9.

Example

import asyncio
from aioimaplib import aioimaplib


async def check_mailbox(host, user, password):
    imap_client = aioimaplib.IMAP4_SSL(host=host)
    await imap_client.wait_hello_from_server()

    await imap_client.login(user, password)

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

    await 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.

async def wait_for_new_message(host, user, password):
    imap_client = aioimaplib.IMAP4_SSL(host=host)
    await imap_client.wait_hello_from_server()

    await imap_client.login(user, password)
    await imap_client.select()

    idle = await imap_client.idle_start(timeout=10)
    while imap_client.has_pending_idle():
        msg = await imap_client.wait_server_push()
        print(msg)
        if msg == STOP_WAIT_SERVER_PUSH:
            imap_client.idle_done()
            await asyncio.wait_for(idle, 1)

    await imap_client.logout()

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

Or in a more event based style (the IDLE command is closed at each message from server):

async def idle_loop(host, user, password):
   imap_client = aioimaplib.IMAP4_SSL(host=host, timeout=30)
   await imap_client.wait_hello_from_server()

   await imap_client.login(user, password)
   await imap_client.select()

   while True:
      print((await imap_client.uid('fetch', '1:*', 'FLAGS')))

      idle = await imap_client.idle_start(timeout=60)
      print((await imap_client.wait_server_push()))

      imap_client.idle_done()
      await asyncio.wait_for(idle, 30)

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

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
  • outlook with SSL
  • yahoo with SSL
  • free.fr with SSL
  • orange.fr with SSL
  • mailden.net with 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 an 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

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
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].