Python Sage IMAP
Production-oriented IMAP for Python 3.10+ — UID-first mailbox operations, CONDSTORE sync, IDLE, OAuth2, SPECIAL-USE folders, and an optional async API (sage_imap.aio).
Current release:
2.0.0— sync API on stdlibimaplib; async via optional[async]extra (aioimaplib).
Why this library?
Python Sage IMAP targets applications that need reliable email access beyond thin imaplib wrappers:
- UID-first search, fetch, move, and flag operations via
IMAPMailboxUIDServiceandIMAPSession - Streaming fetch with
iter_uid_fetch/iter_messagesandParseMode(headers-only, minimal, full, raw) - Incremental sync with CONDSTORE (
MailboxSyncState,CHANGEDSINCE) - IDLE for push-style mailbox notifications
- OAuth2 with refresh (
OAuth2Config,ensure_access_token) - Resilience — retries, connection pooling (
use_pool=True), metrics, health checks - Async parity —
AsyncIMAPSessionundersage_imap.aio(install[async])
Installation
pip install python-sage-imap
Async support:
pip install python-sage-imap[async]
Requirements: Python 3.10+, network access to an IMAP server (TLS recommended).
Development
git clone https://github.com/sageteamorg/python-sage-imap.git
cd python-sage-imap
poetry install
poetry install -E async # optional, for sage_imap.aio tests
poetry run pytest -m "not integration"
Integration tests against a Mailcow-compatible stack:
make integration-up
make integration-test
make integration-down
Set IMAP_HOST, IMAP_USER, IMAP_PASSWORD, and optionally IMAP_PORT. See docker/mailcow/README.md.
Quick start (sync)
Use IMAPSession as the primary entry point:
from sage_imap import IMAPSession, IMAPSearchCriteria, SpecialUse
with IMAPSession("imap.example.com", "user@example.com", "app-password") as session:
session.select("INBOX")
result = session.search(IMAPSearchCriteria.UNSEEN)
trash = session.special_folder(SpecialUse.TRASH)
for msg in session.iter_messages(result.to_uid_message_set(), batch_size=50):
print(msg.uid, msg.subject)
More: docs/SESSION.md · Read the Docs
Quick start (async)
import asyncio
from sage_imap.aio import AsyncIMAPSession
from sage_imap.helpers.search import IMAPSearchCriteria
async def main():
async with AsyncIMAPSession("imap.example.com", "user@example.com", "secret") as session:
await session.select("INBOX")
result = await session.search(IMAPSearchCriteria.UNSEEN)
async for msg in session.iter_messages(result.to_uid_message_set()):
print(msg.subject)
asyncio.run(main())
See docs/ASYNC.md and examples/09_async_session.py.
Sync vs async
| Topic | Sync | Async |
|---|---|---|
| Import | from sage_imap import IMAPSession |
from sage_imap.aio import AsyncIMAPSession |
| Transport | imaplib + threading.RLock |
aioimaplib + asyncio.Lock |
| Install | pip install python-sage-imap |
pip install python-sage-imap[async] |
| OAuth refresh | stdlib (urllib) |
httpx (or thread fallback) |
Async is not re-exported from top-level sage_imap (by design). See docs/MIGRATION_v2.md when upgrading from 1.x.
Lower-level API
Services remain available for fine-grained control:
from sage_imap import IMAPClient, IMAPMailboxUIDService, IMAPSearchCriteria
with IMAPClient("imap.example.com", "user@example.com", "secret") as client:
caps = client.transport.get_capabilities()
mailbox = IMAPMailboxUIDService(client)
mailbox.select("INBOX")
result = mailbox.uid_search(IMAPSearchCriteria.ALL)
for msg in mailbox.iter_uid_fetch(result.to_uid_message_set()):
print(msg.subject)
IMAPClient delegates raw imaplib methods (e.g. list, select) when connected; prefer UID services for message operations.
Examples
Runnable scripts live under examples/. Configure credentials via environment variables:
export IMAP_HOST=imap.example.com
export IMAP_USER=user@example.com
export IMAP_PASSWORD=secret
poetry run python examples/01_basic_client_usage.py
| Script | Topic |
|---|---|
01_basic_client_usage.py |
Client, pooling, metrics |
02_connection_pooling_example.py |
use_pool=True |
03_retry_and_resilience_example.py |
Retries and recovery |
04_monitoring_and_metrics_example.py |
ConnectionMetrics |
05_advanced_client_features.py |
OAuth, TLS, health |
06_mailbox_operations_example.py |
Mailbox CRUD |
07_advanced_mailbox_features.py |
Upload, bulk ops |
08_mailbox_uid_operations.py |
UID search/fetch |
09_async_session.py |
Async session |
See examples/README.md.
Configuration
from sage_imap import ConnectionConfig, IMAPSession, build_ssl_context
config = ConnectionConfig(
host="imap.example.com",
username="user@example.com",
password="secret",
port=993,
use_ssl=True,
timeout=30.0,
max_retries=5,
retry_delay=2.0,
enable_monitoring=True,
enable_background_health=False,
)
with IMAPSession.from_config(config) as session:
session.select("INBOX")
Documentation
- Online: https://python-sage-imap.readthedocs.io/
- Session facade: docs/SESSION.md
- Async: docs/ASYNC.md
- v2 migration: docs/MIGRATION_v2.md
- Changelog: CHANGELOG.md
Testing
poetry run pytest -m "not integration"
poetry run pytest tests/aio -m "not integration" # requires -E async
poetry run pytest --cov=sage_imap --cov-report=html
Contributing
See CONTRIBUTING.md and SECURITY.md.
make setup-dev
make test
make lint
License
MIT — see LICENSE.
Support
Metadata
Release files for python-sage-imap 2.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| python_sage_imap-2.0.0.tar.gz | 305.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| python_sage_imap-2.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 657.9 kB
Release files / python_sage_imap-2.0.0.tar.gz
| Download URL | python_sage_imap-2.0.0.tar.gz |
|---|---|
| Size | 305.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ee5975f66533641eb6fc6405688451fd0af4dace1c70b20f0b160976fef65136
|
|
BLAKE2b-256 checksum How to use checksums |
70346d5ecdba5aa5238b7027662ea1910ed9c36ae985d445104b69b6aaf519a1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.0.1 CPython/3.12.4 Windows/11
|
Release files / python_sage_imap-2.0.0-py3-none-any.whl
| Download URL | python_sage_imap-2.0.0-py3-none-any.whl |
|---|---|
| Size | 352.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a60c9ff15f727dfd3599af974207e6250552bc0d130eb83011ed974e2a955d59
|
|
BLAKE2b-256 checksum How to use checksums |
f26db6da4b22ecd4fb53c752286c4c05e33f36d03dbbdc60ed33553a7dcfa735
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.0.1 CPython/3.12.4 Windows/11
|