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, an optional async API (sage_imap.aio), and an optional IMAP ORM (sage_imap.orm).

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])
  • IMAP ORM (optional) — manager/queryset layer, Pydantic schemas, multi-tenant account_id, CONDSTORE checkpoints (pip install python-sage-imap[orm])

Installation

pip install python-sage-imap

Async support:

pip install python-sage-imap[async]

IMAP ORM (manager/queryset API, Pydantic schemas):

pip install python-sage-imap[orm]

Async ORM:

pip install python-sage-imap[orm,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.

Quick start (IMAP ORM)

Optional Django-style managers over live IMAP (no SQL). Requires [orm]:

import os
from sage_imap.orm import ImapAccountConfig, ImapMessage, ImapORM, LoadLevel
from sage_imap.orm.schemas import ImapMessageSummarySchema

config = ImapAccountConfig(
    account_id="demo",
    host=os.environ["IMAP_HOST"],
    username=os.environ["IMAP_USER"],
    password=os.environ["IMAP_PASSWORD"],
)

with ImapORM.open("demo", config=config) as orm:
    orm.select_mailbox("INBOX")
    qs = ImapMessage.objects.filter(unread=True).limit(10).with_load_level(LoadLevel.HEADERS)
    for msg in qs.iter():
        print(ImapMessageSummarySchema.from_imap_message(msg).model_dump(mode="json"))

Tutorial: IMAP ORM tutorial · Examples: examples/10_orm_sync.py, examples/11_orm_async.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)
ORM Sync Async
Import from sage_imap.orm import ImapORM, ImapMessage from sage_imap.orm.async_session import AsyncImapORM
Install pip install python-sage-imap[orm] pip install python-sage-imap[orm,async]

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
10_orm_sync.py Sync IMAP ORM
11_orm_async.py Async IMAP ORM

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.1.0b1.tar.gz (105.1 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.1.0b1-py3-none-any.whl (132.4 kB view details)

Uploaded Python 3

File details

Details for the file python_sage_imap-2.1.0b1.tar.gz.

File metadata

  • Download URL: python_sage_imap-2.1.0b1.tar.gz
  • Upload date:
  • Size: 105.1 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.1.0b1.tar.gz
Algorithm Hash digest
SHA256 b6d9b2be16c2d0b9d41b61d53936dffca14bac260344ba9db36170112d17eb97
MD5 1e317b20e128d7490dae5fa1f9fe2d3e
BLAKE2b-256 1833d293e4d53512784af38bc2f9b855e744cf0d11f79feff30784cf05a4cfcf

See more details on using hashes here.

File details

Details for the file python_sage_imap-2.1.0b1-py3-none-any.whl.

File metadata

File hashes

Hashes for python_sage_imap-2.1.0b1-py3-none-any.whl
Algorithm Hash digest
SHA256 e773e1704adaa6e3e5460da69335a54d6bbd470715871d257768f5453a973ce6
MD5 b5113037d8e40d8bb8937f4efd3b5378
BLAKE2b-256 180e6d41ef820873b552e6b790819c3ae577594fcdadc3266af1445876cdf065

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