aioimaplib - Async IMAP Client
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.
Common errors
-
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.fixEnsure 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`. -
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).fixDouble-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. -
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.fixReplace `await client.start_tls()` with `await client.starttls()` in your code. The method was renamed to follow common Python conventions. -
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.fixVerify 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.
Warnings
- breaking Version 2.0.0 introduced significant breaking changes to connection management. The `__aenter__` and `__aexit__` methods were removed from the client class.
- breaking The `IMAP4_SSL.start_tls()` method was renamed to `IMAP4.starttls()` in version 2.0.0.
- breaking The `IMAP4.idle()` method was removed in version 2.0.0. For IMAP IDLE command, more explicit control is now provided.
- breaking The `IMAP4.noop()` method was removed in version 2.0.0. The standard `noop` command is now available through the generic command interface.
- 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.
Install
-
pip install aioimaplib
Imports
- IMAP4_SSL
from aioimaplib import IMAP4_SSL
- IMAP4
from aioimaplib import IMAP4
Quickstart
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())