Skip to main content

Production-ready Python IMAP client with transport layer, mailbox services, OAuth2, and connection pooling.

Project description

Python Sage IMAP

PyPI version Python License: MIT codecov Documentation

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 stdlib imaplib; 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 IMAPMailboxUIDService and IMAPSession
  • Streaming fetch with iter_uid_fetch / iter_messages and ParseMode (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 parityAsyncIMAPSession under sage_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

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

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

python_sage_imap-2.0.0.tar.gz (305.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

python_sage_imap-2.0.0-py3-none-any.whl (352.9 kB view details)

Uploaded Python 3

File details

Details for the file python_sage_imap-2.0.0.tar.gz.

File metadata

  • Download URL: python_sage_imap-2.0.0.tar.gz
  • Upload date:
  • Size: 305.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.0.1 CPython/3.12.4 Windows/11

File hashes

Hashes for python_sage_imap-2.0.0.tar.gz
Algorithm Hash digest
SHA256 ee5975f66533641eb6fc6405688451fd0af4dace1c70b20f0b160976fef65136
MD5 a66f137145ad43547c6626ed1e163357
BLAKE2b-256 70346d5ecdba5aa5238b7027662ea1910ed9c36ae985d445104b69b6aaf519a1

See more details on using hashes here.

File details

Details for the file python_sage_imap-2.0.0-py3-none-any.whl.

File metadata

  • Download URL: python_sage_imap-2.0.0-py3-none-any.whl
  • Upload date:
  • Size: 352.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.0.1 CPython/3.12.4 Windows/11

File hashes

Hashes for python_sage_imap-2.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a60c9ff15f727dfd3599af974207e6250552bc0d130eb83011ed974e2a955d59
MD5 6f22d583c94c13cbb90da72cf17e319c
BLAKE2b-256 f26db6da4b22ecd4fb53c752286c4c05e33f36d03dbbdc60ed33553a7dcfa735

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page