Skip to content

Mail Intake

mail_intake

Mail Intake — provider-agnostic, read-only email ingestion framework.

Mail Intake is a contract-first library designed to ingest, parse, and normalize email data from external providers (such as Gmail) into clean, provider-agnostic domain models.

The library is intentionally structured around clear layers, each exposed as a first-class module at the package root:

  • adapters: provider-specific access (e.g. Gmail)
  • auth: authentication providers and credential lifecycle management
  • credentials: credential persistence abstractions and implementations
  • parsers: extraction and normalization of message content
  • ingestion: orchestration and high-level ingestion workflows
  • models: canonical, provider-agnostic data representations
  • config: explicit global configuration
  • exceptions: library-defined error hierarchy

The package root acts as a namespace, not a facade. Consumers are expected to import functionality explicitly from the appropriate module.


Installation

Install using pip:

pip install mail-intake

Or with Poetry:

poetry add mail-intake

Mail Intake is pure Python and has no runtime dependencies beyond those required by the selected provider (for example, Google APIs for Gmail).


Basic Usage

Minimal Gmail ingestion example (local development):

from mail_intake.ingestion import MailIntakeReader
from mail_intake.adapters import MailIntakeGmailAdapter
from mail_intake.auth import MailIntakeGoogleAuth
from mail_intake.credentials import PickleCredentialStore

store = PickleCredentialStore(path="token.pickle")

auth = MailIntakeGoogleAuth(
    credentials_path="credentials.json",
    store=store,
    scopes=["https://www.googleapis.com/auth/gmail.readonly"],
)

adapter = MailIntakeGmailAdapter(auth_provider=auth)
reader = MailIntakeReader(adapter)

for message in reader.iter_messages("from:recruiter@example.com"):
    print(message.subject, message.from_email)

Iterating over threads:

for thread in reader.iter_threads("subject:Interview"):
    print(thread.normalized_subject, len(thread.messages))

Extensibility Model

Mail Intake is designed to be extensible via public contracts exposed through its modules:

  • Users MAY implement their own mail adapters by subclassing adapters.MailIntakeAdapter
  • Users MAY implement their own authentication providers by subclassing auth.MailIntakeAuthProvider[T]
  • Users MAY implement their own credential persistence layers by implementing credentials.CredentialStore[T]

Users SHOULD NOT subclass built-in adapter implementations. Built-in adapters (such as Gmail) are reference implementations and may change internally without notice.


Public API Surface

The supported public API consists of the following top-level modules:

  • mail_intake.ingestion
  • mail_intake.adapters
  • mail_intake.auth
  • mail_intake.credentials
  • mail_intake.parsers
  • mail_intake.models
  • mail_intake.config
  • mail_intake.exceptions

Classes and functions should be imported explicitly from these modules. No individual symbols are re-exported at the package root.


Design Guarantees

  • Read-only access: no mutation of provider state
  • Provider-agnostic domain models
  • Explicit configuration and dependency injection
  • No implicit global state or environment reads
  • Deterministic, testable behavior
  • Distributed-safe authentication design

Mail Intake favors correctness, clarity, and explicitness over convenience shortcuts.

Core Philosophy

Mail Intake is built as a contract-first ingestion pipeline:

  1. Layered Decoupling: Adapters handle transport, Parsers handle format normalization, and Ingestion orchestrates.
  2. Provider Agnosticism: Domain models and core logic never depend on provider-specific (e.g., Gmail) API internals.
  3. Stateless Workflows: The library functions as a read-only pipe, ensuring side-effect-free ingestion.

Documentation Design

Follow these "AI-Native" docstring principles across the codebase:

For Humans
  • Namespace Clarity: Always specify which module a class or function belongs to.
  • Contract Explanations: Use the adapters and auth base classes to explain extension requirements.
For LLMs
  • Dotted Paths: Use full dotted paths in docstrings to help agents link concepts across modules.
  • Typed Interfaces: Provide .pyi stubs for every public module to ensure perfect context for AI coding tools.
  • Canonical Exceptions: Always use : description pairs in Raises blocks to enable structured error analysis.