aioimaplib - Async IMAP Client

raw JSON →
2.0.1 verified Thu Apr 16 auth: no python

aioimaplib is a Python asyncio IMAP4rev1 client library, providing asynchronous access to IMAP servers. It allows developers to interact with email servers, fetch messages, manage mailboxes, and more, using modern async/await syntax. The library is currently at version 2.0.1 and generally follows a release cadence tied to bug fixes and feature enhancements as needed.

pip install aioimaplib
error AttributeError: __aenter__
cause Attempting to use the `async with` context manager with aioimaplib client instances in versions 2.x and later, but using an old syntax or misconfiguring the client. This typically means you are using `aioimaplib` v2+ but with code written for v1.
fix
Ensure you are using async with aioimaplib.IMAP4_SSL(...) as client: or explicitly calling await client.connect() and await client.disconnect(). The __aenter__ and __aexit__ methods were removed from the class directly and are now handled internally by the async with statement through connect/disconnect.
error aioimaplib.exceptions.IMAP4Exception: LOGIN failed.
cause Incorrect username or password provided to the `login` command, or the IMAP server is rejecting the credentials (e.g., due to 2FA requiring an app-specific password, or incorrect server configuration).
fix
Double-check your username and password. If 2-Factor Authentication (2FA) is enabled on your email account, ensure you are using an app-specific password generated for aioimaplib or a similar client. Verify server logs if possible.
error AttributeError: 'IMAP4_SSL' object has no attribute 'start_tls'
cause You are running aioimaplib version 2.x or later, but your code is trying to call the `start_tls()` method, which was renamed.
fix
Replace await client.start_tls() with await client.starttls() in your code. The method was renamed to follow common Python conventions.
error socket.gaierror: [Errno 8] nodename nor servname provided, or not known
cause The hostname provided to `aioimaplib.IMAP4_SSL` or `aioimaplib.IMAP4` is either incorrect, malformed, or cannot be resolved by DNS.
fix
Verify that the host parameter (e.g., imap.mail.com) is correct and spelled accurately. Check your network connection and DNS settings. Ensure the hostname is not an empty string.
breaking Version 2.0.0 introduced significant breaking changes to connection management. The `__aenter__` and `__aexit__` methods were removed from the client class.
fix Migrate to the `async with client:` context manager (which uses `connect()` and `disconnect()` internally) or explicitly call `await client.connect()` and `await client.disconnect()`.
breaking The `IMAP4_SSL.start_tls()` method was renamed to `IMAP4.starttls()` in version 2.0.0.
fix Update your code to use `await client.starttls()` when upgrading from 1.x to 2.x.
breaking The `IMAP4.idle()` method was removed in version 2.0.0. For IMAP IDLE command, more explicit control is now provided.
fix Use `await client.idle_start()` to initiate IDLE mode and `await client.idle_done()` to terminate it.
breaking The `IMAP4.noop()` method was removed in version 2.0.0. The standard `noop` command is now available through the generic command interface.
fix Use `await client.noop_()` instead of the removed `noop()` method.
gotcha Failing to call `await client.wait_hello_from_server()` after connection but before login can lead to issues if the server's initial greeting is delayed.
fix Always include `await client.wait_hello_from_server()` after creating the client instance or after `await client.connect()` to ensure the server is ready before sending commands like `login`.

This quickstart demonstrates how to connect to an IMAP server using TLS (IMAP4_SSL), log in, list available mailboxes, and count messages in the 'INBOX'. It uses `async with` for connection management and fetches credentials from environment variables.

import aioimaplib
import asyncio
import os

async def main():
    IMAP_HOST = os.environ.get('IMAP_HOST', 'imap.mail.com')
    IMAP_USER = os.environ.get('IMAP_USER', 'your_email@mail.com')
    IMAP_PASS = os.environ.get('IMAP_PASS', 'your_password')

    if not all([IMAP_HOST, IMAP_USER, IMAP_PASS]):
        print("Please set IMAP_HOST, IMAP_USER, and IMAP_PASS environment variables.")
        return

    try:
        async with aioimaplib.IMAP4_SSL(host=IMAP_HOST) as client:
            await client.wait_hello_from_server()
            await client.login(IMAP_USER, IMAP_PASS)
            print(f"Logged in as {IMAP_USER}")

            status, mailboxes = await client.list()
            if status == 'OK':
                print("Mailboxes:")
                for mb in mailboxes:
                    print(f"  {mb.decode('utf-8')}")
            else:
                print(f"Failed to list mailboxes: {status}")

            await client.select('INBOX')
            status, msg_ids = await client.search('ALL')
            if status == 'OK' and msg_ids[0]:
                print(f"INBOX contains {len(msg_ids[0].split())} messages.")
            elif status == 'OK':
                print("INBOX is empty.")
            else:
                print(f"Failed to search INBOX: {status}")

    except aioimaplib.exceptions.IMAP4Exception as e:
        print(f"IMAP error: {e}")
    except Exception as e:
        print(f"An unexpected error occurred: {e}")

if __name__ == '__main__':
    asyncio.run(main())