From 370d1272bff3c6a88c4c2fad1cb74b597e6f2fd9 Mon Sep 17 00:00:00 2001 From: Vishesh 'ironeagle' Bangotra Date: Wed, 16 Sep 2026 20:02:50 +0530 Subject: [PATCH] docs: add wiki and refresh flat lib with mcp artifacts - Add hand-written wiki (index, overview, how-to, extending, dev) following the platform anatomy - Remove stale nested docs/lib/mail_intake and regenerate the flat lib reference to match docforge.nav.yml - Regenerate MCP bundle with standardized docstrings --- docs/lib/index.md | 1 - docs/lib/mail_intake/adapters/base.md | 3 - docs/lib/mail_intake/adapters/gmail.md | 3 - docs/lib/mail_intake/adapters/index.md | 5 - docs/lib/mail_intake/auth/base.md | 3 - docs/lib/mail_intake/auth/google.md | 3 - docs/lib/mail_intake/auth/index.md | 5 - docs/lib/mail_intake/config.md | 3 - docs/lib/mail_intake/credentials/index.md | 6 - docs/lib/mail_intake/credentials/pickle.md | 3 - docs/lib/mail_intake/credentials/redis.md | 3 - docs/lib/mail_intake/credentials/store.md | 3 - docs/lib/mail_intake/exceptions.md | 3 - docs/lib/mail_intake/index.md | 11 - docs/lib/mail_intake/ingestion/index.md | 4 - docs/lib/mail_intake/ingestion/reader.md | 3 - docs/lib/mail_intake/models/index.md | 5 - docs/lib/mail_intake/models/message.md | 3 - docs/lib/mail_intake/models/thread.md | 3 - docs/lib/mail_intake/parsers/body.md | 3 - docs/lib/mail_intake/parsers/headers.md | 3 - docs/lib/mail_intake/parsers/index.md | 6 - docs/lib/mail_intake/parsers/subject.md | 3 - docs/mcp/index.json | 2 +- .../modules/mail_intake.adapters.base.json | 36 +- .../modules/mail_intake.adapters.gmail.json | 50 +- docs/mcp/modules/mail_intake.adapters.json | 104 +-- docs/mcp/modules/mail_intake.auth.base.json | 32 +- docs/mcp/modules/mail_intake.auth.google.json | 67 +- docs/mcp/modules/mail_intake.auth.json | 113 +--- docs/mcp/modules/mail_intake.config.json | 9 +- docs/mcp/modules/mail_intake.credentials.json | 139 ++-- .../mail_intake.credentials.pickle.json | 30 +- .../mail_intake.credentials.redis.json | 37 +- .../mail_intake.credentials.store.json | 36 +- docs/mcp/modules/mail_intake.exceptions.json | 8 +- docs/mcp/modules/mail_intake.ingestion.json | 85 +-- .../modules/mail_intake.ingestion.reader.json | 79 +-- docs/mcp/modules/mail_intake.json | 599 +++++------------- docs/mcp/modules/mail_intake.models.json | 95 +-- .../modules/mail_intake.models.message.json | 16 +- .../modules/mail_intake.models.thread.json | 45 +- .../mcp/modules/mail_intake.parsers.body.json | 25 +- .../modules/mail_intake.parsers.headers.json | 4 +- docs/mcp/modules/mail_intake.parsers.json | 46 +- .../modules/mail_intake.parsers.subject.json | 9 +- docs/mkdocs.wiki.yml | 69 ++ docs/wiki/01_overview.md | 91 +++ docs/wiki/02_how_to_use.md | 105 +++ docs/wiki/03_extending.md | 106 ++++ docs/wiki/04_development.md | 88 +++ docs/wiki/index.md | 71 +++ 52 files changed, 936 insertions(+), 1348 deletions(-) delete mode 100644 docs/lib/mail_intake/adapters/base.md delete mode 100644 docs/lib/mail_intake/adapters/gmail.md delete mode 100644 docs/lib/mail_intake/adapters/index.md delete mode 100644 docs/lib/mail_intake/auth/base.md delete mode 100644 docs/lib/mail_intake/auth/google.md delete mode 100644 docs/lib/mail_intake/auth/index.md delete mode 100644 docs/lib/mail_intake/config.md delete mode 100644 docs/lib/mail_intake/credentials/index.md delete mode 100644 docs/lib/mail_intake/credentials/pickle.md delete mode 100644 docs/lib/mail_intake/credentials/redis.md delete mode 100644 docs/lib/mail_intake/credentials/store.md delete mode 100644 docs/lib/mail_intake/exceptions.md delete mode 100644 docs/lib/mail_intake/index.md delete mode 100644 docs/lib/mail_intake/ingestion/index.md delete mode 100644 docs/lib/mail_intake/ingestion/reader.md delete mode 100644 docs/lib/mail_intake/models/index.md delete mode 100644 docs/lib/mail_intake/models/message.md delete mode 100644 docs/lib/mail_intake/models/thread.md delete mode 100644 docs/lib/mail_intake/parsers/body.md delete mode 100644 docs/lib/mail_intake/parsers/headers.md delete mode 100644 docs/lib/mail_intake/parsers/index.md delete mode 100644 docs/lib/mail_intake/parsers/subject.md create mode 100644 docs/mkdocs.wiki.yml create mode 100644 docs/wiki/01_overview.md create mode 100644 docs/wiki/02_how_to_use.md create mode 100644 docs/wiki/03_extending.md create mode 100644 docs/wiki/04_development.md create mode 100644 docs/wiki/index.md diff --git a/docs/lib/index.md b/docs/lib/index.md index 7336caf..cb976a8 100644 --- a/docs/lib/index.md +++ b/docs/lib/index.md @@ -1,4 +1,3 @@ # mail_intake ::: mail_intake -- [Mail Intake](mail_intake/) diff --git a/docs/lib/mail_intake/adapters/base.md b/docs/lib/mail_intake/adapters/base.md deleted file mode 100644 index 309649c..0000000 --- a/docs/lib/mail_intake/adapters/base.md +++ /dev/null @@ -1,3 +0,0 @@ -# Base - -::: mail_intake.adapters.base diff --git a/docs/lib/mail_intake/adapters/gmail.md b/docs/lib/mail_intake/adapters/gmail.md deleted file mode 100644 index 13818cc..0000000 --- a/docs/lib/mail_intake/adapters/gmail.md +++ /dev/null @@ -1,3 +0,0 @@ -# Gmail - -::: mail_intake.adapters.gmail diff --git a/docs/lib/mail_intake/adapters/index.md b/docs/lib/mail_intake/adapters/index.md deleted file mode 100644 index 457cf71..0000000 --- a/docs/lib/mail_intake/adapters/index.md +++ /dev/null @@ -1,5 +0,0 @@ -# Adapters - -::: mail_intake.adapters -- [Base](base.md) -- [Gmail](gmail.md) diff --git a/docs/lib/mail_intake/auth/base.md b/docs/lib/mail_intake/auth/base.md deleted file mode 100644 index a1da95e..0000000 --- a/docs/lib/mail_intake/auth/base.md +++ /dev/null @@ -1,3 +0,0 @@ -# Base - -::: mail_intake.auth.base diff --git a/docs/lib/mail_intake/auth/google.md b/docs/lib/mail_intake/auth/google.md deleted file mode 100644 index 93e3086..0000000 --- a/docs/lib/mail_intake/auth/google.md +++ /dev/null @@ -1,3 +0,0 @@ -# Google - -::: mail_intake.auth.google diff --git a/docs/lib/mail_intake/auth/index.md b/docs/lib/mail_intake/auth/index.md deleted file mode 100644 index 29bed92..0000000 --- a/docs/lib/mail_intake/auth/index.md +++ /dev/null @@ -1,5 +0,0 @@ -# Auth - -::: mail_intake.auth -- [Base](base.md) -- [Google](google.md) diff --git a/docs/lib/mail_intake/config.md b/docs/lib/mail_intake/config.md deleted file mode 100644 index 355fbef..0000000 --- a/docs/lib/mail_intake/config.md +++ /dev/null @@ -1,3 +0,0 @@ -# Config - -::: mail_intake.config diff --git a/docs/lib/mail_intake/credentials/index.md b/docs/lib/mail_intake/credentials/index.md deleted file mode 100644 index a59e6ec..0000000 --- a/docs/lib/mail_intake/credentials/index.md +++ /dev/null @@ -1,6 +0,0 @@ -# Credentials - -::: mail_intake.credentials -- [Pickle](pickle.md) -- [Redis](redis.md) -- [Store](store.md) diff --git a/docs/lib/mail_intake/credentials/pickle.md b/docs/lib/mail_intake/credentials/pickle.md deleted file mode 100644 index 36f450d..0000000 --- a/docs/lib/mail_intake/credentials/pickle.md +++ /dev/null @@ -1,3 +0,0 @@ -# Pickle - -::: mail_intake.credentials.pickle diff --git a/docs/lib/mail_intake/credentials/redis.md b/docs/lib/mail_intake/credentials/redis.md deleted file mode 100644 index a62ff87..0000000 --- a/docs/lib/mail_intake/credentials/redis.md +++ /dev/null @@ -1,3 +0,0 @@ -# Redis - -::: mail_intake.credentials.redis diff --git a/docs/lib/mail_intake/credentials/store.md b/docs/lib/mail_intake/credentials/store.md deleted file mode 100644 index 14d4841..0000000 --- a/docs/lib/mail_intake/credentials/store.md +++ /dev/null @@ -1,3 +0,0 @@ -# Store - -::: mail_intake.credentials.store diff --git a/docs/lib/mail_intake/exceptions.md b/docs/lib/mail_intake/exceptions.md deleted file mode 100644 index 6ac1bf2..0000000 --- a/docs/lib/mail_intake/exceptions.md +++ /dev/null @@ -1,3 +0,0 @@ -# Exceptions - -::: mail_intake.exceptions diff --git a/docs/lib/mail_intake/index.md b/docs/lib/mail_intake/index.md deleted file mode 100644 index abc2259..0000000 --- a/docs/lib/mail_intake/index.md +++ /dev/null @@ -1,11 +0,0 @@ -# Mail Intake - -::: mail_intake -- [Adapters](adapters/) -- [Auth](auth/) -- [Config](config.md) -- [Credentials](credentials/) -- [Exceptions](exceptions.md) -- [Ingestion](ingestion/) -- [Models](models/) -- [Parsers](parsers/) diff --git a/docs/lib/mail_intake/ingestion/index.md b/docs/lib/mail_intake/ingestion/index.md deleted file mode 100644 index 7193c72..0000000 --- a/docs/lib/mail_intake/ingestion/index.md +++ /dev/null @@ -1,4 +0,0 @@ -# Ingestion - -::: mail_intake.ingestion -- [Reader](reader.md) diff --git a/docs/lib/mail_intake/ingestion/reader.md b/docs/lib/mail_intake/ingestion/reader.md deleted file mode 100644 index 690d9d9..0000000 --- a/docs/lib/mail_intake/ingestion/reader.md +++ /dev/null @@ -1,3 +0,0 @@ -# Reader - -::: mail_intake.ingestion.reader diff --git a/docs/lib/mail_intake/models/index.md b/docs/lib/mail_intake/models/index.md deleted file mode 100644 index ea55662..0000000 --- a/docs/lib/mail_intake/models/index.md +++ /dev/null @@ -1,5 +0,0 @@ -# Models - -::: mail_intake.models -- [Message](message.md) -- [Thread](thread.md) diff --git a/docs/lib/mail_intake/models/message.md b/docs/lib/mail_intake/models/message.md deleted file mode 100644 index b460397..0000000 --- a/docs/lib/mail_intake/models/message.md +++ /dev/null @@ -1,3 +0,0 @@ -# Message - -::: mail_intake.models.message diff --git a/docs/lib/mail_intake/models/thread.md b/docs/lib/mail_intake/models/thread.md deleted file mode 100644 index 74d3cc2..0000000 --- a/docs/lib/mail_intake/models/thread.md +++ /dev/null @@ -1,3 +0,0 @@ -# Thread - -::: mail_intake.models.thread diff --git a/docs/lib/mail_intake/parsers/body.md b/docs/lib/mail_intake/parsers/body.md deleted file mode 100644 index 2cf14af..0000000 --- a/docs/lib/mail_intake/parsers/body.md +++ /dev/null @@ -1,3 +0,0 @@ -# Body - -::: mail_intake.parsers.body diff --git a/docs/lib/mail_intake/parsers/headers.md b/docs/lib/mail_intake/parsers/headers.md deleted file mode 100644 index 8192602..0000000 --- a/docs/lib/mail_intake/parsers/headers.md +++ /dev/null @@ -1,3 +0,0 @@ -# Headers - -::: mail_intake.parsers.headers diff --git a/docs/lib/mail_intake/parsers/index.md b/docs/lib/mail_intake/parsers/index.md deleted file mode 100644 index b5e3b8e..0000000 --- a/docs/lib/mail_intake/parsers/index.md +++ /dev/null @@ -1,6 +0,0 @@ -# Parsers - -::: mail_intake.parsers -- [Body](body.md) -- [Headers](headers.md) -- [Subject](subject.md) diff --git a/docs/lib/mail_intake/parsers/subject.md b/docs/lib/mail_intake/parsers/subject.md deleted file mode 100644 index 50bdd01..0000000 --- a/docs/lib/mail_intake/parsers/subject.md +++ /dev/null @@ -1,3 +0,0 @@ -# Subject - -::: mail_intake.parsers.subject diff --git a/docs/mcp/index.json b/docs/mcp/index.json index d4d506d..2685f38 100644 --- a/docs/mcp/index.json +++ b/docs/mcp/index.json @@ -1,5 +1,5 @@ { - "project": "mail_intake", + "project": "Mail Intake", "type": "docforge-model", "modules_count": 22, "source": "docforge" diff --git a/docs/mcp/modules/mail_intake.adapters.base.json b/docs/mcp/modules/mail_intake.adapters.base.json index 3612a5b..2e966cf 100644 --- a/docs/mcp/modules/mail_intake.adapters.base.json +++ b/docs/mcp/modules/mail_intake.adapters.base.json @@ -4,60 +4,32 @@ "path": "mail_intake.adapters.base", "docstring": "# Summary\n\nMail provider adapter contracts for Mail Intake.\n\nThis module defines the **provider-agnostic adapter interface** used for\nread-only mail ingestion.\n\nAdapters encapsulate all provider-specific access logic and expose a\nminimal, normalized contract to the rest of the system. No provider-specific\ntypes or semantics should leak beyond implementations of this interface.", "objects": { - "ABC": { - "name": "ABC", - "kind": "alias", - "path": "mail_intake.adapters.base.ABC", - "signature": "", - "docstring": null - }, - "abstractmethod": { - "name": "abstractmethod", - "kind": "alias", - "path": "mail_intake.adapters.base.abstractmethod", - "signature": "", - "docstring": null - }, - "Iterator": { - "name": "Iterator", - "kind": "alias", - "path": "mail_intake.adapters.base.Iterator", - "signature": "", - "docstring": null - }, - "Any": { - "name": "Any", - "kind": "alias", - "path": "mail_intake.adapters.base.Any", - "signature": "", - "docstring": null - }, "MailIntakeAdapter": { "name": "MailIntakeAdapter", "kind": "class", "path": "mail_intake.adapters.base.MailIntakeAdapter", - "signature": "", + "signature": null, "docstring": "Base adapter interface for mail providers.\n\nNotes:\n **Guarantees:**\n\n - Discover messages matching a query.\n - Retrieve full message payloads.\n - Retrieve full thread payloads.\n\n **Lifecycle:**\n\n - Adapters are intentionally read-only and must not mutate provider state.", "members": { "iter_message_refs": { "name": "iter_message_refs", "kind": "function", "path": "mail_intake.adapters.base.MailIntakeAdapter.iter_message_refs", - "signature": "", + "signature": "iter_message_refs(query: str) -> Iterator[dict[str, str]]", "docstring": "Iterate over lightweight message references matching a query.\n\nArgs:\n query (str):\n Provider-specific query string used to filter messages.\n\nReturns:\n Iterator[dict[str, str]]:\n An iterator over lightweight message reference dictionaries.\n\nYields:\n dict[str, str]:\n Dictionaries containing message and thread identifiers.\n\nNotes:\n **Guarantees:**\n\n - Implementations must yield dictionaries containing at least\n `message_id` and `thread_id`.\n\nExample:\n Typical yield:\n\n ```python\n {\n \"message_id\": \"...\",\n \"thread_id\": \"...\"\n }\n ```" }, "fetch_message": { "name": "fetch_message", "kind": "function", "path": "mail_intake.adapters.base.MailIntakeAdapter.fetch_message", - "signature": "", + "signature": "fetch_message(message_id: str) -> dict[str, Any]", "docstring": "Fetch a full raw message by message identifier.\n\nArgs:\n message_id (str):\n Provider-specific message identifier.\n\nReturns:\n dict[str, Any]:\n Provider-native message payload (e.g., Gmail message JSON structure)." }, "fetch_thread": { "name": "fetch_thread", "kind": "function", "path": "mail_intake.adapters.base.MailIntakeAdapter.fetch_thread", - "signature": "", + "signature": "fetch_thread(thread_id: str) -> dict[str, Any]", "docstring": "Fetch a full raw thread by thread identifier.\n\nArgs:\n thread_id (str):\n Provider-specific thread identifier.\n\nReturns:\n dict[str, Any]:\n Provider-native thread payload." } } diff --git a/docs/mcp/modules/mail_intake.adapters.gmail.json b/docs/mcp/modules/mail_intake.adapters.gmail.json index 570317b..d23b381 100644 --- a/docs/mcp/modules/mail_intake.adapters.gmail.json +++ b/docs/mcp/modules/mail_intake.adapters.gmail.json @@ -4,60 +4,32 @@ "path": "mail_intake.adapters.gmail", "docstring": "# Summary\n\nGmail adapter implementation for Mail Intake.\n\nThis module provides a **Gmail-specific implementation** of the\n`MailIntakeAdapter` contract.\n\nIt is the only place in the codebase where:\n\n- `googleapiclient` is imported.\n- Gmail REST API semantics are known.\n- Low-level `.execute()` calls are made.\n\nAll Gmail-specific behavior must be strictly contained within this module.", "objects": { - "Iterator": { - "name": "Iterator", - "kind": "alias", - "path": "mail_intake.adapters.gmail.Iterator", - "signature": "", - "docstring": null - }, - "Any": { - "name": "Any", - "kind": "alias", - "path": "mail_intake.adapters.gmail.Any", - "signature": "", - "docstring": null - }, - "build": { - "name": "build", - "kind": "alias", - "path": "mail_intake.adapters.gmail.build", - "signature": "", - "docstring": null - }, - "HttpError": { - "name": "HttpError", - "kind": "alias", - "path": "mail_intake.adapters.gmail.HttpError", - "signature": "", - "docstring": null - }, "MailIntakeAdapter": { "name": "MailIntakeAdapter", "kind": "class", "path": "mail_intake.adapters.gmail.MailIntakeAdapter", - "signature": "", + "signature": null, "docstring": "Base adapter interface for mail providers.\n\nNotes:\n **Guarantees:**\n\n - Discover messages matching a query.\n - Retrieve full message payloads.\n - Retrieve full thread payloads.\n\n **Lifecycle:**\n\n - Adapters are intentionally read-only and must not mutate provider state.", "members": { "iter_message_refs": { "name": "iter_message_refs", "kind": "function", "path": "mail_intake.adapters.gmail.MailIntakeAdapter.iter_message_refs", - "signature": "", + "signature": "iter_message_refs(query: str)", "docstring": "Iterate over lightweight message references matching a query.\n\nArgs:\n query (str):\n Provider-specific query string used to filter messages.\n\nReturns:\n Iterator[dict[str, str]]:\n An iterator over lightweight message reference dictionaries.\n\nYields:\n dict[str, str]:\n Dictionaries containing message and thread identifiers.\n\nNotes:\n **Guarantees:**\n\n - Implementations must yield dictionaries containing at least\n `message_id` and `thread_id`.\n\nExample:\n Typical yield:\n\n ```python\n {\n \"message_id\": \"...\",\n \"thread_id\": \"...\"\n }\n ```" }, "fetch_message": { "name": "fetch_message", "kind": "function", "path": "mail_intake.adapters.gmail.MailIntakeAdapter.fetch_message", - "signature": "", + "signature": "fetch_message(message_id: str)", "docstring": "Fetch a full raw message by message identifier.\n\nArgs:\n message_id (str):\n Provider-specific message identifier.\n\nReturns:\n dict[str, Any]:\n Provider-native message payload (e.g., Gmail message JSON structure)." }, "fetch_thread": { "name": "fetch_thread", "kind": "function", "path": "mail_intake.adapters.gmail.MailIntakeAdapter.fetch_thread", - "signature": "", + "signature": "fetch_thread(thread_id: str)", "docstring": "Fetch a full raw thread by thread identifier.\n\nArgs:\n thread_id (str):\n Provider-specific thread identifier.\n\nReturns:\n dict[str, Any]:\n Provider-native thread payload." } } @@ -66,14 +38,14 @@ "name": "MailIntakeAuthProvider", "kind": "class", "path": "mail_intake.adapters.gmail.MailIntakeAuthProvider", - "signature": "", + "signature": null, "docstring": "Abstract base class for authentication providers.\n\nThis interface enforces a strict contract between authentication\nproviders and mail adapters by requiring providers to explicitly\ndeclare the type of credentials they return.\n\nNotes:\n **Responsibilities:**\n\n - Acquire credentials from an external provider.\n - Refresh or revalidate credentials as needed.\n - Handle authentication-specific failure modes.\n - Coordinate with credential persistence layers where applicable.\n\n **Constraints:**\n\n - Mail adapters must treat returned credentials as opaque and\n provider-specific.\n - Mail adapters rely only on the declared credential type expected\n by the adapter.", "members": { "get_credentials": { "name": "get_credentials", "kind": "function", "path": "mail_intake.adapters.gmail.MailIntakeAuthProvider.get_credentials", - "signature": "", + "signature": "get_credentials()", "docstring": "Retrieve valid, provider-specific credentials.\n\nReturns:\n T:\n Credentials of type `T` suitable for immediate use by the\n corresponding mail adapter.\n\nRaises:\n Exception:\n An authentication-specific exception indicating that\n credentials could not be obtained or validated.\n\nNotes:\n **Guarantees:**\n\n - This method is synchronous by design.\n - Represents the sole entry point through which adapters obtain\n authentication material.\n - Implementations must either return credentials of the declared\n type `T` that are valid at the time of return or raise an exception." } } @@ -82,14 +54,14 @@ "name": "MailIntakeAdapterError", "kind": "class", "path": "mail_intake.adapters.gmail.MailIntakeAdapterError", - "signature": "", + "signature": null, "docstring": "Errors raised by mail provider adapters.\n\nNotes:\n **Lifecycle:**\n\n - Raised when a provider adapter encounters API errors, transport\n failures, or invalid provider responses." }, "MailIntakeGmailAdapter": { "name": "MailIntakeGmailAdapter", "kind": "class", "path": "mail_intake.adapters.gmail.MailIntakeGmailAdapter", - "signature": "", + "signature": "MailIntakeGmailAdapter(auth_provider: MailIntakeAuthProvider[Any], user_id: str = 'me')", "docstring": "Gmail read-only adapter.\n\nThis adapter implements the `MailIntakeAdapter` interface using the\nGmail REST API. It translates the generic mail intake contract into\nGmail-specific API calls.\n\nNotes:\n **Responsibilities:**\n\n - This class is the ONLY place where `googleapiclient` is imported.\n - Gmail REST semantics are known.\n - `.execute()` is called.\n\n **Constraints:**\n\n - Must remain thin and imperative.\n - Must not perform parsing or interpretation.\n - Must not expose Gmail-specific types beyond this class.", "members": { "service": { @@ -103,21 +75,21 @@ "name": "iter_message_refs", "kind": "function", "path": "mail_intake.adapters.gmail.MailIntakeGmailAdapter.iter_message_refs", - "signature": "", + "signature": "iter_message_refs(query: str) -> Iterator[dict[str, str]]", "docstring": "Iterate over message references matching the query.\n\nArgs:\n query (str):\n Gmail search query string.\n\nYields:\n dict[str, str]:\n Dictionaries containing ``message_id`` and ``thread_id``.\n\nRaises:\n MailIntakeAdapterError:\n If the Gmail API returns an error." }, "fetch_message": { "name": "fetch_message", "kind": "function", "path": "mail_intake.adapters.gmail.MailIntakeGmailAdapter.fetch_message", - "signature": "", + "signature": "fetch_message(message_id: str) -> dict[str, Any]", "docstring": "Fetch a full Gmail message by message ID.\n\nArgs:\n message_id (str):\n Gmail message identifier.\n\nReturns:\n dict[str, Any]:\n Provider-native Gmail message payload.\n\nRaises:\n MailIntakeAdapterError:\n If the Gmail API returns an error." }, "fetch_thread": { "name": "fetch_thread", "kind": "function", "path": "mail_intake.adapters.gmail.MailIntakeGmailAdapter.fetch_thread", - "signature": "", + "signature": "fetch_thread(thread_id: str) -> dict[str, Any]", "docstring": "Fetch a full Gmail thread by thread ID.\n\nArgs:\n thread_id (str):\n Gmail thread identifier.\n\nReturns:\n dict[str, Any]:\n Provider-native Gmail thread payload.\n\nRaises:\n MailIntakeAdapterError:\n If the Gmail API returns an error." } } diff --git a/docs/mcp/modules/mail_intake.adapters.json b/docs/mcp/modules/mail_intake.adapters.json index 7d52c53..c2bbab4 100644 --- a/docs/mcp/modules/mail_intake.adapters.json +++ b/docs/mcp/modules/mail_intake.adapters.json @@ -8,28 +8,28 @@ "name": "MailIntakeAdapter", "kind": "class", "path": "mail_intake.adapters.MailIntakeAdapter", - "signature": "", + "signature": null, "docstring": "Base adapter interface for mail providers.\n\nNotes:\n **Guarantees:**\n\n - Discover messages matching a query.\n - Retrieve full message payloads.\n - Retrieve full thread payloads.\n\n **Lifecycle:**\n\n - Adapters are intentionally read-only and must not mutate provider state.", "members": { "iter_message_refs": { "name": "iter_message_refs", "kind": "function", "path": "mail_intake.adapters.MailIntakeAdapter.iter_message_refs", - "signature": "", + "signature": "iter_message_refs(query: str)", "docstring": "Iterate over lightweight message references matching a query.\n\nArgs:\n query (str):\n Provider-specific query string used to filter messages.\n\nReturns:\n Iterator[dict[str, str]]:\n An iterator over lightweight message reference dictionaries.\n\nYields:\n dict[str, str]:\n Dictionaries containing message and thread identifiers.\n\nNotes:\n **Guarantees:**\n\n - Implementations must yield dictionaries containing at least\n `message_id` and `thread_id`.\n\nExample:\n Typical yield:\n\n ```python\n {\n \"message_id\": \"...\",\n \"thread_id\": \"...\"\n }\n ```" }, "fetch_message": { "name": "fetch_message", "kind": "function", "path": "mail_intake.adapters.MailIntakeAdapter.fetch_message", - "signature": "", + "signature": "fetch_message(message_id: str)", "docstring": "Fetch a full raw message by message identifier.\n\nArgs:\n message_id (str):\n Provider-specific message identifier.\n\nReturns:\n dict[str, Any]:\n Provider-native message payload (e.g., Gmail message JSON structure)." }, "fetch_thread": { "name": "fetch_thread", "kind": "function", "path": "mail_intake.adapters.MailIntakeAdapter.fetch_thread", - "signature": "", + "signature": "fetch_thread(thread_id: str)", "docstring": "Fetch a full raw thread by thread identifier.\n\nArgs:\n thread_id (str):\n Provider-specific thread identifier.\n\nReturns:\n dict[str, Any]:\n Provider-native thread payload." } } @@ -38,35 +38,35 @@ "name": "MailIntakeGmailAdapter", "kind": "class", "path": "mail_intake.adapters.MailIntakeGmailAdapter", - "signature": "", + "signature": "MailIntakeGmailAdapter(auth_provider: MailIntakeAuthProvider[Any], user_id: str = 'me')", "docstring": "Gmail read-only adapter.\n\nThis adapter implements the `MailIntakeAdapter` interface using the\nGmail REST API. It translates the generic mail intake contract into\nGmail-specific API calls.\n\nNotes:\n **Responsibilities:**\n\n - This class is the ONLY place where `googleapiclient` is imported.\n - Gmail REST semantics are known.\n - `.execute()` is called.\n\n **Constraints:**\n\n - Must remain thin and imperative.\n - Must not perform parsing or interpretation.\n - Must not expose Gmail-specific types beyond this class.", "members": { "service": { "name": "service", "kind": "attribute", "path": "mail_intake.adapters.MailIntakeGmailAdapter.service", - "signature": "", + "signature": null, "docstring": "Lazily initialize and return the Gmail API service client.\n\nRaises:\n MailIntakeAdapterError:\n If the Gmail service cannot be initialized." }, "iter_message_refs": { "name": "iter_message_refs", "kind": "function", "path": "mail_intake.adapters.MailIntakeGmailAdapter.iter_message_refs", - "signature": "", + "signature": "iter_message_refs(query: str)", "docstring": "Iterate over message references matching the query.\n\nArgs:\n query (str):\n Gmail search query string.\n\nYields:\n dict[str, str]:\n Dictionaries containing ``message_id`` and ``thread_id``.\n\nRaises:\n MailIntakeAdapterError:\n If the Gmail API returns an error." }, "fetch_message": { "name": "fetch_message", "kind": "function", "path": "mail_intake.adapters.MailIntakeGmailAdapter.fetch_message", - "signature": "", + "signature": "fetch_message(message_id: str)", "docstring": "Fetch a full Gmail message by message ID.\n\nArgs:\n message_id (str):\n Gmail message identifier.\n\nReturns:\n dict[str, Any]:\n Provider-native Gmail message payload.\n\nRaises:\n MailIntakeAdapterError:\n If the Gmail API returns an error." }, "fetch_thread": { "name": "fetch_thread", "kind": "function", "path": "mail_intake.adapters.MailIntakeGmailAdapter.fetch_thread", - "signature": "", + "signature": "fetch_thread(thread_id: str)", "docstring": "Fetch a full Gmail thread by thread ID.\n\nArgs:\n thread_id (str):\n Gmail thread identifier.\n\nReturns:\n dict[str, Any]:\n Provider-native Gmail thread payload.\n\nRaises:\n MailIntakeAdapterError:\n If the Gmail API returns an error." } } @@ -78,60 +78,32 @@ "signature": null, "docstring": "# Summary\n\nMail provider adapter contracts for Mail Intake.\n\nThis module defines the **provider-agnostic adapter interface** used for\nread-only mail ingestion.\n\nAdapters encapsulate all provider-specific access logic and expose a\nminimal, normalized contract to the rest of the system. No provider-specific\ntypes or semantics should leak beyond implementations of this interface.", "members": { - "ABC": { - "name": "ABC", - "kind": "alias", - "path": "mail_intake.adapters.base.ABC", - "signature": "", - "docstring": null - }, - "abstractmethod": { - "name": "abstractmethod", - "kind": "alias", - "path": "mail_intake.adapters.base.abstractmethod", - "signature": "", - "docstring": null - }, - "Iterator": { - "name": "Iterator", - "kind": "alias", - "path": "mail_intake.adapters.base.Iterator", - "signature": "", - "docstring": null - }, - "Any": { - "name": "Any", - "kind": "alias", - "path": "mail_intake.adapters.base.Any", - "signature": "", - "docstring": null - }, "MailIntakeAdapter": { "name": "MailIntakeAdapter", "kind": "class", "path": "mail_intake.adapters.base.MailIntakeAdapter", - "signature": "", + "signature": null, "docstring": "Base adapter interface for mail providers.\n\nNotes:\n **Guarantees:**\n\n - Discover messages matching a query.\n - Retrieve full message payloads.\n - Retrieve full thread payloads.\n\n **Lifecycle:**\n\n - Adapters are intentionally read-only and must not mutate provider state.", "members": { "iter_message_refs": { "name": "iter_message_refs", "kind": "function", "path": "mail_intake.adapters.base.MailIntakeAdapter.iter_message_refs", - "signature": "", + "signature": "iter_message_refs(query: str) -> Iterator[dict[str, str]]", "docstring": "Iterate over lightweight message references matching a query.\n\nArgs:\n query (str):\n Provider-specific query string used to filter messages.\n\nReturns:\n Iterator[dict[str, str]]:\n An iterator over lightweight message reference dictionaries.\n\nYields:\n dict[str, str]:\n Dictionaries containing message and thread identifiers.\n\nNotes:\n **Guarantees:**\n\n - Implementations must yield dictionaries containing at least\n `message_id` and `thread_id`.\n\nExample:\n Typical yield:\n\n ```python\n {\n \"message_id\": \"...\",\n \"thread_id\": \"...\"\n }\n ```" }, "fetch_message": { "name": "fetch_message", "kind": "function", "path": "mail_intake.adapters.base.MailIntakeAdapter.fetch_message", - "signature": "", + "signature": "fetch_message(message_id: str) -> dict[str, Any]", "docstring": "Fetch a full raw message by message identifier.\n\nArgs:\n message_id (str):\n Provider-specific message identifier.\n\nReturns:\n dict[str, Any]:\n Provider-native message payload (e.g., Gmail message JSON structure)." }, "fetch_thread": { "name": "fetch_thread", "kind": "function", "path": "mail_intake.adapters.base.MailIntakeAdapter.fetch_thread", - "signature": "", + "signature": "fetch_thread(thread_id: str) -> dict[str, Any]", "docstring": "Fetch a full raw thread by thread identifier.\n\nArgs:\n thread_id (str):\n Provider-specific thread identifier.\n\nReturns:\n dict[str, Any]:\n Provider-native thread payload." } } @@ -145,60 +117,32 @@ "signature": null, "docstring": "# Summary\n\nGmail adapter implementation for Mail Intake.\n\nThis module provides a **Gmail-specific implementation** of the\n`MailIntakeAdapter` contract.\n\nIt is the only place in the codebase where:\n\n- `googleapiclient` is imported.\n- Gmail REST API semantics are known.\n- Low-level `.execute()` calls are made.\n\nAll Gmail-specific behavior must be strictly contained within this module.", "members": { - "Iterator": { - "name": "Iterator", - "kind": "alias", - "path": "mail_intake.adapters.gmail.Iterator", - "signature": "", - "docstring": null - }, - "Any": { - "name": "Any", - "kind": "alias", - "path": "mail_intake.adapters.gmail.Any", - "signature": "", - "docstring": null - }, - "build": { - "name": "build", - "kind": "alias", - "path": "mail_intake.adapters.gmail.build", - "signature": "", - "docstring": null - }, - "HttpError": { - "name": "HttpError", - "kind": "alias", - "path": "mail_intake.adapters.gmail.HttpError", - "signature": "", - "docstring": null - }, "MailIntakeAdapter": { "name": "MailIntakeAdapter", "kind": "class", "path": "mail_intake.adapters.gmail.MailIntakeAdapter", - "signature": "", + "signature": null, "docstring": "Base adapter interface for mail providers.\n\nNotes:\n **Guarantees:**\n\n - Discover messages matching a query.\n - Retrieve full message payloads.\n - Retrieve full thread payloads.\n\n **Lifecycle:**\n\n - Adapters are intentionally read-only and must not mutate provider state.", "members": { "iter_message_refs": { "name": "iter_message_refs", "kind": "function", "path": "mail_intake.adapters.gmail.MailIntakeAdapter.iter_message_refs", - "signature": "", + "signature": "iter_message_refs(query: str)", "docstring": "Iterate over lightweight message references matching a query.\n\nArgs:\n query (str):\n Provider-specific query string used to filter messages.\n\nReturns:\n Iterator[dict[str, str]]:\n An iterator over lightweight message reference dictionaries.\n\nYields:\n dict[str, str]:\n Dictionaries containing message and thread identifiers.\n\nNotes:\n **Guarantees:**\n\n - Implementations must yield dictionaries containing at least\n `message_id` and `thread_id`.\n\nExample:\n Typical yield:\n\n ```python\n {\n \"message_id\": \"...\",\n \"thread_id\": \"...\"\n }\n ```" }, "fetch_message": { "name": "fetch_message", "kind": "function", "path": "mail_intake.adapters.gmail.MailIntakeAdapter.fetch_message", - "signature": "", + "signature": "fetch_message(message_id: str)", "docstring": "Fetch a full raw message by message identifier.\n\nArgs:\n message_id (str):\n Provider-specific message identifier.\n\nReturns:\n dict[str, Any]:\n Provider-native message payload (e.g., Gmail message JSON structure)." }, "fetch_thread": { "name": "fetch_thread", "kind": "function", "path": "mail_intake.adapters.gmail.MailIntakeAdapter.fetch_thread", - "signature": "", + "signature": "fetch_thread(thread_id: str)", "docstring": "Fetch a full raw thread by thread identifier.\n\nArgs:\n thread_id (str):\n Provider-specific thread identifier.\n\nReturns:\n dict[str, Any]:\n Provider-native thread payload." } } @@ -207,14 +151,14 @@ "name": "MailIntakeAuthProvider", "kind": "class", "path": "mail_intake.adapters.gmail.MailIntakeAuthProvider", - "signature": "", + "signature": null, "docstring": "Abstract base class for authentication providers.\n\nThis interface enforces a strict contract between authentication\nproviders and mail adapters by requiring providers to explicitly\ndeclare the type of credentials they return.\n\nNotes:\n **Responsibilities:**\n\n - Acquire credentials from an external provider.\n - Refresh or revalidate credentials as needed.\n - Handle authentication-specific failure modes.\n - Coordinate with credential persistence layers where applicable.\n\n **Constraints:**\n\n - Mail adapters must treat returned credentials as opaque and\n provider-specific.\n - Mail adapters rely only on the declared credential type expected\n by the adapter.", "members": { "get_credentials": { "name": "get_credentials", "kind": "function", "path": "mail_intake.adapters.gmail.MailIntakeAuthProvider.get_credentials", - "signature": "", + "signature": "get_credentials()", "docstring": "Retrieve valid, provider-specific credentials.\n\nReturns:\n T:\n Credentials of type `T` suitable for immediate use by the\n corresponding mail adapter.\n\nRaises:\n Exception:\n An authentication-specific exception indicating that\n credentials could not be obtained or validated.\n\nNotes:\n **Guarantees:**\n\n - This method is synchronous by design.\n - Represents the sole entry point through which adapters obtain\n authentication material.\n - Implementations must either return credentials of the declared\n type `T` that are valid at the time of return or raise an exception." } } @@ -223,14 +167,14 @@ "name": "MailIntakeAdapterError", "kind": "class", "path": "mail_intake.adapters.gmail.MailIntakeAdapterError", - "signature": "", + "signature": null, "docstring": "Errors raised by mail provider adapters.\n\nNotes:\n **Lifecycle:**\n\n - Raised when a provider adapter encounters API errors, transport\n failures, or invalid provider responses." }, "MailIntakeGmailAdapter": { "name": "MailIntakeGmailAdapter", "kind": "class", "path": "mail_intake.adapters.gmail.MailIntakeGmailAdapter", - "signature": "", + "signature": "MailIntakeGmailAdapter(auth_provider: MailIntakeAuthProvider[Any], user_id: str = 'me')", "docstring": "Gmail read-only adapter.\n\nThis adapter implements the `MailIntakeAdapter` interface using the\nGmail REST API. It translates the generic mail intake contract into\nGmail-specific API calls.\n\nNotes:\n **Responsibilities:**\n\n - This class is the ONLY place where `googleapiclient` is imported.\n - Gmail REST semantics are known.\n - `.execute()` is called.\n\n **Constraints:**\n\n - Must remain thin and imperative.\n - Must not perform parsing or interpretation.\n - Must not expose Gmail-specific types beyond this class.", "members": { "service": { @@ -244,21 +188,21 @@ "name": "iter_message_refs", "kind": "function", "path": "mail_intake.adapters.gmail.MailIntakeGmailAdapter.iter_message_refs", - "signature": "", + "signature": "iter_message_refs(query: str) -> Iterator[dict[str, str]]", "docstring": "Iterate over message references matching the query.\n\nArgs:\n query (str):\n Gmail search query string.\n\nYields:\n dict[str, str]:\n Dictionaries containing ``message_id`` and ``thread_id``.\n\nRaises:\n MailIntakeAdapterError:\n If the Gmail API returns an error." }, "fetch_message": { "name": "fetch_message", "kind": "function", "path": "mail_intake.adapters.gmail.MailIntakeGmailAdapter.fetch_message", - "signature": "", + "signature": "fetch_message(message_id: str) -> dict[str, Any]", "docstring": "Fetch a full Gmail message by message ID.\n\nArgs:\n message_id (str):\n Gmail message identifier.\n\nReturns:\n dict[str, Any]:\n Provider-native Gmail message payload.\n\nRaises:\n MailIntakeAdapterError:\n If the Gmail API returns an error." }, "fetch_thread": { "name": "fetch_thread", "kind": "function", "path": "mail_intake.adapters.gmail.MailIntakeGmailAdapter.fetch_thread", - "signature": "", + "signature": "fetch_thread(thread_id: str) -> dict[str, Any]", "docstring": "Fetch a full Gmail thread by thread ID.\n\nArgs:\n thread_id (str):\n Gmail thread identifier.\n\nReturns:\n dict[str, Any]:\n Provider-native Gmail thread payload.\n\nRaises:\n MailIntakeAdapterError:\n If the Gmail API returns an error." } } diff --git a/docs/mcp/modules/mail_intake.auth.base.json b/docs/mcp/modules/mail_intake.auth.base.json index db333d6..0072a2d 100644 --- a/docs/mcp/modules/mail_intake.auth.base.json +++ b/docs/mcp/modules/mail_intake.auth.base.json @@ -4,34 +4,6 @@ "path": "mail_intake.auth.base", "docstring": "# Summary\n\nAuthentication provider contracts for Mail Intake.\n\nThis module defines the **authentication abstraction layer** used by mail\nadapters to obtain provider-specific credentials.\n\nAuthentication concerns are intentionally decoupled from adapter logic.\nAdapters depend only on this interface and must not be aware of how\ncredentials are acquired, refreshed, or persisted.", "objects": { - "ABC": { - "name": "ABC", - "kind": "alias", - "path": "mail_intake.auth.base.ABC", - "signature": "", - "docstring": null - }, - "abstractmethod": { - "name": "abstractmethod", - "kind": "alias", - "path": "mail_intake.auth.base.abstractmethod", - "signature": "", - "docstring": null - }, - "Generic": { - "name": "Generic", - "kind": "alias", - "path": "mail_intake.auth.base.Generic", - "signature": "", - "docstring": null - }, - "TypeVar": { - "name": "TypeVar", - "kind": "alias", - "path": "mail_intake.auth.base.TypeVar", - "signature": "", - "docstring": null - }, "T": { "name": "T", "kind": "attribute", @@ -43,14 +15,14 @@ "name": "MailIntakeAuthProvider", "kind": "class", "path": "mail_intake.auth.base.MailIntakeAuthProvider", - "signature": "", + "signature": null, "docstring": "Abstract base class for authentication providers.\n\nThis interface enforces a strict contract between authentication\nproviders and mail adapters by requiring providers to explicitly\ndeclare the type of credentials they return.\n\nNotes:\n **Responsibilities:**\n\n - Acquire credentials from an external provider.\n - Refresh or revalidate credentials as needed.\n - Handle authentication-specific failure modes.\n - Coordinate with credential persistence layers where applicable.\n\n **Constraints:**\n\n - Mail adapters must treat returned credentials as opaque and\n provider-specific.\n - Mail adapters rely only on the declared credential type expected\n by the adapter.", "members": { "get_credentials": { "name": "get_credentials", "kind": "function", "path": "mail_intake.auth.base.MailIntakeAuthProvider.get_credentials", - "signature": "", + "signature": "get_credentials() -> T", "docstring": "Retrieve valid, provider-specific credentials.\n\nReturns:\n T:\n Credentials of type `T` suitable for immediate use by the\n corresponding mail adapter.\n\nRaises:\n Exception:\n An authentication-specific exception indicating that\n credentials could not be obtained or validated.\n\nNotes:\n **Guarantees:**\n\n - This method is synchronous by design.\n - Represents the sole entry point through which adapters obtain\n authentication material.\n - Implementations must either return credentials of the declared\n type `T` that are valid at the time of return or raise an exception." } } diff --git a/docs/mcp/modules/mail_intake.auth.google.json b/docs/mcp/modules/mail_intake.auth.google.json index 4f2bba8..357f621 100644 --- a/docs/mcp/modules/mail_intake.auth.google.json +++ b/docs/mcp/modules/mail_intake.auth.google.json @@ -4,60 +4,18 @@ "path": "mail_intake.auth.google", "docstring": "# Summary\n\nGoogle authentication provider implementation for Mail Intake.\n\nThis module provides a **Google OAuth–based authentication provider**\nused primarily for Gmail access.\n\nIt encapsulates all Google-specific authentication concerns, including:\n\n- Credential loading and persistence.\n- Token refresh handling.\n- Interactive OAuth flow initiation.\n- Coordination with a credential persistence layer.\n\nNo Google authentication details should leak outside this module.", "objects": { - "os": { - "name": "os", - "kind": "alias", - "path": "mail_intake.auth.google.os", - "signature": "", - "docstring": null - }, - "Sequence": { - "name": "Sequence", - "kind": "alias", - "path": "mail_intake.auth.google.Sequence", - "signature": "", - "docstring": null - }, - "google": { - "name": "google", - "kind": "alias", - "path": "mail_intake.auth.google.google", - "signature": "", - "docstring": null - }, - "Request": { - "name": "Request", - "kind": "alias", - "path": "mail_intake.auth.google.Request", - "signature": "", - "docstring": null - }, - "Credentials": { - "name": "Credentials", - "kind": "alias", - "path": "mail_intake.auth.google.Credentials", - "signature": "", - "docstring": null - }, - "InstalledAppFlow": { - "name": "InstalledAppFlow", - "kind": "alias", - "path": "mail_intake.auth.google.InstalledAppFlow", - "signature": "", - "docstring": null - }, "MailIntakeAuthProvider": { "name": "MailIntakeAuthProvider", "kind": "class", "path": "mail_intake.auth.google.MailIntakeAuthProvider", - "signature": "", + "signature": null, "docstring": "Abstract base class for authentication providers.\n\nThis interface enforces a strict contract between authentication\nproviders and mail adapters by requiring providers to explicitly\ndeclare the type of credentials they return.\n\nNotes:\n **Responsibilities:**\n\n - Acquire credentials from an external provider.\n - Refresh or revalidate credentials as needed.\n - Handle authentication-specific failure modes.\n - Coordinate with credential persistence layers where applicable.\n\n **Constraints:**\n\n - Mail adapters must treat returned credentials as opaque and\n provider-specific.\n - Mail adapters rely only on the declared credential type expected\n by the adapter.", "members": { "get_credentials": { "name": "get_credentials", "kind": "function", "path": "mail_intake.auth.google.MailIntakeAuthProvider.get_credentials", - "signature": "", + "signature": "get_credentials()", "docstring": "Retrieve valid, provider-specific credentials.\n\nReturns:\n T:\n Credentials of type `T` suitable for immediate use by the\n corresponding mail adapter.\n\nRaises:\n Exception:\n An authentication-specific exception indicating that\n credentials could not be obtained or validated.\n\nNotes:\n **Guarantees:**\n\n - This method is synchronous by design.\n - Represents the sole entry point through which adapters obtain\n authentication material.\n - Implementations must either return credentials of the declared\n type `T` that are valid at the time of return or raise an exception." } } @@ -66,28 +24,28 @@ "name": "CredentialStore", "kind": "class", "path": "mail_intake.auth.google.CredentialStore", - "signature": "", + "signature": null, "docstring": "Abstract base class defining a generic persistence interface.\n\nUsed for authentication credentials across different backends.\n\nNotes:\n **Responsibilities:**\n\n - Provide persistent storage separating life-cycle management from\n storage mechanics.\n - Keep implementation focused only on persistence.\n\n **Constraints:**\n\n - The store is intentionally agnostic to:\n - The concrete credential type being stored.\n - The serialization format used to persist credentials.\n - The underlying storage backend or durability guarantees.", "members": { "load": { "name": "load", "kind": "function", "path": "mail_intake.auth.google.CredentialStore.load", - "signature": "", + "signature": "load()", "docstring": "Load previously persisted credentials.\n\nReturns:\n T | None:\n An instance of type `T` if credentials are available and\n loadable; otherwise `None`.\n\nNotes:\n **Guarantees:**\n\n - Implementations should return `None` when no credentials are\n present or when stored credentials cannot be successfully\n decoded or deserialized.\n - The store must not attempt to validate, refresh, or otherwise\n interpret the returned credentials." }, "save": { "name": "save", "kind": "function", "path": "mail_intake.auth.google.CredentialStore.save", - "signature": "", + "signature": "save(credentials: T)", "docstring": "Persist credentials to the underlying storage backend.\n\nArgs:\n credentials (T):\n The credential object to persist.\n\nNotes:\n **Lifecycle:**\n\n - This method is invoked when credentials are newly obtained or have been refreshed and are known to be valid at the time of persistence\n\n **Responsibilities:**\n\n - Ensuring durability appropriate to the deployment context\n - Applying encryption or access controls where required\n - Overwriting any previously stored credentials" }, "clear": { "name": "clear", "kind": "function", "path": "mail_intake.auth.google.CredentialStore.clear", - "signature": "", + "signature": "clear()", "docstring": "Remove any persisted credentials from the store.\n\nNotes:\n **Lifecycle:**\n\n - This method is called when credentials are known to be invalid, revoked, corrupted, or otherwise unusable\n - Must ensure that no stale authentication material remains accessible\n\n **Guarantees:**\n\n - Implementations should treat this operation as idempotent" } } @@ -96,14 +54,14 @@ "name": "MailIntakeAuthError", "kind": "class", "path": "mail_intake.auth.google.MailIntakeAuthError", - "signature": "", + "signature": null, "docstring": "Authentication and credential-related failures.\n\nNotes:\n **Lifecycle:**\n\n - Raised when authentication providers are unable to acquire,\n refresh, or persist valid credentials." }, "MailIntakeGoogleAuth": { "name": "MailIntakeGoogleAuth", "kind": "class", "path": "mail_intake.auth.google.MailIntakeGoogleAuth", - "signature": "", + "signature": "MailIntakeGoogleAuth(credentials_path: str, store: CredentialStore[Any], scopes: Sequence[str])", "docstring": "Google OAuth provider for Gmail access.\n\nThis provider implements the `MailIntakeAuthProvider` interface using\nGoogle's OAuth 2.0 flow and credential management libraries.\n\nNotes:\n **Responsibilities:**\n\n - Load cached credentials from a credential store when available.\n - Refresh expired credentials when possible.\n - Initiate an interactive OAuth flow only when required.\n - Persist refreshed or newly obtained credentials via the store.\n\n **Guarantees:**\n\n - This class is synchronous by design and maintains a minimal\n internal state.", "members": { "credentials_path": { @@ -131,17 +89,10 @@ "name": "get_credentials", "kind": "function", "path": "mail_intake.auth.google.MailIntakeGoogleAuth.get_credentials", - "signature": "", + "signature": "get_credentials() -> Any", "docstring": "Retrieve valid Google OAuth credentials.\n\nReturns:\n Credentials:\n A `google.oauth2.credentials.Credentials` instance suitable\n for use with Google API clients.\n\nRaises:\n MailIntakeAuthError:\n If credentials cannot be loaded, refreshed,\n or obtained via interactive authentication.\n\nNotes:\n **Lifecycle:**\n\n - Load cached credentials from the configured credential store.\n - Refresh expired credentials when possible.\n - Perform an interactive OAuth login as a fallback.\n - Persist valid credentials for future use." } } - }, - "Any": { - "name": "Any", - "kind": "alias", - "path": "mail_intake.auth.google.Any", - "signature": "", - "docstring": null } } } diff --git a/docs/mcp/modules/mail_intake.auth.json b/docs/mcp/modules/mail_intake.auth.json index 2981649..4a999a3 100644 --- a/docs/mcp/modules/mail_intake.auth.json +++ b/docs/mcp/modules/mail_intake.auth.json @@ -8,14 +8,14 @@ "name": "MailIntakeAuthProvider", "kind": "class", "path": "mail_intake.auth.MailIntakeAuthProvider", - "signature": "", + "signature": null, "docstring": "Abstract base class for authentication providers.\n\nThis interface enforces a strict contract between authentication\nproviders and mail adapters by requiring providers to explicitly\ndeclare the type of credentials they return.\n\nNotes:\n **Responsibilities:**\n\n - Acquire credentials from an external provider.\n - Refresh or revalidate credentials as needed.\n - Handle authentication-specific failure modes.\n - Coordinate with credential persistence layers where applicable.\n\n **Constraints:**\n\n - Mail adapters must treat returned credentials as opaque and\n provider-specific.\n - Mail adapters rely only on the declared credential type expected\n by the adapter.", "members": { "get_credentials": { "name": "get_credentials", "kind": "function", "path": "mail_intake.auth.MailIntakeAuthProvider.get_credentials", - "signature": "", + "signature": "get_credentials()", "docstring": "Retrieve valid, provider-specific credentials.\n\nReturns:\n T:\n Credentials of type `T` suitable for immediate use by the\n corresponding mail adapter.\n\nRaises:\n Exception:\n An authentication-specific exception indicating that\n credentials could not be obtained or validated.\n\nNotes:\n **Guarantees:**\n\n - This method is synchronous by design.\n - Represents the sole entry point through which adapters obtain\n authentication material.\n - Implementations must either return credentials of the declared\n type `T` that are valid at the time of return or raise an exception." } } @@ -24,35 +24,35 @@ "name": "MailIntakeGoogleAuth", "kind": "class", "path": "mail_intake.auth.MailIntakeGoogleAuth", - "signature": "", + "signature": "MailIntakeGoogleAuth(credentials_path: str, store: CredentialStore[Any], scopes: Sequence[str])", "docstring": "Google OAuth provider for Gmail access.\n\nThis provider implements the `MailIntakeAuthProvider` interface using\nGoogle's OAuth 2.0 flow and credential management libraries.\n\nNotes:\n **Responsibilities:**\n\n - Load cached credentials from a credential store when available.\n - Refresh expired credentials when possible.\n - Initiate an interactive OAuth flow only when required.\n - Persist refreshed or newly obtained credentials via the store.\n\n **Guarantees:**\n\n - This class is synchronous by design and maintains a minimal\n internal state.", "members": { "credentials_path": { "name": "credentials_path", "kind": "attribute", "path": "mail_intake.auth.MailIntakeGoogleAuth.credentials_path", - "signature": "", + "signature": null, "docstring": null }, "store": { "name": "store", "kind": "attribute", "path": "mail_intake.auth.MailIntakeGoogleAuth.store", - "signature": "", + "signature": null, "docstring": null }, "scopes": { "name": "scopes", "kind": "attribute", "path": "mail_intake.auth.MailIntakeGoogleAuth.scopes", - "signature": "", + "signature": null, "docstring": null }, "get_credentials": { "name": "get_credentials", "kind": "function", "path": "mail_intake.auth.MailIntakeGoogleAuth.get_credentials", - "signature": "", + "signature": "get_credentials()", "docstring": "Retrieve valid Google OAuth credentials.\n\nReturns:\n Credentials:\n A `google.oauth2.credentials.Credentials` instance suitable\n for use with Google API clients.\n\nRaises:\n MailIntakeAuthError:\n If credentials cannot be loaded, refreshed,\n or obtained via interactive authentication.\n\nNotes:\n **Lifecycle:**\n\n - Load cached credentials from the configured credential store.\n - Refresh expired credentials when possible.\n - Perform an interactive OAuth login as a fallback.\n - Persist valid credentials for future use." } } @@ -64,34 +64,6 @@ "signature": null, "docstring": "# Summary\n\nAuthentication provider contracts for Mail Intake.\n\nThis module defines the **authentication abstraction layer** used by mail\nadapters to obtain provider-specific credentials.\n\nAuthentication concerns are intentionally decoupled from adapter logic.\nAdapters depend only on this interface and must not be aware of how\ncredentials are acquired, refreshed, or persisted.", "members": { - "ABC": { - "name": "ABC", - "kind": "alias", - "path": "mail_intake.auth.base.ABC", - "signature": "", - "docstring": null - }, - "abstractmethod": { - "name": "abstractmethod", - "kind": "alias", - "path": "mail_intake.auth.base.abstractmethod", - "signature": "", - "docstring": null - }, - "Generic": { - "name": "Generic", - "kind": "alias", - "path": "mail_intake.auth.base.Generic", - "signature": "", - "docstring": null - }, - "TypeVar": { - "name": "TypeVar", - "kind": "alias", - "path": "mail_intake.auth.base.TypeVar", - "signature": "", - "docstring": null - }, "T": { "name": "T", "kind": "attribute", @@ -103,14 +75,14 @@ "name": "MailIntakeAuthProvider", "kind": "class", "path": "mail_intake.auth.base.MailIntakeAuthProvider", - "signature": "", + "signature": null, "docstring": "Abstract base class for authentication providers.\n\nThis interface enforces a strict contract between authentication\nproviders and mail adapters by requiring providers to explicitly\ndeclare the type of credentials they return.\n\nNotes:\n **Responsibilities:**\n\n - Acquire credentials from an external provider.\n - Refresh or revalidate credentials as needed.\n - Handle authentication-specific failure modes.\n - Coordinate with credential persistence layers where applicable.\n\n **Constraints:**\n\n - Mail adapters must treat returned credentials as opaque and\n provider-specific.\n - Mail adapters rely only on the declared credential type expected\n by the adapter.", "members": { "get_credentials": { "name": "get_credentials", "kind": "function", "path": "mail_intake.auth.base.MailIntakeAuthProvider.get_credentials", - "signature": "", + "signature": "get_credentials() -> T", "docstring": "Retrieve valid, provider-specific credentials.\n\nReturns:\n T:\n Credentials of type `T` suitable for immediate use by the\n corresponding mail adapter.\n\nRaises:\n Exception:\n An authentication-specific exception indicating that\n credentials could not be obtained or validated.\n\nNotes:\n **Guarantees:**\n\n - This method is synchronous by design.\n - Represents the sole entry point through which adapters obtain\n authentication material.\n - Implementations must either return credentials of the declared\n type `T` that are valid at the time of return or raise an exception." } } @@ -124,60 +96,18 @@ "signature": null, "docstring": "# Summary\n\nGoogle authentication provider implementation for Mail Intake.\n\nThis module provides a **Google OAuth–based authentication provider**\nused primarily for Gmail access.\n\nIt encapsulates all Google-specific authentication concerns, including:\n\n- Credential loading and persistence.\n- Token refresh handling.\n- Interactive OAuth flow initiation.\n- Coordination with a credential persistence layer.\n\nNo Google authentication details should leak outside this module.", "members": { - "os": { - "name": "os", - "kind": "alias", - "path": "mail_intake.auth.google.os", - "signature": "", - "docstring": null - }, - "Sequence": { - "name": "Sequence", - "kind": "alias", - "path": "mail_intake.auth.google.Sequence", - "signature": "", - "docstring": null - }, - "google": { - "name": "google", - "kind": "alias", - "path": "mail_intake.auth.google.google", - "signature": "", - "docstring": null - }, - "Request": { - "name": "Request", - "kind": "alias", - "path": "mail_intake.auth.google.Request", - "signature": "", - "docstring": null - }, - "Credentials": { - "name": "Credentials", - "kind": "alias", - "path": "mail_intake.auth.google.Credentials", - "signature": "", - "docstring": null - }, - "InstalledAppFlow": { - "name": "InstalledAppFlow", - "kind": "alias", - "path": "mail_intake.auth.google.InstalledAppFlow", - "signature": "", - "docstring": null - }, "MailIntakeAuthProvider": { "name": "MailIntakeAuthProvider", "kind": "class", "path": "mail_intake.auth.google.MailIntakeAuthProvider", - "signature": "", + "signature": null, "docstring": "Abstract base class for authentication providers.\n\nThis interface enforces a strict contract between authentication\nproviders and mail adapters by requiring providers to explicitly\ndeclare the type of credentials they return.\n\nNotes:\n **Responsibilities:**\n\n - Acquire credentials from an external provider.\n - Refresh or revalidate credentials as needed.\n - Handle authentication-specific failure modes.\n - Coordinate with credential persistence layers where applicable.\n\n **Constraints:**\n\n - Mail adapters must treat returned credentials as opaque and\n provider-specific.\n - Mail adapters rely only on the declared credential type expected\n by the adapter.", "members": { "get_credentials": { "name": "get_credentials", "kind": "function", "path": "mail_intake.auth.google.MailIntakeAuthProvider.get_credentials", - "signature": "", + "signature": "get_credentials()", "docstring": "Retrieve valid, provider-specific credentials.\n\nReturns:\n T:\n Credentials of type `T` suitable for immediate use by the\n corresponding mail adapter.\n\nRaises:\n Exception:\n An authentication-specific exception indicating that\n credentials could not be obtained or validated.\n\nNotes:\n **Guarantees:**\n\n - This method is synchronous by design.\n - Represents the sole entry point through which adapters obtain\n authentication material.\n - Implementations must either return credentials of the declared\n type `T` that are valid at the time of return or raise an exception." } } @@ -186,28 +116,28 @@ "name": "CredentialStore", "kind": "class", "path": "mail_intake.auth.google.CredentialStore", - "signature": "", + "signature": null, "docstring": "Abstract base class defining a generic persistence interface.\n\nUsed for authentication credentials across different backends.\n\nNotes:\n **Responsibilities:**\n\n - Provide persistent storage separating life-cycle management from\n storage mechanics.\n - Keep implementation focused only on persistence.\n\n **Constraints:**\n\n - The store is intentionally agnostic to:\n - The concrete credential type being stored.\n - The serialization format used to persist credentials.\n - The underlying storage backend or durability guarantees.", "members": { "load": { "name": "load", "kind": "function", "path": "mail_intake.auth.google.CredentialStore.load", - "signature": "", + "signature": "load()", "docstring": "Load previously persisted credentials.\n\nReturns:\n T | None:\n An instance of type `T` if credentials are available and\n loadable; otherwise `None`.\n\nNotes:\n **Guarantees:**\n\n - Implementations should return `None` when no credentials are\n present or when stored credentials cannot be successfully\n decoded or deserialized.\n - The store must not attempt to validate, refresh, or otherwise\n interpret the returned credentials." }, "save": { "name": "save", "kind": "function", "path": "mail_intake.auth.google.CredentialStore.save", - "signature": "", + "signature": "save(credentials: T)", "docstring": "Persist credentials to the underlying storage backend.\n\nArgs:\n credentials (T):\n The credential object to persist.\n\nNotes:\n **Lifecycle:**\n\n - This method is invoked when credentials are newly obtained or have been refreshed and are known to be valid at the time of persistence\n\n **Responsibilities:**\n\n - Ensuring durability appropriate to the deployment context\n - Applying encryption or access controls where required\n - Overwriting any previously stored credentials" }, "clear": { "name": "clear", "kind": "function", "path": "mail_intake.auth.google.CredentialStore.clear", - "signature": "", + "signature": "clear()", "docstring": "Remove any persisted credentials from the store.\n\nNotes:\n **Lifecycle:**\n\n - This method is called when credentials are known to be invalid, revoked, corrupted, or otherwise unusable\n - Must ensure that no stale authentication material remains accessible\n\n **Guarantees:**\n\n - Implementations should treat this operation as idempotent" } } @@ -216,14 +146,14 @@ "name": "MailIntakeAuthError", "kind": "class", "path": "mail_intake.auth.google.MailIntakeAuthError", - "signature": "", + "signature": null, "docstring": "Authentication and credential-related failures.\n\nNotes:\n **Lifecycle:**\n\n - Raised when authentication providers are unable to acquire,\n refresh, or persist valid credentials." }, "MailIntakeGoogleAuth": { "name": "MailIntakeGoogleAuth", "kind": "class", "path": "mail_intake.auth.google.MailIntakeGoogleAuth", - "signature": "", + "signature": "MailIntakeGoogleAuth(credentials_path: str, store: CredentialStore[Any], scopes: Sequence[str])", "docstring": "Google OAuth provider for Gmail access.\n\nThis provider implements the `MailIntakeAuthProvider` interface using\nGoogle's OAuth 2.0 flow and credential management libraries.\n\nNotes:\n **Responsibilities:**\n\n - Load cached credentials from a credential store when available.\n - Refresh expired credentials when possible.\n - Initiate an interactive OAuth flow only when required.\n - Persist refreshed or newly obtained credentials via the store.\n\n **Guarantees:**\n\n - This class is synchronous by design and maintains a minimal\n internal state.", "members": { "credentials_path": { @@ -251,17 +181,10 @@ "name": "get_credentials", "kind": "function", "path": "mail_intake.auth.google.MailIntakeGoogleAuth.get_credentials", - "signature": "", + "signature": "get_credentials() -> Any", "docstring": "Retrieve valid Google OAuth credentials.\n\nReturns:\n Credentials:\n A `google.oauth2.credentials.Credentials` instance suitable\n for use with Google API clients.\n\nRaises:\n MailIntakeAuthError:\n If credentials cannot be loaded, refreshed,\n or obtained via interactive authentication.\n\nNotes:\n **Lifecycle:**\n\n - Load cached credentials from the configured credential store.\n - Refresh expired credentials when possible.\n - Perform an interactive OAuth login as a fallback.\n - Persist valid credentials for future use." } } - }, - "Any": { - "name": "Any", - "kind": "alias", - "path": "mail_intake.auth.google.Any", - "signature": "", - "docstring": null } } } diff --git a/docs/mcp/modules/mail_intake.config.json b/docs/mcp/modules/mail_intake.config.json index 0bf2561..6feb14a 100644 --- a/docs/mcp/modules/mail_intake.config.json +++ b/docs/mcp/modules/mail_intake.config.json @@ -4,18 +4,11 @@ "path": "mail_intake.config", "docstring": "# Summary\n\nGlobal configuration models for Mail Intake.\n\nThis module defines the **top-level configuration object** used to control\nmail ingestion behavior across adapters, authentication providers, and\ningestion workflows.\n\nConfiguration is intentionally explicit, immutable, and free of implicit\nenvironment reads to ensure predictability and testability.", "objects": { - "dataclass": { - "name": "dataclass", - "kind": "alias", - "path": "mail_intake.config.dataclass", - "signature": "", - "docstring": null - }, "MailIntakeConfig": { "name": "MailIntakeConfig", "kind": "class", "path": "mail_intake.config.MailIntakeConfig", - "signature": "", + "signature": "MailIntakeConfig(provider: str = ..., user_id: str = ..., readonly: bool = ..., credentials_path: str | None = ..., token_path: str | None = ...)", "docstring": "Global configuration for `mail-intake`.\n\nNotes:\n **Guarantees:**\n\n - This configuration is intentionally explicit and immutable.\n - No implicit environment reads or global state.\n - Explicit configuration over implicit defaults.\n - No direct environment or filesystem access.\n - This model is safe to pass across layers and suitable for\n serialization.", "members": { "provider": { diff --git a/docs/mcp/modules/mail_intake.credentials.json b/docs/mcp/modules/mail_intake.credentials.json index f18c4df..0c13fc5 100644 --- a/docs/mcp/modules/mail_intake.credentials.json +++ b/docs/mcp/modules/mail_intake.credentials.json @@ -8,28 +8,28 @@ "name": "CredentialStore", "kind": "class", "path": "mail_intake.credentials.CredentialStore", - "signature": "", + "signature": null, "docstring": "Abstract base class defining a generic persistence interface.\n\nUsed for authentication credentials across different backends.\n\nNotes:\n **Responsibilities:**\n\n - Provide persistent storage separating life-cycle management from\n storage mechanics.\n - Keep implementation focused only on persistence.\n\n **Constraints:**\n\n - The store is intentionally agnostic to:\n - The concrete credential type being stored.\n - The serialization format used to persist credentials.\n - The underlying storage backend or durability guarantees.", "members": { "load": { "name": "load", "kind": "function", "path": "mail_intake.credentials.CredentialStore.load", - "signature": "", + "signature": "load()", "docstring": "Load previously persisted credentials.\n\nReturns:\n T | None:\n An instance of type `T` if credentials are available and\n loadable; otherwise `None`.\n\nNotes:\n **Guarantees:**\n\n - Implementations should return `None` when no credentials are\n present or when stored credentials cannot be successfully\n decoded or deserialized.\n - The store must not attempt to validate, refresh, or otherwise\n interpret the returned credentials." }, "save": { "name": "save", "kind": "function", "path": "mail_intake.credentials.CredentialStore.save", - "signature": "", + "signature": "save(credentials: T)", "docstring": "Persist credentials to the underlying storage backend.\n\nArgs:\n credentials (T):\n The credential object to persist.\n\nNotes:\n **Lifecycle:**\n\n - This method is invoked when credentials are newly obtained or have been refreshed and are known to be valid at the time of persistence\n\n **Responsibilities:**\n\n - Ensuring durability appropriate to the deployment context\n - Applying encryption or access controls where required\n - Overwriting any previously stored credentials" }, "clear": { "name": "clear", "kind": "function", "path": "mail_intake.credentials.CredentialStore.clear", - "signature": "", + "signature": "clear()", "docstring": "Remove any persisted credentials from the store.\n\nNotes:\n **Lifecycle:**\n\n - This method is called when credentials are known to be invalid, revoked, corrupted, or otherwise unusable\n - Must ensure that no stale authentication material remains accessible\n\n **Guarantees:**\n\n - Implementations should treat this operation as idempotent" } } @@ -38,35 +38,35 @@ "name": "PickleCredentialStore", "kind": "class", "path": "mail_intake.credentials.PickleCredentialStore", - "signature": "", + "signature": "PickleCredentialStore(path: str)", "docstring": "Filesystem-backed credential store using pickle serialization.\n\nThis store persists credentials as a pickled object on the local\nfilesystem. It is a simple implementation intended primarily for\ndevelopment, testing, and single-process execution contexts.\n\nNotes:\n **Guarantees:**\n\n - Stores credentials on the local filesystem.\n - Uses `pickle` for serialization and deserialization.\n - Does not provide encryption, locking, or concurrency guarantees.\n\n **Constraints:**\n\n - Credential lifecycle management, validation, and refresh logic are\n explicitly out of scope for this class.", "members": { "path": { "name": "path", "kind": "attribute", "path": "mail_intake.credentials.PickleCredentialStore.path", - "signature": "", + "signature": null, "docstring": null }, "load": { "name": "load", "kind": "function", "path": "mail_intake.credentials.PickleCredentialStore.load", - "signature": "", + "signature": "load()", "docstring": "Load credentials from the local filesystem.\n\nReturns:\n T | None:\n An instance of type `T` if credentials are present and\n successfully deserialized; otherwise `None`.\n\nNotes:\n **Guarantees:**\n\n - If the credential file does not exist or cannot be successfully\n deserialized, this method returns `None`.\n - The store does not attempt to validate or interpret the\n returned credentials." }, "save": { "name": "save", "kind": "function", "path": "mail_intake.credentials.PickleCredentialStore.save", - "signature": "", + "signature": "save(credentials: T)", "docstring": "Persist credentials to the local filesystem.\n\nArgs:\n credentials (T):\n The credential object to persist.\n\nNotes:\n **Responsibilities:**\n\n - Any previously stored credentials at the configured path are overwritten" }, "clear": { "name": "clear", "kind": "function", "path": "mail_intake.credentials.PickleCredentialStore.clear", - "signature": "", + "signature": "clear()", "docstring": "Remove persisted credentials from the local filesystem.\n\nNotes:\n **Lifecycle:**\n\n - This method deletes the credential file if it exists and should be treated as an idempotent operation" } } @@ -75,63 +75,63 @@ "name": "RedisCredentialStore", "kind": "class", "path": "mail_intake.credentials.RedisCredentialStore", - "signature": "", + "signature": "RedisCredentialStore(redis_client: Any, key: str, serialize: Callable[[T], bytes], deserialize: Callable[[bytes], T], ttl_seconds: int | None = None)", "docstring": "Redis-backed implementation of `CredentialStore`.\n\nThis store persists credentials in Redis and is suitable for\ndistributed and horizontally scaled deployments where credentials\nmust be shared across multiple processes or nodes.\n\nNotes:\n **Responsibilities:**\n\n - This class is responsible only for persistence and retrieval.\n - It does not interpret, validate, refresh, or otherwise manage the\n lifecycle of the credentials being stored.\n\n **Guarantees:**\n\n - The store is intentionally generic and delegates all serialization\n concerns to caller-provided functions.\n - This avoids unsafe mechanisms such as `pickle` and allows\n credential formats to be explicitly controlled and audited.", "members": { "redis": { "name": "redis", "kind": "attribute", "path": "mail_intake.credentials.RedisCredentialStore.redis", - "signature": "", + "signature": null, "docstring": null }, "key": { "name": "key", "kind": "attribute", "path": "mail_intake.credentials.RedisCredentialStore.key", - "signature": "", + "signature": null, "docstring": null }, "serialize": { "name": "serialize", "kind": "attribute", "path": "mail_intake.credentials.RedisCredentialStore.serialize", - "signature": "", + "signature": null, "docstring": null }, "deserialize": { "name": "deserialize", "kind": "attribute", "path": "mail_intake.credentials.RedisCredentialStore.deserialize", - "signature": "", + "signature": null, "docstring": null }, "ttl_seconds": { "name": "ttl_seconds", "kind": "attribute", "path": "mail_intake.credentials.RedisCredentialStore.ttl_seconds", - "signature": "", + "signature": null, "docstring": null }, "load": { "name": "load", "kind": "function", "path": "mail_intake.credentials.RedisCredentialStore.load", - "signature": "", + "signature": "load()", "docstring": "Load credentials from Redis.\n\nReturns:\n T | None:\n An instance of type `T` if credentials are present and\n successfully deserialized; otherwise `None`.\n\nNotes:\n **Guarantees:**\n\n - If no value exists for the configured key, or if the stored\n payload cannot be successfully deserialized, this method\n returns `None`.\n - The store does not attempt to validate the returned\n credentials or determine whether they are expired or\n otherwise usable." }, "save": { "name": "save", "kind": "function", "path": "mail_intake.credentials.RedisCredentialStore.save", - "signature": "", + "signature": "save(credentials: T)", "docstring": "Persist credentials to Redis.\n\nArgs:\n credentials (T):\n The credential object to persist.\n\nNotes:\n **Responsibilities:**\n\n - Any previously stored credentials under the same key are overwritten\n - If a TTL is configured, the credentials will expire automatically after the specified duration" }, "clear": { "name": "clear", "kind": "function", "path": "mail_intake.credentials.RedisCredentialStore.clear", - "signature": "", + "signature": "clear()", "docstring": "Remove stored credentials from Redis.\n\nNotes:\n **Lifecycle:**\n\n - This operation deletes the configured Redis key if it exists\n - Implementations should treat this method as idempotent" } } @@ -143,46 +143,32 @@ "signature": null, "docstring": "# Summary\n\nLocal filesystem–based credential persistence for Mail Intake.\n\nThis module provides a file-backed implementation of the\n`CredentialStore` abstraction using Python's `pickle` module.\n\nThe `pickle`-based credential store is intended for local development,\nsingle-node deployments, and controlled environments where credentials\ndo not need to be shared across processes or machines.\n\nDue to the security and portability risks associated with `pickle`-based\nserialization, this implementation is not suitable for distributed or\nuntrusted environments.", "members": { - "pickle": { - "name": "pickle", - "kind": "alias", - "path": "mail_intake.credentials.pickle.pickle", - "signature": "", - "docstring": null - }, - "TypeVar": { - "name": "TypeVar", - "kind": "alias", - "path": "mail_intake.credentials.pickle.TypeVar", - "signature": "", - "docstring": null - }, "CredentialStore": { "name": "CredentialStore", "kind": "class", "path": "mail_intake.credentials.pickle.CredentialStore", - "signature": "", + "signature": null, "docstring": "Abstract base class defining a generic persistence interface.\n\nUsed for authentication credentials across different backends.\n\nNotes:\n **Responsibilities:**\n\n - Provide persistent storage separating life-cycle management from\n storage mechanics.\n - Keep implementation focused only on persistence.\n\n **Constraints:**\n\n - The store is intentionally agnostic to:\n - The concrete credential type being stored.\n - The serialization format used to persist credentials.\n - The underlying storage backend or durability guarantees.", "members": { "load": { "name": "load", "kind": "function", "path": "mail_intake.credentials.pickle.CredentialStore.load", - "signature": "", + "signature": "load()", "docstring": "Load previously persisted credentials.\n\nReturns:\n T | None:\n An instance of type `T` if credentials are available and\n loadable; otherwise `None`.\n\nNotes:\n **Guarantees:**\n\n - Implementations should return `None` when no credentials are\n present or when stored credentials cannot be successfully\n decoded or deserialized.\n - The store must not attempt to validate, refresh, or otherwise\n interpret the returned credentials." }, "save": { "name": "save", "kind": "function", "path": "mail_intake.credentials.pickle.CredentialStore.save", - "signature": "", + "signature": "save(credentials: T)", "docstring": "Persist credentials to the underlying storage backend.\n\nArgs:\n credentials (T):\n The credential object to persist.\n\nNotes:\n **Lifecycle:**\n\n - This method is invoked when credentials are newly obtained or have been refreshed and are known to be valid at the time of persistence\n\n **Responsibilities:**\n\n - Ensuring durability appropriate to the deployment context\n - Applying encryption or access controls where required\n - Overwriting any previously stored credentials" }, "clear": { "name": "clear", "kind": "function", "path": "mail_intake.credentials.pickle.CredentialStore.clear", - "signature": "", + "signature": "clear()", "docstring": "Remove any persisted credentials from the store.\n\nNotes:\n **Lifecycle:**\n\n - This method is called when credentials are known to be invalid, revoked, corrupted, or otherwise unusable\n - Must ensure that no stale authentication material remains accessible\n\n **Guarantees:**\n\n - Implementations should treat this operation as idempotent" } } @@ -198,7 +184,7 @@ "name": "PickleCredentialStore", "kind": "class", "path": "mail_intake.credentials.pickle.PickleCredentialStore", - "signature": "", + "signature": "PickleCredentialStore(path: str)", "docstring": "Filesystem-backed credential store using pickle serialization.\n\nThis store persists credentials as a pickled object on the local\nfilesystem. It is a simple implementation intended primarily for\ndevelopment, testing, and single-process execution contexts.\n\nNotes:\n **Guarantees:**\n\n - Stores credentials on the local filesystem.\n - Uses `pickle` for serialization and deserialization.\n - Does not provide encryption, locking, or concurrency guarantees.\n\n **Constraints:**\n\n - Credential lifecycle management, validation, and refresh logic are\n explicitly out of scope for this class.", "members": { "path": { @@ -212,21 +198,21 @@ "name": "load", "kind": "function", "path": "mail_intake.credentials.pickle.PickleCredentialStore.load", - "signature": "", + "signature": "load() -> T | None", "docstring": "Load credentials from the local filesystem.\n\nReturns:\n T | None:\n An instance of type `T` if credentials are present and\n successfully deserialized; otherwise `None`.\n\nNotes:\n **Guarantees:**\n\n - If the credential file does not exist or cannot be successfully\n deserialized, this method returns `None`.\n - The store does not attempt to validate or interpret the\n returned credentials." }, "save": { "name": "save", "kind": "function", "path": "mail_intake.credentials.pickle.PickleCredentialStore.save", - "signature": "", + "signature": "save(credentials: T) -> None", "docstring": "Persist credentials to the local filesystem.\n\nArgs:\n credentials (T):\n The credential object to persist.\n\nNotes:\n **Responsibilities:**\n\n - Any previously stored credentials at the configured path are overwritten" }, "clear": { "name": "clear", "kind": "function", "path": "mail_intake.credentials.pickle.PickleCredentialStore.clear", - "signature": "", + "signature": "clear() -> None", "docstring": "Remove persisted credentials from the local filesystem.\n\nNotes:\n **Lifecycle:**\n\n - This method deletes the credential file if it exists and should be treated as an idempotent operation" } } @@ -240,53 +226,32 @@ "signature": null, "docstring": "# Summary\n\nRedis-backed credential persistence for Mail Intake.\n\nThis module provides a Redis-based implementation of the\n`CredentialStore` abstraction, enabling credential persistence\nacross distributed and horizontally scaled deployments.\n\nThe Redis credential store is designed for environments where\nauthentication credentials must be shared safely across multiple\nprocesses, containers, or nodes, such as container orchestration\nplatforms and microservice architectures.\n\nKey characteristics:\n\n- Distributed-safe, shared storage using Redis.\n- Explicit, caller-defined serialization and deserialization.\n- No reliance on unsafe mechanisms such as `pickle`.\n- Optional time-to-live (TTL) support for automatic credential expiry.\n\nThis module is responsible solely for persistence concerns.\nCredential validation, refresh, rotation, and acquisition remain the\nresponsibility of authentication provider implementations.", "members": { - "Callable": { - "name": "Callable", - "kind": "alias", - "path": "mail_intake.credentials.redis.Callable", - "signature": "", - "docstring": null - }, - "Any": { - "name": "Any", - "kind": "alias", - "path": "mail_intake.credentials.redis.Any", - "signature": "", - "docstring": null - }, - "TypeVar": { - "name": "TypeVar", - "kind": "alias", - "path": "mail_intake.credentials.redis.TypeVar", - "signature": "", - "docstring": null - }, "CredentialStore": { "name": "CredentialStore", "kind": "class", "path": "mail_intake.credentials.redis.CredentialStore", - "signature": "", + "signature": null, "docstring": "Abstract base class defining a generic persistence interface.\n\nUsed for authentication credentials across different backends.\n\nNotes:\n **Responsibilities:**\n\n - Provide persistent storage separating life-cycle management from\n storage mechanics.\n - Keep implementation focused only on persistence.\n\n **Constraints:**\n\n - The store is intentionally agnostic to:\n - The concrete credential type being stored.\n - The serialization format used to persist credentials.\n - The underlying storage backend or durability guarantees.", "members": { "load": { "name": "load", "kind": "function", "path": "mail_intake.credentials.redis.CredentialStore.load", - "signature": "", + "signature": "load()", "docstring": "Load previously persisted credentials.\n\nReturns:\n T | None:\n An instance of type `T` if credentials are available and\n loadable; otherwise `None`.\n\nNotes:\n **Guarantees:**\n\n - Implementations should return `None` when no credentials are\n present or when stored credentials cannot be successfully\n decoded or deserialized.\n - The store must not attempt to validate, refresh, or otherwise\n interpret the returned credentials." }, "save": { "name": "save", "kind": "function", "path": "mail_intake.credentials.redis.CredentialStore.save", - "signature": "", + "signature": "save(credentials: T)", "docstring": "Persist credentials to the underlying storage backend.\n\nArgs:\n credentials (T):\n The credential object to persist.\n\nNotes:\n **Lifecycle:**\n\n - This method is invoked when credentials are newly obtained or have been refreshed and are known to be valid at the time of persistence\n\n **Responsibilities:**\n\n - Ensuring durability appropriate to the deployment context\n - Applying encryption or access controls where required\n - Overwriting any previously stored credentials" }, "clear": { "name": "clear", "kind": "function", "path": "mail_intake.credentials.redis.CredentialStore.clear", - "signature": "", + "signature": "clear()", "docstring": "Remove any persisted credentials from the store.\n\nNotes:\n **Lifecycle:**\n\n - This method is called when credentials are known to be invalid, revoked, corrupted, or otherwise unusable\n - Must ensure that no stale authentication material remains accessible\n\n **Guarantees:**\n\n - Implementations should treat this operation as idempotent" } } @@ -302,7 +267,7 @@ "name": "RedisCredentialStore", "kind": "class", "path": "mail_intake.credentials.redis.RedisCredentialStore", - "signature": "", + "signature": "RedisCredentialStore(redis_client: Any, key: str, serialize: Callable[[T], bytes], deserialize: Callable[[bytes], T], ttl_seconds: int | None = None)", "docstring": "Redis-backed implementation of `CredentialStore`.\n\nThis store persists credentials in Redis and is suitable for\ndistributed and horizontally scaled deployments where credentials\nmust be shared across multiple processes or nodes.\n\nNotes:\n **Responsibilities:**\n\n - This class is responsible only for persistence and retrieval.\n - It does not interpret, validate, refresh, or otherwise manage the\n lifecycle of the credentials being stored.\n\n **Guarantees:**\n\n - The store is intentionally generic and delegates all serialization\n concerns to caller-provided functions.\n - This avoids unsafe mechanisms such as `pickle` and allows\n credential formats to be explicitly controlled and audited.", "members": { "redis": { @@ -344,21 +309,21 @@ "name": "load", "kind": "function", "path": "mail_intake.credentials.redis.RedisCredentialStore.load", - "signature": "", + "signature": "load() -> T | None", "docstring": "Load credentials from Redis.\n\nReturns:\n T | None:\n An instance of type `T` if credentials are present and\n successfully deserialized; otherwise `None`.\n\nNotes:\n **Guarantees:**\n\n - If no value exists for the configured key, or if the stored\n payload cannot be successfully deserialized, this method\n returns `None`.\n - The store does not attempt to validate the returned\n credentials or determine whether they are expired or\n otherwise usable." }, "save": { "name": "save", "kind": "function", "path": "mail_intake.credentials.redis.RedisCredentialStore.save", - "signature": "", + "signature": "save(credentials: T) -> None", "docstring": "Persist credentials to Redis.\n\nArgs:\n credentials (T):\n The credential object to persist.\n\nNotes:\n **Responsibilities:**\n\n - Any previously stored credentials under the same key are overwritten\n - If a TTL is configured, the credentials will expire automatically after the specified duration" }, "clear": { "name": "clear", "kind": "function", "path": "mail_intake.credentials.redis.RedisCredentialStore.clear", - "signature": "", + "signature": "clear() -> None", "docstring": "Remove stored credentials from Redis.\n\nNotes:\n **Lifecycle:**\n\n - This operation deletes the configured Redis key if it exists\n - Implementations should treat this method as idempotent" } } @@ -372,34 +337,6 @@ "signature": null, "docstring": "# Summary\n\nCredential persistence abstractions for Mail Intake.\n\nThis module defines the generic persistence contract used to store and\nretrieve authentication credentials across Mail Intake components.\n\nThe `CredentialStore` abstraction establishes a strict separation\nbetween credential *lifecycle management* and credential *storage*.\nAuthentication providers are responsible for acquiring, validating,\nrefreshing, and revoking credentials, while concrete store\nimplementations are responsible solely for persistence concerns.\n\nBy remaining agnostic to credential structure, serialization format,\nand storage backend, this module enables multiple persistence\nstrategiesβ€”such as local files, in-memory caches, distributed stores,\nor secrets managersβ€”without coupling authentication logic to any\nspecific storage mechanism.", "members": { - "ABC": { - "name": "ABC", - "kind": "alias", - "path": "mail_intake.credentials.store.ABC", - "signature": "", - "docstring": null - }, - "abstractmethod": { - "name": "abstractmethod", - "kind": "alias", - "path": "mail_intake.credentials.store.abstractmethod", - "signature": "", - "docstring": null - }, - "Generic": { - "name": "Generic", - "kind": "alias", - "path": "mail_intake.credentials.store.Generic", - "signature": "", - "docstring": null - }, - "TypeVar": { - "name": "TypeVar", - "kind": "alias", - "path": "mail_intake.credentials.store.TypeVar", - "signature": "", - "docstring": null - }, "T": { "name": "T", "kind": "attribute", @@ -411,28 +348,28 @@ "name": "CredentialStore", "kind": "class", "path": "mail_intake.credentials.store.CredentialStore", - "signature": "", + "signature": null, "docstring": "Abstract base class defining a generic persistence interface.\n\nUsed for authentication credentials across different backends.\n\nNotes:\n **Responsibilities:**\n\n - Provide persistent storage separating life-cycle management from\n storage mechanics.\n - Keep implementation focused only on persistence.\n\n **Constraints:**\n\n - The store is intentionally agnostic to:\n - The concrete credential type being stored.\n - The serialization format used to persist credentials.\n - The underlying storage backend or durability guarantees.", "members": { "load": { "name": "load", "kind": "function", "path": "mail_intake.credentials.store.CredentialStore.load", - "signature": "", + "signature": "load() -> T | None", "docstring": "Load previously persisted credentials.\n\nReturns:\n T | None:\n An instance of type `T` if credentials are available and\n loadable; otherwise `None`.\n\nNotes:\n **Guarantees:**\n\n - Implementations should return `None` when no credentials are\n present or when stored credentials cannot be successfully\n decoded or deserialized.\n - The store must not attempt to validate, refresh, or otherwise\n interpret the returned credentials." }, "save": { "name": "save", "kind": "function", "path": "mail_intake.credentials.store.CredentialStore.save", - "signature": "", + "signature": "save(credentials: T) -> None", "docstring": "Persist credentials to the underlying storage backend.\n\nArgs:\n credentials (T):\n The credential object to persist.\n\nNotes:\n **Lifecycle:**\n\n - This method is invoked when credentials are newly obtained or have been refreshed and are known to be valid at the time of persistence\n\n **Responsibilities:**\n\n - Ensuring durability appropriate to the deployment context\n - Applying encryption or access controls where required\n - Overwriting any previously stored credentials" }, "clear": { "name": "clear", "kind": "function", "path": "mail_intake.credentials.store.CredentialStore.clear", - "signature": "", + "signature": "clear() -> None", "docstring": "Remove any persisted credentials from the store.\n\nNotes:\n **Lifecycle:**\n\n - This method is called when credentials are known to be invalid, revoked, corrupted, or otherwise unusable\n - Must ensure that no stale authentication material remains accessible\n\n **Guarantees:**\n\n - Implementations should treat this operation as idempotent" } } diff --git a/docs/mcp/modules/mail_intake.credentials.pickle.json b/docs/mcp/modules/mail_intake.credentials.pickle.json index 4813aad..f6bb66d 100644 --- a/docs/mcp/modules/mail_intake.credentials.pickle.json +++ b/docs/mcp/modules/mail_intake.credentials.pickle.json @@ -4,46 +4,32 @@ "path": "mail_intake.credentials.pickle", "docstring": "# Summary\n\nLocal filesystem–based credential persistence for Mail Intake.\n\nThis module provides a file-backed implementation of the\n`CredentialStore` abstraction using Python's `pickle` module.\n\nThe `pickle`-based credential store is intended for local development,\nsingle-node deployments, and controlled environments where credentials\ndo not need to be shared across processes or machines.\n\nDue to the security and portability risks associated with `pickle`-based\nserialization, this implementation is not suitable for distributed or\nuntrusted environments.", "objects": { - "pickle": { - "name": "pickle", - "kind": "alias", - "path": "mail_intake.credentials.pickle.pickle", - "signature": "", - "docstring": null - }, - "TypeVar": { - "name": "TypeVar", - "kind": "alias", - "path": "mail_intake.credentials.pickle.TypeVar", - "signature": "", - "docstring": null - }, "CredentialStore": { "name": "CredentialStore", "kind": "class", "path": "mail_intake.credentials.pickle.CredentialStore", - "signature": "", + "signature": null, "docstring": "Abstract base class defining a generic persistence interface.\n\nUsed for authentication credentials across different backends.\n\nNotes:\n **Responsibilities:**\n\n - Provide persistent storage separating life-cycle management from\n storage mechanics.\n - Keep implementation focused only on persistence.\n\n **Constraints:**\n\n - The store is intentionally agnostic to:\n - The concrete credential type being stored.\n - The serialization format used to persist credentials.\n - The underlying storage backend or durability guarantees.", "members": { "load": { "name": "load", "kind": "function", "path": "mail_intake.credentials.pickle.CredentialStore.load", - "signature": "", + "signature": "load()", "docstring": "Load previously persisted credentials.\n\nReturns:\n T | None:\n An instance of type `T` if credentials are available and\n loadable; otherwise `None`.\n\nNotes:\n **Guarantees:**\n\n - Implementations should return `None` when no credentials are\n present or when stored credentials cannot be successfully\n decoded or deserialized.\n - The store must not attempt to validate, refresh, or otherwise\n interpret the returned credentials." }, "save": { "name": "save", "kind": "function", "path": "mail_intake.credentials.pickle.CredentialStore.save", - "signature": "", + "signature": "save(credentials: T)", "docstring": "Persist credentials to the underlying storage backend.\n\nArgs:\n credentials (T):\n The credential object to persist.\n\nNotes:\n **Lifecycle:**\n\n - This method is invoked when credentials are newly obtained or have been refreshed and are known to be valid at the time of persistence\n\n **Responsibilities:**\n\n - Ensuring durability appropriate to the deployment context\n - Applying encryption or access controls where required\n - Overwriting any previously stored credentials" }, "clear": { "name": "clear", "kind": "function", "path": "mail_intake.credentials.pickle.CredentialStore.clear", - "signature": "", + "signature": "clear()", "docstring": "Remove any persisted credentials from the store.\n\nNotes:\n **Lifecycle:**\n\n - This method is called when credentials are known to be invalid, revoked, corrupted, or otherwise unusable\n - Must ensure that no stale authentication material remains accessible\n\n **Guarantees:**\n\n - Implementations should treat this operation as idempotent" } } @@ -59,7 +45,7 @@ "name": "PickleCredentialStore", "kind": "class", "path": "mail_intake.credentials.pickle.PickleCredentialStore", - "signature": "", + "signature": "PickleCredentialStore(path: str)", "docstring": "Filesystem-backed credential store using pickle serialization.\n\nThis store persists credentials as a pickled object on the local\nfilesystem. It is a simple implementation intended primarily for\ndevelopment, testing, and single-process execution contexts.\n\nNotes:\n **Guarantees:**\n\n - Stores credentials on the local filesystem.\n - Uses `pickle` for serialization and deserialization.\n - Does not provide encryption, locking, or concurrency guarantees.\n\n **Constraints:**\n\n - Credential lifecycle management, validation, and refresh logic are\n explicitly out of scope for this class.", "members": { "path": { @@ -73,21 +59,21 @@ "name": "load", "kind": "function", "path": "mail_intake.credentials.pickle.PickleCredentialStore.load", - "signature": "", + "signature": "load() -> T | None", "docstring": "Load credentials from the local filesystem.\n\nReturns:\n T | None:\n An instance of type `T` if credentials are present and\n successfully deserialized; otherwise `None`.\n\nNotes:\n **Guarantees:**\n\n - If the credential file does not exist or cannot be successfully\n deserialized, this method returns `None`.\n - The store does not attempt to validate or interpret the\n returned credentials." }, "save": { "name": "save", "kind": "function", "path": "mail_intake.credentials.pickle.PickleCredentialStore.save", - "signature": "", + "signature": "save(credentials: T) -> None", "docstring": "Persist credentials to the local filesystem.\n\nArgs:\n credentials (T):\n The credential object to persist.\n\nNotes:\n **Responsibilities:**\n\n - Any previously stored credentials at the configured path are overwritten" }, "clear": { "name": "clear", "kind": "function", "path": "mail_intake.credentials.pickle.PickleCredentialStore.clear", - "signature": "", + "signature": "clear() -> None", "docstring": "Remove persisted credentials from the local filesystem.\n\nNotes:\n **Lifecycle:**\n\n - This method deletes the credential file if it exists and should be treated as an idempotent operation" } } diff --git a/docs/mcp/modules/mail_intake.credentials.redis.json b/docs/mcp/modules/mail_intake.credentials.redis.json index 4325f23..4b1d6b9 100644 --- a/docs/mcp/modules/mail_intake.credentials.redis.json +++ b/docs/mcp/modules/mail_intake.credentials.redis.json @@ -4,53 +4,32 @@ "path": "mail_intake.credentials.redis", "docstring": "# Summary\n\nRedis-backed credential persistence for Mail Intake.\n\nThis module provides a Redis-based implementation of the\n`CredentialStore` abstraction, enabling credential persistence\nacross distributed and horizontally scaled deployments.\n\nThe Redis credential store is designed for environments where\nauthentication credentials must be shared safely across multiple\nprocesses, containers, or nodes, such as container orchestration\nplatforms and microservice architectures.\n\nKey characteristics:\n\n- Distributed-safe, shared storage using Redis.\n- Explicit, caller-defined serialization and deserialization.\n- No reliance on unsafe mechanisms such as `pickle`.\n- Optional time-to-live (TTL) support for automatic credential expiry.\n\nThis module is responsible solely for persistence concerns.\nCredential validation, refresh, rotation, and acquisition remain the\nresponsibility of authentication provider implementations.", "objects": { - "Callable": { - "name": "Callable", - "kind": "alias", - "path": "mail_intake.credentials.redis.Callable", - "signature": "", - "docstring": null - }, - "Any": { - "name": "Any", - "kind": "alias", - "path": "mail_intake.credentials.redis.Any", - "signature": "", - "docstring": null - }, - "TypeVar": { - "name": "TypeVar", - "kind": "alias", - "path": "mail_intake.credentials.redis.TypeVar", - "signature": "", - "docstring": null - }, "CredentialStore": { "name": "CredentialStore", "kind": "class", "path": "mail_intake.credentials.redis.CredentialStore", - "signature": "", + "signature": null, "docstring": "Abstract base class defining a generic persistence interface.\n\nUsed for authentication credentials across different backends.\n\nNotes:\n **Responsibilities:**\n\n - Provide persistent storage separating life-cycle management from\n storage mechanics.\n - Keep implementation focused only on persistence.\n\n **Constraints:**\n\n - The store is intentionally agnostic to:\n - The concrete credential type being stored.\n - The serialization format used to persist credentials.\n - The underlying storage backend or durability guarantees.", "members": { "load": { "name": "load", "kind": "function", "path": "mail_intake.credentials.redis.CredentialStore.load", - "signature": "", + "signature": "load()", "docstring": "Load previously persisted credentials.\n\nReturns:\n T | None:\n An instance of type `T` if credentials are available and\n loadable; otherwise `None`.\n\nNotes:\n **Guarantees:**\n\n - Implementations should return `None` when no credentials are\n present or when stored credentials cannot be successfully\n decoded or deserialized.\n - The store must not attempt to validate, refresh, or otherwise\n interpret the returned credentials." }, "save": { "name": "save", "kind": "function", "path": "mail_intake.credentials.redis.CredentialStore.save", - "signature": "", + "signature": "save(credentials: T)", "docstring": "Persist credentials to the underlying storage backend.\n\nArgs:\n credentials (T):\n The credential object to persist.\n\nNotes:\n **Lifecycle:**\n\n - This method is invoked when credentials are newly obtained or have been refreshed and are known to be valid at the time of persistence\n\n **Responsibilities:**\n\n - Ensuring durability appropriate to the deployment context\n - Applying encryption or access controls where required\n - Overwriting any previously stored credentials" }, "clear": { "name": "clear", "kind": "function", "path": "mail_intake.credentials.redis.CredentialStore.clear", - "signature": "", + "signature": "clear()", "docstring": "Remove any persisted credentials from the store.\n\nNotes:\n **Lifecycle:**\n\n - This method is called when credentials are known to be invalid, revoked, corrupted, or otherwise unusable\n - Must ensure that no stale authentication material remains accessible\n\n **Guarantees:**\n\n - Implementations should treat this operation as idempotent" } } @@ -66,7 +45,7 @@ "name": "RedisCredentialStore", "kind": "class", "path": "mail_intake.credentials.redis.RedisCredentialStore", - "signature": "", + "signature": "RedisCredentialStore(redis_client: Any, key: str, serialize: Callable[[T], bytes], deserialize: Callable[[bytes], T], ttl_seconds: int | None = None)", "docstring": "Redis-backed implementation of `CredentialStore`.\n\nThis store persists credentials in Redis and is suitable for\ndistributed and horizontally scaled deployments where credentials\nmust be shared across multiple processes or nodes.\n\nNotes:\n **Responsibilities:**\n\n - This class is responsible only for persistence and retrieval.\n - It does not interpret, validate, refresh, or otherwise manage the\n lifecycle of the credentials being stored.\n\n **Guarantees:**\n\n - The store is intentionally generic and delegates all serialization\n concerns to caller-provided functions.\n - This avoids unsafe mechanisms such as `pickle` and allows\n credential formats to be explicitly controlled and audited.", "members": { "redis": { @@ -108,21 +87,21 @@ "name": "load", "kind": "function", "path": "mail_intake.credentials.redis.RedisCredentialStore.load", - "signature": "", + "signature": "load() -> T | None", "docstring": "Load credentials from Redis.\n\nReturns:\n T | None:\n An instance of type `T` if credentials are present and\n successfully deserialized; otherwise `None`.\n\nNotes:\n **Guarantees:**\n\n - If no value exists for the configured key, or if the stored\n payload cannot be successfully deserialized, this method\n returns `None`.\n - The store does not attempt to validate the returned\n credentials or determine whether they are expired or\n otherwise usable." }, "save": { "name": "save", "kind": "function", "path": "mail_intake.credentials.redis.RedisCredentialStore.save", - "signature": "", + "signature": "save(credentials: T) -> None", "docstring": "Persist credentials to Redis.\n\nArgs:\n credentials (T):\n The credential object to persist.\n\nNotes:\n **Responsibilities:**\n\n - Any previously stored credentials under the same key are overwritten\n - If a TTL is configured, the credentials will expire automatically after the specified duration" }, "clear": { "name": "clear", "kind": "function", "path": "mail_intake.credentials.redis.RedisCredentialStore.clear", - "signature": "", + "signature": "clear() -> None", "docstring": "Remove stored credentials from Redis.\n\nNotes:\n **Lifecycle:**\n\n - This operation deletes the configured Redis key if it exists\n - Implementations should treat this method as idempotent" } } diff --git a/docs/mcp/modules/mail_intake.credentials.store.json b/docs/mcp/modules/mail_intake.credentials.store.json index 1d527e5..d777c89 100644 --- a/docs/mcp/modules/mail_intake.credentials.store.json +++ b/docs/mcp/modules/mail_intake.credentials.store.json @@ -4,34 +4,6 @@ "path": "mail_intake.credentials.store", "docstring": "# Summary\n\nCredential persistence abstractions for Mail Intake.\n\nThis module defines the generic persistence contract used to store and\nretrieve authentication credentials across Mail Intake components.\n\nThe `CredentialStore` abstraction establishes a strict separation\nbetween credential *lifecycle management* and credential *storage*.\nAuthentication providers are responsible for acquiring, validating,\nrefreshing, and revoking credentials, while concrete store\nimplementations are responsible solely for persistence concerns.\n\nBy remaining agnostic to credential structure, serialization format,\nand storage backend, this module enables multiple persistence\nstrategiesβ€”such as local files, in-memory caches, distributed stores,\nor secrets managersβ€”without coupling authentication logic to any\nspecific storage mechanism.", "objects": { - "ABC": { - "name": "ABC", - "kind": "alias", - "path": "mail_intake.credentials.store.ABC", - "signature": "", - "docstring": null - }, - "abstractmethod": { - "name": "abstractmethod", - "kind": "alias", - "path": "mail_intake.credentials.store.abstractmethod", - "signature": "", - "docstring": null - }, - "Generic": { - "name": "Generic", - "kind": "alias", - "path": "mail_intake.credentials.store.Generic", - "signature": "", - "docstring": null - }, - "TypeVar": { - "name": "TypeVar", - "kind": "alias", - "path": "mail_intake.credentials.store.TypeVar", - "signature": "", - "docstring": null - }, "T": { "name": "T", "kind": "attribute", @@ -43,28 +15,28 @@ "name": "CredentialStore", "kind": "class", "path": "mail_intake.credentials.store.CredentialStore", - "signature": "", + "signature": null, "docstring": "Abstract base class defining a generic persistence interface.\n\nUsed for authentication credentials across different backends.\n\nNotes:\n **Responsibilities:**\n\n - Provide persistent storage separating life-cycle management from\n storage mechanics.\n - Keep implementation focused only on persistence.\n\n **Constraints:**\n\n - The store is intentionally agnostic to:\n - The concrete credential type being stored.\n - The serialization format used to persist credentials.\n - The underlying storage backend or durability guarantees.", "members": { "load": { "name": "load", "kind": "function", "path": "mail_intake.credentials.store.CredentialStore.load", - "signature": "", + "signature": "load() -> T | None", "docstring": "Load previously persisted credentials.\n\nReturns:\n T | None:\n An instance of type `T` if credentials are available and\n loadable; otherwise `None`.\n\nNotes:\n **Guarantees:**\n\n - Implementations should return `None` when no credentials are\n present or when stored credentials cannot be successfully\n decoded or deserialized.\n - The store must not attempt to validate, refresh, or otherwise\n interpret the returned credentials." }, "save": { "name": "save", "kind": "function", "path": "mail_intake.credentials.store.CredentialStore.save", - "signature": "", + "signature": "save(credentials: T) -> None", "docstring": "Persist credentials to the underlying storage backend.\n\nArgs:\n credentials (T):\n The credential object to persist.\n\nNotes:\n **Lifecycle:**\n\n - This method is invoked when credentials are newly obtained or have been refreshed and are known to be valid at the time of persistence\n\n **Responsibilities:**\n\n - Ensuring durability appropriate to the deployment context\n - Applying encryption or access controls where required\n - Overwriting any previously stored credentials" }, "clear": { "name": "clear", "kind": "function", "path": "mail_intake.credentials.store.CredentialStore.clear", - "signature": "", + "signature": "clear() -> None", "docstring": "Remove any persisted credentials from the store.\n\nNotes:\n **Lifecycle:**\n\n - This method is called when credentials are known to be invalid, revoked, corrupted, or otherwise unusable\n - Must ensure that no stale authentication material remains accessible\n\n **Guarantees:**\n\n - Implementations should treat this operation as idempotent" } } diff --git a/docs/mcp/modules/mail_intake.exceptions.json b/docs/mcp/modules/mail_intake.exceptions.json index 2fa2244..ef3ec40 100644 --- a/docs/mcp/modules/mail_intake.exceptions.json +++ b/docs/mcp/modules/mail_intake.exceptions.json @@ -8,28 +8,28 @@ "name": "MailIntakeError", "kind": "class", "path": "mail_intake.exceptions.MailIntakeError", - "signature": "", + "signature": null, "docstring": "Base exception for all Mail Intake errors.\n\nNotes:\n **Guarantees:**\n\n - This is the root of the Mail Intake exception hierarchy\n - All errors raised by the library must derive from this class\n - Consumers should generally catch this type when handling library-level failures" }, "MailIntakeAuthError": { "name": "MailIntakeAuthError", "kind": "class", "path": "mail_intake.exceptions.MailIntakeAuthError", - "signature": "", + "signature": null, "docstring": "Authentication and credential-related failures.\n\nNotes:\n **Lifecycle:**\n\n - Raised when authentication providers are unable to acquire,\n refresh, or persist valid credentials." }, "MailIntakeAdapterError": { "name": "MailIntakeAdapterError", "kind": "class", "path": "mail_intake.exceptions.MailIntakeAdapterError", - "signature": "", + "signature": null, "docstring": "Errors raised by mail provider adapters.\n\nNotes:\n **Lifecycle:**\n\n - Raised when a provider adapter encounters API errors, transport\n failures, or invalid provider responses." }, "MailIntakeParsingError": { "name": "MailIntakeParsingError", "kind": "class", "path": "mail_intake.exceptions.MailIntakeParsingError", - "signature": "", + "signature": null, "docstring": "Errors encountered while parsing message content.\n\nNotes:\n **Lifecycle:**\n\n - Raised when raw provider payloads cannot be interpreted or\n normalized into internal domain models." } } diff --git a/docs/mcp/modules/mail_intake.ingestion.json b/docs/mcp/modules/mail_intake.ingestion.json index 8cc077c..e59ba60 100644 --- a/docs/mcp/modules/mail_intake.ingestion.json +++ b/docs/mcp/modules/mail_intake.ingestion.json @@ -8,21 +8,21 @@ "name": "MailIntakeReader", "kind": "class", "path": "mail_intake.ingestion.MailIntakeReader", - "signature": "", + "signature": "MailIntakeReader(adapter: MailIntakeAdapter)", "docstring": "High-level read-only ingestion interface.\n\nNotes:\n **Responsibilities:**\n\n - This class is the primary entry point for consumers of the\n Mail Intake library.\n - It orchestrates the full ingestion pipeline:\n - Querying the adapter for message references.\n - Fetching raw provider messages.\n - Parsing and normalizing message data.\n - Constructing domain models.\n\n **Constraints:**\n\n - This class is intentionally: Provider-agnostic, stateless beyond\n iteration scope, read-only.", "members": { "iter_messages": { "name": "iter_messages", "kind": "function", "path": "mail_intake.ingestion.MailIntakeReader.iter_messages", - "signature": "", + "signature": "iter_messages(query: str)", "docstring": "Iterate over parsed messages matching a provider query.\n\nArgs:\n query (str):\n Provider-specific query string used to filter messages.\n\nYields:\n MailIntakeMessage:\n Fully parsed and normalized `MailIntakeMessage` instances.\n\nRaises:\n MailIntakeParsingError:\n If a message cannot be parsed." }, "iter_threads": { "name": "iter_threads", "kind": "function", "path": "mail_intake.ingestion.MailIntakeReader.iter_threads", - "signature": "", + "signature": "iter_threads(query: str)", "docstring": "Iterate over threads constructed from messages matching a query.\n\nArgs:\n query (str):\n Provider-specific query string used to filter messages.\n\nReturns:\n Iterator[MailIntakeThread]:\n An iterator over `MailIntakeThread` instances.\n\nRaises:\n `MailIntakeParsingError`:\n If a message cannot be parsed.\n\nNotes:\n **Guarantees:**\n\n - Messages are grouped by `thread_id` and yielded as complete\n thread objects containing all associated messages." } } @@ -34,53 +34,32 @@ "signature": null, "docstring": "# Summary\n\nHigh-level mail ingestion orchestration for Mail Intake.\n\nThis module provides the primary, provider-agnostic entry point for\nreading and processing mail data.\n\nIt coordinates:\n\n- Mail adapter access.\n- Message and thread iteration.\n- Header and body parsing.\n- Normalization and model construction.\n\nNo provider-specific logic or API semantics are permitted in this layer.", "members": { - "Iterator": { - "name": "Iterator", - "kind": "alias", - "path": "mail_intake.ingestion.reader.Iterator", - "signature": "", - "docstring": null - }, - "datetime": { - "name": "datetime", - "kind": "alias", - "path": "mail_intake.ingestion.reader.datetime", - "signature": "", - "docstring": null - }, - "Any": { - "name": "Any", - "kind": "alias", - "path": "mail_intake.ingestion.reader.Any", - "signature": "", - "docstring": null - }, "MailIntakeAdapter": { "name": "MailIntakeAdapter", "kind": "class", "path": "mail_intake.ingestion.reader.MailIntakeAdapter", - "signature": "", + "signature": null, "docstring": "Base adapter interface for mail providers.\n\nNotes:\n **Guarantees:**\n\n - Discover messages matching a query.\n - Retrieve full message payloads.\n - Retrieve full thread payloads.\n\n **Lifecycle:**\n\n - Adapters are intentionally read-only and must not mutate provider state.", "members": { "iter_message_refs": { "name": "iter_message_refs", "kind": "function", "path": "mail_intake.ingestion.reader.MailIntakeAdapter.iter_message_refs", - "signature": "", + "signature": "iter_message_refs(query: str)", "docstring": "Iterate over lightweight message references matching a query.\n\nArgs:\n query (str):\n Provider-specific query string used to filter messages.\n\nReturns:\n Iterator[dict[str, str]]:\n An iterator over lightweight message reference dictionaries.\n\nYields:\n dict[str, str]:\n Dictionaries containing message and thread identifiers.\n\nNotes:\n **Guarantees:**\n\n - Implementations must yield dictionaries containing at least\n `message_id` and `thread_id`.\n\nExample:\n Typical yield:\n\n ```python\n {\n \"message_id\": \"...\",\n \"thread_id\": \"...\"\n }\n ```" }, "fetch_message": { "name": "fetch_message", "kind": "function", "path": "mail_intake.ingestion.reader.MailIntakeAdapter.fetch_message", - "signature": "", + "signature": "fetch_message(message_id: str)", "docstring": "Fetch a full raw message by message identifier.\n\nArgs:\n message_id (str):\n Provider-specific message identifier.\n\nReturns:\n dict[str, Any]:\n Provider-native message payload (e.g., Gmail message JSON structure)." }, "fetch_thread": { "name": "fetch_thread", "kind": "function", "path": "mail_intake.ingestion.reader.MailIntakeAdapter.fetch_thread", - "signature": "", + "signature": "fetch_thread(thread_id: str)", "docstring": "Fetch a full raw thread by thread identifier.\n\nArgs:\n thread_id (str):\n Provider-specific thread identifier.\n\nReturns:\n dict[str, Any]:\n Provider-native thread payload." } } @@ -89,77 +68,77 @@ "name": "MailIntakeParsingError", "kind": "class", "path": "mail_intake.ingestion.reader.MailIntakeParsingError", - "signature": "", + "signature": null, "docstring": "Errors encountered while parsing message content.\n\nNotes:\n **Lifecycle:**\n\n - Raised when raw provider payloads cannot be interpreted or\n normalized into internal domain models." }, "MailIntakeMessage": { "name": "MailIntakeMessage", "kind": "class", "path": "mail_intake.ingestion.reader.MailIntakeMessage", - "signature": "", + "signature": "MailIntakeMessage(message_id: str, thread_id: str, timestamp: datetime, from_email: str, from_name: str | None, subject: str, body_text: str, snippet: str, raw_headers: dict[str, str])", "docstring": "Canonical internal representation of a single email message.\n\nNotes:\n **Guarantees:**\n\n - This model represents a fully parsed and normalized email message.\n - It is intentionally provider-agnostic and suitable for\n persistence, indexing, and downstream processing.\n\n **Constraints:**\n\n - No provider-specific identifiers, payloads, or API semantics\n should appear in this model.", "members": { "message_id": { "name": "message_id", "kind": "attribute", "path": "mail_intake.ingestion.reader.MailIntakeMessage.message_id", - "signature": "", + "signature": null, "docstring": "Provider-specific message identifier." }, "thread_id": { "name": "thread_id", "kind": "attribute", "path": "mail_intake.ingestion.reader.MailIntakeMessage.thread_id", - "signature": "", + "signature": null, "docstring": "Provider-specific thread identifier to which this message belongs." }, "timestamp": { "name": "timestamp", "kind": "attribute", "path": "mail_intake.ingestion.reader.MailIntakeMessage.timestamp", - "signature": "", + "signature": null, "docstring": "Message timestamp as a timezone-naive UTC datetime." }, "from_email": { "name": "from_email", "kind": "attribute", "path": "mail_intake.ingestion.reader.MailIntakeMessage.from_email", - "signature": "", + "signature": null, "docstring": "Sender email address." }, "from_name": { "name": "from_name", "kind": "attribute", "path": "mail_intake.ingestion.reader.MailIntakeMessage.from_name", - "signature": "", + "signature": null, "docstring": "Optional human-readable sender name." }, "subject": { "name": "subject", "kind": "attribute", "path": "mail_intake.ingestion.reader.MailIntakeMessage.subject", - "signature": "", + "signature": null, "docstring": "Raw subject line of the message." }, "body_text": { "name": "body_text", "kind": "attribute", "path": "mail_intake.ingestion.reader.MailIntakeMessage.body_text", - "signature": "", + "signature": null, "docstring": "Extracted plain-text body content of the message." }, "snippet": { "name": "snippet", "kind": "attribute", "path": "mail_intake.ingestion.reader.MailIntakeMessage.snippet", - "signature": "", + "signature": null, "docstring": "Short provider-supplied preview snippet of the message." }, "raw_headers": { "name": "raw_headers", "kind": "attribute", "path": "mail_intake.ingestion.reader.MailIntakeMessage.raw_headers", - "signature": "", + "signature": null, "docstring": "Normalized mapping of message headers (header name β†’ value)." } } @@ -168,49 +147,49 @@ "name": "MailIntakeThread", "kind": "class", "path": "mail_intake.ingestion.reader.MailIntakeThread", - "signature": "", + "signature": "MailIntakeThread(thread_id: str, normalized_subject: str, participants: set[str] = ..., messages: list[MailIntakeMessage] = ..., last_activity_at: datetime | None = ...)", "docstring": "Canonical internal representation of an email thread.\n\nNotes:\n **Guarantees:**\n\n - A thread groups multiple related messages under a single subject\n and participant set.\n - It is designed to support reasoning over conversational context\n such as job applications, interviews, follow-ups, and ongoing discussions.\n - This model is provider-agnostic and safe to persist.", "members": { "thread_id": { "name": "thread_id", "kind": "attribute", "path": "mail_intake.ingestion.reader.MailIntakeThread.thread_id", - "signature": "", + "signature": null, "docstring": "Provider-specific thread identifier." }, "normalized_subject": { "name": "normalized_subject", "kind": "attribute", "path": "mail_intake.ingestion.reader.MailIntakeThread.normalized_subject", - "signature": "", + "signature": null, "docstring": "Normalized subject line used to group related messages." }, "participants": { "name": "participants", "kind": "attribute", "path": "mail_intake.ingestion.reader.MailIntakeThread.participants", - "signature": "", + "signature": null, "docstring": "Set of unique participant email addresses observed in the thread." }, "messages": { "name": "messages", "kind": "attribute", "path": "mail_intake.ingestion.reader.MailIntakeThread.messages", - "signature": "", + "signature": null, "docstring": "Ordered list of messages belonging to this thread." }, "last_activity_at": { "name": "last_activity_at", "kind": "attribute", "path": "mail_intake.ingestion.reader.MailIntakeThread.last_activity_at", - "signature": "", + "signature": null, "docstring": "Timestamp of the most recent message in the thread." }, "add_message": { "name": "add_message", "kind": "function", "path": "mail_intake.ingestion.reader.MailIntakeThread.add_message", - "signature": "", + "signature": "add_message(message: MailIntakeMessage)", "docstring": "Add a message to the thread and update derived fields.\n\nArgs:\n message (MailIntakeMessage):\n Parsed mail message to add to the thread.\n\nNotes:\n **Responsibilities:**\n\n - Appends the message to the thread.\n - Tracks unique participants.\n - Updates the last activity timestamp." } } @@ -219,49 +198,49 @@ "name": "extract_body", "kind": "function", "path": "mail_intake.ingestion.reader.extract_body", - "signature": "", + "signature": "extract_body(payload: dict[str, Any])", "docstring": "Extract the best-effort message body from a Gmail payload.\n\nPriority:\n\n1. `text/plain`\n2. `text/html` (stripped to text)\n3. Single-part body\n4. Empty string (if nothing usable found)\n\nArgs:\n payload (dict[str, Any]):\n Provider-native message payload dictionary.\n\nReturns:\n str:\n Extracted plain-text message body." }, "extract_sender": { "name": "extract_sender", "kind": "function", "path": "mail_intake.ingestion.reader.extract_sender", - "signature": "", + "signature": "extract_sender(headers: dict[str, str])", "docstring": "Extract sender email and optional display name from headers.\n\nArgs:\n headers (dict[str, str]):\n Normalized header dictionary as returned by `parse_headers()`.\n\nReturns:\n tuple[str, str | None]:\n A tuple `(email, name)` where `email` is the sender email address\n and `name` is the display name, or `None` if unavailable.\n\nNotes:\n **Responsibilities:**\n\n - This function parses the `From` header and attempts to extract\n sender email address and optional human-readable display name.\n\nExample:\n Typical values:\n\n - `\"John Doe \"` -> `(\"john@example.com\", \"John Doe\")`\n - `\"john@example.com\"` -> `(\"john@example.com\", None)`" }, "parse_headers": { "name": "parse_headers", "kind": "function", "path": "mail_intake.ingestion.reader.parse_headers", - "signature": "", + "signature": "parse_headers(raw_headers: list[dict[str, str]])", "docstring": "Convert a list of Gmail-style headers into a normalized dict.\n\nArgs:\n raw_headers (list[dict[str, str]]):\n List of header dictionaries, each containing `name` and `value` keys.\n\nReturns:\n dict[str, str]:\n Dictionary mapping lowercase header names to stripped values.\n\nNotes:\n **Guarantees:**\n\n - Provider payloads (such as Gmail) typically represent headers as a\n list of name/value mappings.\n - This function normalizes them into a case-insensitive dictionary\n keyed by lowercase header names.\n\nExample:\n Typical usage:\n\n ```python\n Input:\n [\n {\"name\": \"From\", \"value\": \"John Doe \"},\n {\"name\": \"Subject\", \"value\": \"Re: Interview Update\"},\n ]\n\n Output:\n {\n \"from\": \"John Doe \",\n \"subject\": \"Re: Interview Update\",\n }\n ```" }, "normalize_subject": { "name": "normalize_subject", "kind": "function", "path": "mail_intake.ingestion.reader.normalize_subject", - "signature": "", + "signature": "normalize_subject(subject: str)", "docstring": "Normalize an email subject for thread-level comparison.\n\nArgs:\n subject (str):\n Raw subject line from a message header.\n\nReturns:\n str:\n Normalized subject string suitable for thread grouping.\n\nNotes:\n **Responsibilities:**\n\n - Strips common prefixes such as `Re:`, `Fwd:`, and `FW:`.\n - Repeats prefix stripping to handle stacked prefixes.\n - Collapses excessive whitespace.\n - Preserves original casing (no lowercasing).\n\n **Guarantees:**\n\n - This function is intentionally conservative and avoids aggressive\n transformations that could alter the semantic meaning of the subject." }, "MailIntakeReader": { "name": "MailIntakeReader", "kind": "class", "path": "mail_intake.ingestion.reader.MailIntakeReader", - "signature": "", + "signature": "MailIntakeReader(adapter: MailIntakeAdapter)", "docstring": "High-level read-only ingestion interface.\n\nNotes:\n **Responsibilities:**\n\n - This class is the primary entry point for consumers of the\n Mail Intake library.\n - It orchestrates the full ingestion pipeline:\n - Querying the adapter for message references.\n - Fetching raw provider messages.\n - Parsing and normalizing message data.\n - Constructing domain models.\n\n **Constraints:**\n\n - This class is intentionally: Provider-agnostic, stateless beyond\n iteration scope, read-only.", "members": { "iter_messages": { "name": "iter_messages", "kind": "function", "path": "mail_intake.ingestion.reader.MailIntakeReader.iter_messages", - "signature": "", + "signature": "iter_messages(query: str) -> Iterator[MailIntakeMessage]", "docstring": "Iterate over parsed messages matching a provider query.\n\nArgs:\n query (str):\n Provider-specific query string used to filter messages.\n\nYields:\n MailIntakeMessage:\n Fully parsed and normalized `MailIntakeMessage` instances.\n\nRaises:\n MailIntakeParsingError:\n If a message cannot be parsed." }, "iter_threads": { "name": "iter_threads", "kind": "function", "path": "mail_intake.ingestion.reader.MailIntakeReader.iter_threads", - "signature": "", + "signature": "iter_threads(query: str) -> Iterator[MailIntakeThread]", "docstring": "Iterate over threads constructed from messages matching a query.\n\nArgs:\n query (str):\n Provider-specific query string used to filter messages.\n\nReturns:\n Iterator[MailIntakeThread]:\n An iterator over `MailIntakeThread` instances.\n\nRaises:\n `MailIntakeParsingError`:\n If a message cannot be parsed.\n\nNotes:\n **Guarantees:**\n\n - Messages are grouped by `thread_id` and yielded as complete\n thread objects containing all associated messages." } } diff --git a/docs/mcp/modules/mail_intake.ingestion.reader.json b/docs/mcp/modules/mail_intake.ingestion.reader.json index d870543..2472acb 100644 --- a/docs/mcp/modules/mail_intake.ingestion.reader.json +++ b/docs/mcp/modules/mail_intake.ingestion.reader.json @@ -4,53 +4,32 @@ "path": "mail_intake.ingestion.reader", "docstring": "# Summary\n\nHigh-level mail ingestion orchestration for Mail Intake.\n\nThis module provides the primary, provider-agnostic entry point for\nreading and processing mail data.\n\nIt coordinates:\n\n- Mail adapter access.\n- Message and thread iteration.\n- Header and body parsing.\n- Normalization and model construction.\n\nNo provider-specific logic or API semantics are permitted in this layer.", "objects": { - "Iterator": { - "name": "Iterator", - "kind": "alias", - "path": "mail_intake.ingestion.reader.Iterator", - "signature": "", - "docstring": null - }, - "datetime": { - "name": "datetime", - "kind": "alias", - "path": "mail_intake.ingestion.reader.datetime", - "signature": "", - "docstring": null - }, - "Any": { - "name": "Any", - "kind": "alias", - "path": "mail_intake.ingestion.reader.Any", - "signature": "", - "docstring": null - }, "MailIntakeAdapter": { "name": "MailIntakeAdapter", "kind": "class", "path": "mail_intake.ingestion.reader.MailIntakeAdapter", - "signature": "", + "signature": null, "docstring": "Base adapter interface for mail providers.\n\nNotes:\n **Guarantees:**\n\n - Discover messages matching a query.\n - Retrieve full message payloads.\n - Retrieve full thread payloads.\n\n **Lifecycle:**\n\n - Adapters are intentionally read-only and must not mutate provider state.", "members": { "iter_message_refs": { "name": "iter_message_refs", "kind": "function", "path": "mail_intake.ingestion.reader.MailIntakeAdapter.iter_message_refs", - "signature": "", + "signature": "iter_message_refs(query: str)", "docstring": "Iterate over lightweight message references matching a query.\n\nArgs:\n query (str):\n Provider-specific query string used to filter messages.\n\nReturns:\n Iterator[dict[str, str]]:\n An iterator over lightweight message reference dictionaries.\n\nYields:\n dict[str, str]:\n Dictionaries containing message and thread identifiers.\n\nNotes:\n **Guarantees:**\n\n - Implementations must yield dictionaries containing at least\n `message_id` and `thread_id`.\n\nExample:\n Typical yield:\n\n ```python\n {\n \"message_id\": \"...\",\n \"thread_id\": \"...\"\n }\n ```" }, "fetch_message": { "name": "fetch_message", "kind": "function", "path": "mail_intake.ingestion.reader.MailIntakeAdapter.fetch_message", - "signature": "", + "signature": "fetch_message(message_id: str)", "docstring": "Fetch a full raw message by message identifier.\n\nArgs:\n message_id (str):\n Provider-specific message identifier.\n\nReturns:\n dict[str, Any]:\n Provider-native message payload (e.g., Gmail message JSON structure)." }, "fetch_thread": { "name": "fetch_thread", "kind": "function", "path": "mail_intake.ingestion.reader.MailIntakeAdapter.fetch_thread", - "signature": "", + "signature": "fetch_thread(thread_id: str)", "docstring": "Fetch a full raw thread by thread identifier.\n\nArgs:\n thread_id (str):\n Provider-specific thread identifier.\n\nReturns:\n dict[str, Any]:\n Provider-native thread payload." } } @@ -59,77 +38,77 @@ "name": "MailIntakeParsingError", "kind": "class", "path": "mail_intake.ingestion.reader.MailIntakeParsingError", - "signature": "", + "signature": null, "docstring": "Errors encountered while parsing message content.\n\nNotes:\n **Lifecycle:**\n\n - Raised when raw provider payloads cannot be interpreted or\n normalized into internal domain models." }, "MailIntakeMessage": { "name": "MailIntakeMessage", "kind": "class", "path": "mail_intake.ingestion.reader.MailIntakeMessage", - "signature": "", + "signature": "MailIntakeMessage(message_id: str, thread_id: str, timestamp: datetime, from_email: str, from_name: str | None, subject: str, body_text: str, snippet: str, raw_headers: dict[str, str])", "docstring": "Canonical internal representation of a single email message.\n\nNotes:\n **Guarantees:**\n\n - This model represents a fully parsed and normalized email message.\n - It is intentionally provider-agnostic and suitable for\n persistence, indexing, and downstream processing.\n\n **Constraints:**\n\n - No provider-specific identifiers, payloads, or API semantics\n should appear in this model.", "members": { "message_id": { "name": "message_id", "kind": "attribute", "path": "mail_intake.ingestion.reader.MailIntakeMessage.message_id", - "signature": "", + "signature": null, "docstring": "Provider-specific message identifier." }, "thread_id": { "name": "thread_id", "kind": "attribute", "path": "mail_intake.ingestion.reader.MailIntakeMessage.thread_id", - "signature": "", + "signature": null, "docstring": "Provider-specific thread identifier to which this message belongs." }, "timestamp": { "name": "timestamp", "kind": "attribute", "path": "mail_intake.ingestion.reader.MailIntakeMessage.timestamp", - "signature": "", + "signature": null, "docstring": "Message timestamp as a timezone-naive UTC datetime." }, "from_email": { "name": "from_email", "kind": "attribute", "path": "mail_intake.ingestion.reader.MailIntakeMessage.from_email", - "signature": "", + "signature": null, "docstring": "Sender email address." }, "from_name": { "name": "from_name", "kind": "attribute", "path": "mail_intake.ingestion.reader.MailIntakeMessage.from_name", - "signature": "", + "signature": null, "docstring": "Optional human-readable sender name." }, "subject": { "name": "subject", "kind": "attribute", "path": "mail_intake.ingestion.reader.MailIntakeMessage.subject", - "signature": "", + "signature": null, "docstring": "Raw subject line of the message." }, "body_text": { "name": "body_text", "kind": "attribute", "path": "mail_intake.ingestion.reader.MailIntakeMessage.body_text", - "signature": "", + "signature": null, "docstring": "Extracted plain-text body content of the message." }, "snippet": { "name": "snippet", "kind": "attribute", "path": "mail_intake.ingestion.reader.MailIntakeMessage.snippet", - "signature": "", + "signature": null, "docstring": "Short provider-supplied preview snippet of the message." }, "raw_headers": { "name": "raw_headers", "kind": "attribute", "path": "mail_intake.ingestion.reader.MailIntakeMessage.raw_headers", - "signature": "", + "signature": null, "docstring": "Normalized mapping of message headers (header name β†’ value)." } } @@ -138,49 +117,49 @@ "name": "MailIntakeThread", "kind": "class", "path": "mail_intake.ingestion.reader.MailIntakeThread", - "signature": "", + "signature": "MailIntakeThread(thread_id: str, normalized_subject: str, participants: set[str] = ..., messages: list[MailIntakeMessage] = ..., last_activity_at: datetime | None = ...)", "docstring": "Canonical internal representation of an email thread.\n\nNotes:\n **Guarantees:**\n\n - A thread groups multiple related messages under a single subject\n and participant set.\n - It is designed to support reasoning over conversational context\n such as job applications, interviews, follow-ups, and ongoing discussions.\n - This model is provider-agnostic and safe to persist.", "members": { "thread_id": { "name": "thread_id", "kind": "attribute", "path": "mail_intake.ingestion.reader.MailIntakeThread.thread_id", - "signature": "", + "signature": null, "docstring": "Provider-specific thread identifier." }, "normalized_subject": { "name": "normalized_subject", "kind": "attribute", "path": "mail_intake.ingestion.reader.MailIntakeThread.normalized_subject", - "signature": "", + "signature": null, "docstring": "Normalized subject line used to group related messages." }, "participants": { "name": "participants", "kind": "attribute", "path": "mail_intake.ingestion.reader.MailIntakeThread.participants", - "signature": "", + "signature": null, "docstring": "Set of unique participant email addresses observed in the thread." }, "messages": { "name": "messages", "kind": "attribute", "path": "mail_intake.ingestion.reader.MailIntakeThread.messages", - "signature": "", + "signature": null, "docstring": "Ordered list of messages belonging to this thread." }, "last_activity_at": { "name": "last_activity_at", "kind": "attribute", "path": "mail_intake.ingestion.reader.MailIntakeThread.last_activity_at", - "signature": "", + "signature": null, "docstring": "Timestamp of the most recent message in the thread." }, "add_message": { "name": "add_message", "kind": "function", "path": "mail_intake.ingestion.reader.MailIntakeThread.add_message", - "signature": "", + "signature": "add_message(message: MailIntakeMessage)", "docstring": "Add a message to the thread and update derived fields.\n\nArgs:\n message (MailIntakeMessage):\n Parsed mail message to add to the thread.\n\nNotes:\n **Responsibilities:**\n\n - Appends the message to the thread.\n - Tracks unique participants.\n - Updates the last activity timestamp." } } @@ -189,49 +168,49 @@ "name": "extract_body", "kind": "function", "path": "mail_intake.ingestion.reader.extract_body", - "signature": "", + "signature": "extract_body(payload: dict[str, Any])", "docstring": "Extract the best-effort message body from a Gmail payload.\n\nPriority:\n\n1. `text/plain`\n2. `text/html` (stripped to text)\n3. Single-part body\n4. Empty string (if nothing usable found)\n\nArgs:\n payload (dict[str, Any]):\n Provider-native message payload dictionary.\n\nReturns:\n str:\n Extracted plain-text message body." }, "extract_sender": { "name": "extract_sender", "kind": "function", "path": "mail_intake.ingestion.reader.extract_sender", - "signature": "", + "signature": "extract_sender(headers: dict[str, str])", "docstring": "Extract sender email and optional display name from headers.\n\nArgs:\n headers (dict[str, str]):\n Normalized header dictionary as returned by `parse_headers()`.\n\nReturns:\n tuple[str, str | None]:\n A tuple `(email, name)` where `email` is the sender email address\n and `name` is the display name, or `None` if unavailable.\n\nNotes:\n **Responsibilities:**\n\n - This function parses the `From` header and attempts to extract\n sender email address and optional human-readable display name.\n\nExample:\n Typical values:\n\n - `\"John Doe \"` -> `(\"john@example.com\", \"John Doe\")`\n - `\"john@example.com\"` -> `(\"john@example.com\", None)`" }, "parse_headers": { "name": "parse_headers", "kind": "function", "path": "mail_intake.ingestion.reader.parse_headers", - "signature": "", + "signature": "parse_headers(raw_headers: list[dict[str, str]])", "docstring": "Convert a list of Gmail-style headers into a normalized dict.\n\nArgs:\n raw_headers (list[dict[str, str]]):\n List of header dictionaries, each containing `name` and `value` keys.\n\nReturns:\n dict[str, str]:\n Dictionary mapping lowercase header names to stripped values.\n\nNotes:\n **Guarantees:**\n\n - Provider payloads (such as Gmail) typically represent headers as a\n list of name/value mappings.\n - This function normalizes them into a case-insensitive dictionary\n keyed by lowercase header names.\n\nExample:\n Typical usage:\n\n ```python\n Input:\n [\n {\"name\": \"From\", \"value\": \"John Doe \"},\n {\"name\": \"Subject\", \"value\": \"Re: Interview Update\"},\n ]\n\n Output:\n {\n \"from\": \"John Doe \",\n \"subject\": \"Re: Interview Update\",\n }\n ```" }, "normalize_subject": { "name": "normalize_subject", "kind": "function", "path": "mail_intake.ingestion.reader.normalize_subject", - "signature": "", + "signature": "normalize_subject(subject: str)", "docstring": "Normalize an email subject for thread-level comparison.\n\nArgs:\n subject (str):\n Raw subject line from a message header.\n\nReturns:\n str:\n Normalized subject string suitable for thread grouping.\n\nNotes:\n **Responsibilities:**\n\n - Strips common prefixes such as `Re:`, `Fwd:`, and `FW:`.\n - Repeats prefix stripping to handle stacked prefixes.\n - Collapses excessive whitespace.\n - Preserves original casing (no lowercasing).\n\n **Guarantees:**\n\n - This function is intentionally conservative and avoids aggressive\n transformations that could alter the semantic meaning of the subject." }, "MailIntakeReader": { "name": "MailIntakeReader", "kind": "class", "path": "mail_intake.ingestion.reader.MailIntakeReader", - "signature": "", + "signature": "MailIntakeReader(adapter: MailIntakeAdapter)", "docstring": "High-level read-only ingestion interface.\n\nNotes:\n **Responsibilities:**\n\n - This class is the primary entry point for consumers of the\n Mail Intake library.\n - It orchestrates the full ingestion pipeline:\n - Querying the adapter for message references.\n - Fetching raw provider messages.\n - Parsing and normalizing message data.\n - Constructing domain models.\n\n **Constraints:**\n\n - This class is intentionally: Provider-agnostic, stateless beyond\n iteration scope, read-only.", "members": { "iter_messages": { "name": "iter_messages", "kind": "function", "path": "mail_intake.ingestion.reader.MailIntakeReader.iter_messages", - "signature": "", + "signature": "iter_messages(query: str) -> Iterator[MailIntakeMessage]", "docstring": "Iterate over parsed messages matching a provider query.\n\nArgs:\n query (str):\n Provider-specific query string used to filter messages.\n\nYields:\n MailIntakeMessage:\n Fully parsed and normalized `MailIntakeMessage` instances.\n\nRaises:\n MailIntakeParsingError:\n If a message cannot be parsed." }, "iter_threads": { "name": "iter_threads", "kind": "function", "path": "mail_intake.ingestion.reader.MailIntakeReader.iter_threads", - "signature": "", + "signature": "iter_threads(query: str) -> Iterator[MailIntakeThread]", "docstring": "Iterate over threads constructed from messages matching a query.\n\nArgs:\n query (str):\n Provider-specific query string used to filter messages.\n\nReturns:\n Iterator[MailIntakeThread]:\n An iterator over `MailIntakeThread` instances.\n\nRaises:\n `MailIntakeParsingError`:\n If a message cannot be parsed.\n\nNotes:\n **Guarantees:**\n\n - Messages are grouped by `thread_id` and yielded as complete\n thread objects containing all associated messages." } } diff --git a/docs/mcp/modules/mail_intake.json b/docs/mcp/modules/mail_intake.json index 041d5b5..fe3dba7 100644 --- a/docs/mcp/modules/mail_intake.json +++ b/docs/mcp/modules/mail_intake.json @@ -11,18 +11,11 @@ "signature": null, "docstring": "# Summary\n\nGlobal configuration models for Mail Intake.\n\nThis module defines the **top-level configuration object** used to control\nmail ingestion behavior across adapters, authentication providers, and\ningestion workflows.\n\nConfiguration is intentionally explicit, immutable, and free of implicit\nenvironment reads to ensure predictability and testability.", "members": { - "dataclass": { - "name": "dataclass", - "kind": "alias", - "path": "mail_intake.config.dataclass", - "signature": "", - "docstring": null - }, "MailIntakeConfig": { "name": "MailIntakeConfig", "kind": "class", "path": "mail_intake.config.MailIntakeConfig", - "signature": "", + "signature": "MailIntakeConfig(provider: str = ..., user_id: str = ..., readonly: bool = ..., credentials_path: str | None = ..., token_path: str | None = ...)", "docstring": "Global configuration for `mail-intake`.\n\nNotes:\n **Guarantees:**\n\n - This configuration is intentionally explicit and immutable.\n - No implicit environment reads or global state.\n - Explicit configuration over implicit defaults.\n - No direct environment or filesystem access.\n - This model is safe to pass across layers and suitable for\n serialization.", "members": { "provider": { @@ -75,28 +68,28 @@ "name": "MailIntakeError", "kind": "class", "path": "mail_intake.exceptions.MailIntakeError", - "signature": "", + "signature": null, "docstring": "Base exception for all Mail Intake errors.\n\nNotes:\n **Guarantees:**\n\n - This is the root of the Mail Intake exception hierarchy\n - All errors raised by the library must derive from this class\n - Consumers should generally catch this type when handling library-level failures" }, "MailIntakeAuthError": { "name": "MailIntakeAuthError", "kind": "class", "path": "mail_intake.exceptions.MailIntakeAuthError", - "signature": "", + "signature": null, "docstring": "Authentication and credential-related failures.\n\nNotes:\n **Lifecycle:**\n\n - Raised when authentication providers are unable to acquire,\n refresh, or persist valid credentials." }, "MailIntakeAdapterError": { "name": "MailIntakeAdapterError", "kind": "class", "path": "mail_intake.exceptions.MailIntakeAdapterError", - "signature": "", + "signature": null, "docstring": "Errors raised by mail provider adapters.\n\nNotes:\n **Lifecycle:**\n\n - Raised when a provider adapter encounters API errors, transport\n failures, or invalid provider responses." }, "MailIntakeParsingError": { "name": "MailIntakeParsingError", "kind": "class", "path": "mail_intake.exceptions.MailIntakeParsingError", - "signature": "", + "signature": null, "docstring": "Errors encountered while parsing message content.\n\nNotes:\n **Lifecycle:**\n\n - Raised when raw provider payloads cannot be interpreted or\n normalized into internal domain models." } } @@ -112,28 +105,28 @@ "name": "MailIntakeAdapter", "kind": "class", "path": "mail_intake.adapters.MailIntakeAdapter", - "signature": "", + "signature": null, "docstring": "Base adapter interface for mail providers.\n\nNotes:\n **Guarantees:**\n\n - Discover messages matching a query.\n - Retrieve full message payloads.\n - Retrieve full thread payloads.\n\n **Lifecycle:**\n\n - Adapters are intentionally read-only and must not mutate provider state.", "members": { "iter_message_refs": { "name": "iter_message_refs", "kind": "function", "path": "mail_intake.adapters.MailIntakeAdapter.iter_message_refs", - "signature": "", + "signature": "iter_message_refs(query: str)", "docstring": "Iterate over lightweight message references matching a query.\n\nArgs:\n query (str):\n Provider-specific query string used to filter messages.\n\nReturns:\n Iterator[dict[str, str]]:\n An iterator over lightweight message reference dictionaries.\n\nYields:\n dict[str, str]:\n Dictionaries containing message and thread identifiers.\n\nNotes:\n **Guarantees:**\n\n - Implementations must yield dictionaries containing at least\n `message_id` and `thread_id`.\n\nExample:\n Typical yield:\n\n ```python\n {\n \"message_id\": \"...\",\n \"thread_id\": \"...\"\n }\n ```" }, "fetch_message": { "name": "fetch_message", "kind": "function", "path": "mail_intake.adapters.MailIntakeAdapter.fetch_message", - "signature": "", + "signature": "fetch_message(message_id: str)", "docstring": "Fetch a full raw message by message identifier.\n\nArgs:\n message_id (str):\n Provider-specific message identifier.\n\nReturns:\n dict[str, Any]:\n Provider-native message payload (e.g., Gmail message JSON structure)." }, "fetch_thread": { "name": "fetch_thread", "kind": "function", "path": "mail_intake.adapters.MailIntakeAdapter.fetch_thread", - "signature": "", + "signature": "fetch_thread(thread_id: str)", "docstring": "Fetch a full raw thread by thread identifier.\n\nArgs:\n thread_id (str):\n Provider-specific thread identifier.\n\nReturns:\n dict[str, Any]:\n Provider-native thread payload." } } @@ -142,35 +135,35 @@ "name": "MailIntakeGmailAdapter", "kind": "class", "path": "mail_intake.adapters.MailIntakeGmailAdapter", - "signature": "", + "signature": "MailIntakeGmailAdapter(auth_provider: MailIntakeAuthProvider[Any], user_id: str = 'me')", "docstring": "Gmail read-only adapter.\n\nThis adapter implements the `MailIntakeAdapter` interface using the\nGmail REST API. It translates the generic mail intake contract into\nGmail-specific API calls.\n\nNotes:\n **Responsibilities:**\n\n - This class is the ONLY place where `googleapiclient` is imported.\n - Gmail REST semantics are known.\n - `.execute()` is called.\n\n **Constraints:**\n\n - Must remain thin and imperative.\n - Must not perform parsing or interpretation.\n - Must not expose Gmail-specific types beyond this class.", "members": { "service": { "name": "service", "kind": "attribute", "path": "mail_intake.adapters.MailIntakeGmailAdapter.service", - "signature": "", + "signature": null, "docstring": "Lazily initialize and return the Gmail API service client.\n\nRaises:\n MailIntakeAdapterError:\n If the Gmail service cannot be initialized." }, "iter_message_refs": { "name": "iter_message_refs", "kind": "function", "path": "mail_intake.adapters.MailIntakeGmailAdapter.iter_message_refs", - "signature": "", + "signature": "iter_message_refs(query: str)", "docstring": "Iterate over message references matching the query.\n\nArgs:\n query (str):\n Gmail search query string.\n\nYields:\n dict[str, str]:\n Dictionaries containing ``message_id`` and ``thread_id``.\n\nRaises:\n MailIntakeAdapterError:\n If the Gmail API returns an error." }, "fetch_message": { "name": "fetch_message", "kind": "function", "path": "mail_intake.adapters.MailIntakeGmailAdapter.fetch_message", - "signature": "", + "signature": "fetch_message(message_id: str)", "docstring": "Fetch a full Gmail message by message ID.\n\nArgs:\n message_id (str):\n Gmail message identifier.\n\nReturns:\n dict[str, Any]:\n Provider-native Gmail message payload.\n\nRaises:\n MailIntakeAdapterError:\n If the Gmail API returns an error." }, "fetch_thread": { "name": "fetch_thread", "kind": "function", "path": "mail_intake.adapters.MailIntakeGmailAdapter.fetch_thread", - "signature": "", + "signature": "fetch_thread(thread_id: str)", "docstring": "Fetch a full Gmail thread by thread ID.\n\nArgs:\n thread_id (str):\n Gmail thread identifier.\n\nReturns:\n dict[str, Any]:\n Provider-native Gmail thread payload.\n\nRaises:\n MailIntakeAdapterError:\n If the Gmail API returns an error." } } @@ -182,60 +175,32 @@ "signature": null, "docstring": "# Summary\n\nMail provider adapter contracts for Mail Intake.\n\nThis module defines the **provider-agnostic adapter interface** used for\nread-only mail ingestion.\n\nAdapters encapsulate all provider-specific access logic and expose a\nminimal, normalized contract to the rest of the system. No provider-specific\ntypes or semantics should leak beyond implementations of this interface.", "members": { - "ABC": { - "name": "ABC", - "kind": "alias", - "path": "mail_intake.adapters.base.ABC", - "signature": "", - "docstring": null - }, - "abstractmethod": { - "name": "abstractmethod", - "kind": "alias", - "path": "mail_intake.adapters.base.abstractmethod", - "signature": "", - "docstring": null - }, - "Iterator": { - "name": "Iterator", - "kind": "alias", - "path": "mail_intake.adapters.base.Iterator", - "signature": "", - "docstring": null - }, - "Any": { - "name": "Any", - "kind": "alias", - "path": "mail_intake.adapters.base.Any", - "signature": "", - "docstring": null - }, "MailIntakeAdapter": { "name": "MailIntakeAdapter", "kind": "class", "path": "mail_intake.adapters.base.MailIntakeAdapter", - "signature": "", + "signature": null, "docstring": "Base adapter interface for mail providers.\n\nNotes:\n **Guarantees:**\n\n - Discover messages matching a query.\n - Retrieve full message payloads.\n - Retrieve full thread payloads.\n\n **Lifecycle:**\n\n - Adapters are intentionally read-only and must not mutate provider state.", "members": { "iter_message_refs": { "name": "iter_message_refs", "kind": "function", "path": "mail_intake.adapters.base.MailIntakeAdapter.iter_message_refs", - "signature": "", + "signature": "iter_message_refs(query: str) -> Iterator[dict[str, str]]", "docstring": "Iterate over lightweight message references matching a query.\n\nArgs:\n query (str):\n Provider-specific query string used to filter messages.\n\nReturns:\n Iterator[dict[str, str]]:\n An iterator over lightweight message reference dictionaries.\n\nYields:\n dict[str, str]:\n Dictionaries containing message and thread identifiers.\n\nNotes:\n **Guarantees:**\n\n - Implementations must yield dictionaries containing at least\n `message_id` and `thread_id`.\n\nExample:\n Typical yield:\n\n ```python\n {\n \"message_id\": \"...\",\n \"thread_id\": \"...\"\n }\n ```" }, "fetch_message": { "name": "fetch_message", "kind": "function", "path": "mail_intake.adapters.base.MailIntakeAdapter.fetch_message", - "signature": "", + "signature": "fetch_message(message_id: str) -> dict[str, Any]", "docstring": "Fetch a full raw message by message identifier.\n\nArgs:\n message_id (str):\n Provider-specific message identifier.\n\nReturns:\n dict[str, Any]:\n Provider-native message payload (e.g., Gmail message JSON structure)." }, "fetch_thread": { "name": "fetch_thread", "kind": "function", "path": "mail_intake.adapters.base.MailIntakeAdapter.fetch_thread", - "signature": "", + "signature": "fetch_thread(thread_id: str) -> dict[str, Any]", "docstring": "Fetch a full raw thread by thread identifier.\n\nArgs:\n thread_id (str):\n Provider-specific thread identifier.\n\nReturns:\n dict[str, Any]:\n Provider-native thread payload." } } @@ -249,60 +214,32 @@ "signature": null, "docstring": "# Summary\n\nGmail adapter implementation for Mail Intake.\n\nThis module provides a **Gmail-specific implementation** of the\n`MailIntakeAdapter` contract.\n\nIt is the only place in the codebase where:\n\n- `googleapiclient` is imported.\n- Gmail REST API semantics are known.\n- Low-level `.execute()` calls are made.\n\nAll Gmail-specific behavior must be strictly contained within this module.", "members": { - "Iterator": { - "name": "Iterator", - "kind": "alias", - "path": "mail_intake.adapters.gmail.Iterator", - "signature": "", - "docstring": null - }, - "Any": { - "name": "Any", - "kind": "alias", - "path": "mail_intake.adapters.gmail.Any", - "signature": "", - "docstring": null - }, - "build": { - "name": "build", - "kind": "alias", - "path": "mail_intake.adapters.gmail.build", - "signature": "", - "docstring": null - }, - "HttpError": { - "name": "HttpError", - "kind": "alias", - "path": "mail_intake.adapters.gmail.HttpError", - "signature": "", - "docstring": null - }, "MailIntakeAdapter": { "name": "MailIntakeAdapter", "kind": "class", "path": "mail_intake.adapters.gmail.MailIntakeAdapter", - "signature": "", + "signature": null, "docstring": "Base adapter interface for mail providers.\n\nNotes:\n **Guarantees:**\n\n - Discover messages matching a query.\n - Retrieve full message payloads.\n - Retrieve full thread payloads.\n\n **Lifecycle:**\n\n - Adapters are intentionally read-only and must not mutate provider state.", "members": { "iter_message_refs": { "name": "iter_message_refs", "kind": "function", "path": "mail_intake.adapters.gmail.MailIntakeAdapter.iter_message_refs", - "signature": "", + "signature": "iter_message_refs(query: str)", "docstring": "Iterate over lightweight message references matching a query.\n\nArgs:\n query (str):\n Provider-specific query string used to filter messages.\n\nReturns:\n Iterator[dict[str, str]]:\n An iterator over lightweight message reference dictionaries.\n\nYields:\n dict[str, str]:\n Dictionaries containing message and thread identifiers.\n\nNotes:\n **Guarantees:**\n\n - Implementations must yield dictionaries containing at least\n `message_id` and `thread_id`.\n\nExample:\n Typical yield:\n\n ```python\n {\n \"message_id\": \"...\",\n \"thread_id\": \"...\"\n }\n ```" }, "fetch_message": { "name": "fetch_message", "kind": "function", "path": "mail_intake.adapters.gmail.MailIntakeAdapter.fetch_message", - "signature": "", + "signature": "fetch_message(message_id: str)", "docstring": "Fetch a full raw message by message identifier.\n\nArgs:\n message_id (str):\n Provider-specific message identifier.\n\nReturns:\n dict[str, Any]:\n Provider-native message payload (e.g., Gmail message JSON structure)." }, "fetch_thread": { "name": "fetch_thread", "kind": "function", "path": "mail_intake.adapters.gmail.MailIntakeAdapter.fetch_thread", - "signature": "", + "signature": "fetch_thread(thread_id: str)", "docstring": "Fetch a full raw thread by thread identifier.\n\nArgs:\n thread_id (str):\n Provider-specific thread identifier.\n\nReturns:\n dict[str, Any]:\n Provider-native thread payload." } } @@ -311,14 +248,14 @@ "name": "MailIntakeAuthProvider", "kind": "class", "path": "mail_intake.adapters.gmail.MailIntakeAuthProvider", - "signature": "", + "signature": null, "docstring": "Abstract base class for authentication providers.\n\nThis interface enforces a strict contract between authentication\nproviders and mail adapters by requiring providers to explicitly\ndeclare the type of credentials they return.\n\nNotes:\n **Responsibilities:**\n\n - Acquire credentials from an external provider.\n - Refresh or revalidate credentials as needed.\n - Handle authentication-specific failure modes.\n - Coordinate with credential persistence layers where applicable.\n\n **Constraints:**\n\n - Mail adapters must treat returned credentials as opaque and\n provider-specific.\n - Mail adapters rely only on the declared credential type expected\n by the adapter.", "members": { "get_credentials": { "name": "get_credentials", "kind": "function", "path": "mail_intake.adapters.gmail.MailIntakeAuthProvider.get_credentials", - "signature": "", + "signature": "get_credentials()", "docstring": "Retrieve valid, provider-specific credentials.\n\nReturns:\n T:\n Credentials of type `T` suitable for immediate use by the\n corresponding mail adapter.\n\nRaises:\n Exception:\n An authentication-specific exception indicating that\n credentials could not be obtained or validated.\n\nNotes:\n **Guarantees:**\n\n - This method is synchronous by design.\n - Represents the sole entry point through which adapters obtain\n authentication material.\n - Implementations must either return credentials of the declared\n type `T` that are valid at the time of return or raise an exception." } } @@ -327,14 +264,14 @@ "name": "MailIntakeAdapterError", "kind": "class", "path": "mail_intake.adapters.gmail.MailIntakeAdapterError", - "signature": "", + "signature": null, "docstring": "Errors raised by mail provider adapters.\n\nNotes:\n **Lifecycle:**\n\n - Raised when a provider adapter encounters API errors, transport\n failures, or invalid provider responses." }, "MailIntakeGmailAdapter": { "name": "MailIntakeGmailAdapter", "kind": "class", "path": "mail_intake.adapters.gmail.MailIntakeGmailAdapter", - "signature": "", + "signature": "MailIntakeGmailAdapter(auth_provider: MailIntakeAuthProvider[Any], user_id: str = 'me')", "docstring": "Gmail read-only adapter.\n\nThis adapter implements the `MailIntakeAdapter` interface using the\nGmail REST API. It translates the generic mail intake contract into\nGmail-specific API calls.\n\nNotes:\n **Responsibilities:**\n\n - This class is the ONLY place where `googleapiclient` is imported.\n - Gmail REST semantics are known.\n - `.execute()` is called.\n\n **Constraints:**\n\n - Must remain thin and imperative.\n - Must not perform parsing or interpretation.\n - Must not expose Gmail-specific types beyond this class.", "members": { "service": { @@ -348,21 +285,21 @@ "name": "iter_message_refs", "kind": "function", "path": "mail_intake.adapters.gmail.MailIntakeGmailAdapter.iter_message_refs", - "signature": "", + "signature": "iter_message_refs(query: str) -> Iterator[dict[str, str]]", "docstring": "Iterate over message references matching the query.\n\nArgs:\n query (str):\n Gmail search query string.\n\nYields:\n dict[str, str]:\n Dictionaries containing ``message_id`` and ``thread_id``.\n\nRaises:\n MailIntakeAdapterError:\n If the Gmail API returns an error." }, "fetch_message": { "name": "fetch_message", "kind": "function", "path": "mail_intake.adapters.gmail.MailIntakeGmailAdapter.fetch_message", - "signature": "", + "signature": "fetch_message(message_id: str) -> dict[str, Any]", "docstring": "Fetch a full Gmail message by message ID.\n\nArgs:\n message_id (str):\n Gmail message identifier.\n\nReturns:\n dict[str, Any]:\n Provider-native Gmail message payload.\n\nRaises:\n MailIntakeAdapterError:\n If the Gmail API returns an error." }, "fetch_thread": { "name": "fetch_thread", "kind": "function", "path": "mail_intake.adapters.gmail.MailIntakeGmailAdapter.fetch_thread", - "signature": "", + "signature": "fetch_thread(thread_id: str) -> dict[str, Any]", "docstring": "Fetch a full Gmail thread by thread ID.\n\nArgs:\n thread_id (str):\n Gmail thread identifier.\n\nReturns:\n dict[str, Any]:\n Provider-native Gmail thread payload.\n\nRaises:\n MailIntakeAdapterError:\n If the Gmail API returns an error." } } @@ -382,14 +319,14 @@ "name": "MailIntakeAuthProvider", "kind": "class", "path": "mail_intake.auth.MailIntakeAuthProvider", - "signature": "", + "signature": null, "docstring": "Abstract base class for authentication providers.\n\nThis interface enforces a strict contract between authentication\nproviders and mail adapters by requiring providers to explicitly\ndeclare the type of credentials they return.\n\nNotes:\n **Responsibilities:**\n\n - Acquire credentials from an external provider.\n - Refresh or revalidate credentials as needed.\n - Handle authentication-specific failure modes.\n - Coordinate with credential persistence layers where applicable.\n\n **Constraints:**\n\n - Mail adapters must treat returned credentials as opaque and\n provider-specific.\n - Mail adapters rely only on the declared credential type expected\n by the adapter.", "members": { "get_credentials": { "name": "get_credentials", "kind": "function", "path": "mail_intake.auth.MailIntakeAuthProvider.get_credentials", - "signature": "", + "signature": "get_credentials()", "docstring": "Retrieve valid, provider-specific credentials.\n\nReturns:\n T:\n Credentials of type `T` suitable for immediate use by the\n corresponding mail adapter.\n\nRaises:\n Exception:\n An authentication-specific exception indicating that\n credentials could not be obtained or validated.\n\nNotes:\n **Guarantees:**\n\n - This method is synchronous by design.\n - Represents the sole entry point through which adapters obtain\n authentication material.\n - Implementations must either return credentials of the declared\n type `T` that are valid at the time of return or raise an exception." } } @@ -398,35 +335,35 @@ "name": "MailIntakeGoogleAuth", "kind": "class", "path": "mail_intake.auth.MailIntakeGoogleAuth", - "signature": "", + "signature": "MailIntakeGoogleAuth(credentials_path: str, store: CredentialStore[Any], scopes: Sequence[str])", "docstring": "Google OAuth provider for Gmail access.\n\nThis provider implements the `MailIntakeAuthProvider` interface using\nGoogle's OAuth 2.0 flow and credential management libraries.\n\nNotes:\n **Responsibilities:**\n\n - Load cached credentials from a credential store when available.\n - Refresh expired credentials when possible.\n - Initiate an interactive OAuth flow only when required.\n - Persist refreshed or newly obtained credentials via the store.\n\n **Guarantees:**\n\n - This class is synchronous by design and maintains a minimal\n internal state.", "members": { "credentials_path": { "name": "credentials_path", "kind": "attribute", "path": "mail_intake.auth.MailIntakeGoogleAuth.credentials_path", - "signature": "", + "signature": null, "docstring": null }, "store": { "name": "store", "kind": "attribute", "path": "mail_intake.auth.MailIntakeGoogleAuth.store", - "signature": "", + "signature": null, "docstring": null }, "scopes": { "name": "scopes", "kind": "attribute", "path": "mail_intake.auth.MailIntakeGoogleAuth.scopes", - "signature": "", + "signature": null, "docstring": null }, "get_credentials": { "name": "get_credentials", "kind": "function", "path": "mail_intake.auth.MailIntakeGoogleAuth.get_credentials", - "signature": "", + "signature": "get_credentials()", "docstring": "Retrieve valid Google OAuth credentials.\n\nReturns:\n Credentials:\n A `google.oauth2.credentials.Credentials` instance suitable\n for use with Google API clients.\n\nRaises:\n MailIntakeAuthError:\n If credentials cannot be loaded, refreshed,\n or obtained via interactive authentication.\n\nNotes:\n **Lifecycle:**\n\n - Load cached credentials from the configured credential store.\n - Refresh expired credentials when possible.\n - Perform an interactive OAuth login as a fallback.\n - Persist valid credentials for future use." } } @@ -438,34 +375,6 @@ "signature": null, "docstring": "# Summary\n\nAuthentication provider contracts for Mail Intake.\n\nThis module defines the **authentication abstraction layer** used by mail\nadapters to obtain provider-specific credentials.\n\nAuthentication concerns are intentionally decoupled from adapter logic.\nAdapters depend only on this interface and must not be aware of how\ncredentials are acquired, refreshed, or persisted.", "members": { - "ABC": { - "name": "ABC", - "kind": "alias", - "path": "mail_intake.auth.base.ABC", - "signature": "", - "docstring": null - }, - "abstractmethod": { - "name": "abstractmethod", - "kind": "alias", - "path": "mail_intake.auth.base.abstractmethod", - "signature": "", - "docstring": null - }, - "Generic": { - "name": "Generic", - "kind": "alias", - "path": "mail_intake.auth.base.Generic", - "signature": "", - "docstring": null - }, - "TypeVar": { - "name": "TypeVar", - "kind": "alias", - "path": "mail_intake.auth.base.TypeVar", - "signature": "", - "docstring": null - }, "T": { "name": "T", "kind": "attribute", @@ -477,14 +386,14 @@ "name": "MailIntakeAuthProvider", "kind": "class", "path": "mail_intake.auth.base.MailIntakeAuthProvider", - "signature": "", + "signature": null, "docstring": "Abstract base class for authentication providers.\n\nThis interface enforces a strict contract between authentication\nproviders and mail adapters by requiring providers to explicitly\ndeclare the type of credentials they return.\n\nNotes:\n **Responsibilities:**\n\n - Acquire credentials from an external provider.\n - Refresh or revalidate credentials as needed.\n - Handle authentication-specific failure modes.\n - Coordinate with credential persistence layers where applicable.\n\n **Constraints:**\n\n - Mail adapters must treat returned credentials as opaque and\n provider-specific.\n - Mail adapters rely only on the declared credential type expected\n by the adapter.", "members": { "get_credentials": { "name": "get_credentials", "kind": "function", "path": "mail_intake.auth.base.MailIntakeAuthProvider.get_credentials", - "signature": "", + "signature": "get_credentials() -> T", "docstring": "Retrieve valid, provider-specific credentials.\n\nReturns:\n T:\n Credentials of type `T` suitable for immediate use by the\n corresponding mail adapter.\n\nRaises:\n Exception:\n An authentication-specific exception indicating that\n credentials could not be obtained or validated.\n\nNotes:\n **Guarantees:**\n\n - This method is synchronous by design.\n - Represents the sole entry point through which adapters obtain\n authentication material.\n - Implementations must either return credentials of the declared\n type `T` that are valid at the time of return or raise an exception." } } @@ -498,60 +407,18 @@ "signature": null, "docstring": "# Summary\n\nGoogle authentication provider implementation for Mail Intake.\n\nThis module provides a **Google OAuth–based authentication provider**\nused primarily for Gmail access.\n\nIt encapsulates all Google-specific authentication concerns, including:\n\n- Credential loading and persistence.\n- Token refresh handling.\n- Interactive OAuth flow initiation.\n- Coordination with a credential persistence layer.\n\nNo Google authentication details should leak outside this module.", "members": { - "os": { - "name": "os", - "kind": "alias", - "path": "mail_intake.auth.google.os", - "signature": "", - "docstring": null - }, - "Sequence": { - "name": "Sequence", - "kind": "alias", - "path": "mail_intake.auth.google.Sequence", - "signature": "", - "docstring": null - }, - "google": { - "name": "google", - "kind": "alias", - "path": "mail_intake.auth.google.google", - "signature": "", - "docstring": null - }, - "Request": { - "name": "Request", - "kind": "alias", - "path": "mail_intake.auth.google.Request", - "signature": "", - "docstring": null - }, - "Credentials": { - "name": "Credentials", - "kind": "alias", - "path": "mail_intake.auth.google.Credentials", - "signature": "", - "docstring": null - }, - "InstalledAppFlow": { - "name": "InstalledAppFlow", - "kind": "alias", - "path": "mail_intake.auth.google.InstalledAppFlow", - "signature": "", - "docstring": null - }, "MailIntakeAuthProvider": { "name": "MailIntakeAuthProvider", "kind": "class", "path": "mail_intake.auth.google.MailIntakeAuthProvider", - "signature": "", + "signature": null, "docstring": "Abstract base class for authentication providers.\n\nThis interface enforces a strict contract between authentication\nproviders and mail adapters by requiring providers to explicitly\ndeclare the type of credentials they return.\n\nNotes:\n **Responsibilities:**\n\n - Acquire credentials from an external provider.\n - Refresh or revalidate credentials as needed.\n - Handle authentication-specific failure modes.\n - Coordinate with credential persistence layers where applicable.\n\n **Constraints:**\n\n - Mail adapters must treat returned credentials as opaque and\n provider-specific.\n - Mail adapters rely only on the declared credential type expected\n by the adapter.", "members": { "get_credentials": { "name": "get_credentials", "kind": "function", "path": "mail_intake.auth.google.MailIntakeAuthProvider.get_credentials", - "signature": "", + "signature": "get_credentials()", "docstring": "Retrieve valid, provider-specific credentials.\n\nReturns:\n T:\n Credentials of type `T` suitable for immediate use by the\n corresponding mail adapter.\n\nRaises:\n Exception:\n An authentication-specific exception indicating that\n credentials could not be obtained or validated.\n\nNotes:\n **Guarantees:**\n\n - This method is synchronous by design.\n - Represents the sole entry point through which adapters obtain\n authentication material.\n - Implementations must either return credentials of the declared\n type `T` that are valid at the time of return or raise an exception." } } @@ -560,28 +427,28 @@ "name": "CredentialStore", "kind": "class", "path": "mail_intake.auth.google.CredentialStore", - "signature": "", + "signature": null, "docstring": "Abstract base class defining a generic persistence interface.\n\nUsed for authentication credentials across different backends.\n\nNotes:\n **Responsibilities:**\n\n - Provide persistent storage separating life-cycle management from\n storage mechanics.\n - Keep implementation focused only on persistence.\n\n **Constraints:**\n\n - The store is intentionally agnostic to:\n - The concrete credential type being stored.\n - The serialization format used to persist credentials.\n - The underlying storage backend or durability guarantees.", "members": { "load": { "name": "load", "kind": "function", "path": "mail_intake.auth.google.CredentialStore.load", - "signature": "", + "signature": "load()", "docstring": "Load previously persisted credentials.\n\nReturns:\n T | None:\n An instance of type `T` if credentials are available and\n loadable; otherwise `None`.\n\nNotes:\n **Guarantees:**\n\n - Implementations should return `None` when no credentials are\n present or when stored credentials cannot be successfully\n decoded or deserialized.\n - The store must not attempt to validate, refresh, or otherwise\n interpret the returned credentials." }, "save": { "name": "save", "kind": "function", "path": "mail_intake.auth.google.CredentialStore.save", - "signature": "", + "signature": "save(credentials: T)", "docstring": "Persist credentials to the underlying storage backend.\n\nArgs:\n credentials (T):\n The credential object to persist.\n\nNotes:\n **Lifecycle:**\n\n - This method is invoked when credentials are newly obtained or have been refreshed and are known to be valid at the time of persistence\n\n **Responsibilities:**\n\n - Ensuring durability appropriate to the deployment context\n - Applying encryption or access controls where required\n - Overwriting any previously stored credentials" }, "clear": { "name": "clear", "kind": "function", "path": "mail_intake.auth.google.CredentialStore.clear", - "signature": "", + "signature": "clear()", "docstring": "Remove any persisted credentials from the store.\n\nNotes:\n **Lifecycle:**\n\n - This method is called when credentials are known to be invalid, revoked, corrupted, or otherwise unusable\n - Must ensure that no stale authentication material remains accessible\n\n **Guarantees:**\n\n - Implementations should treat this operation as idempotent" } } @@ -590,14 +457,14 @@ "name": "MailIntakeAuthError", "kind": "class", "path": "mail_intake.auth.google.MailIntakeAuthError", - "signature": "", + "signature": null, "docstring": "Authentication and credential-related failures.\n\nNotes:\n **Lifecycle:**\n\n - Raised when authentication providers are unable to acquire,\n refresh, or persist valid credentials." }, "MailIntakeGoogleAuth": { "name": "MailIntakeGoogleAuth", "kind": "class", "path": "mail_intake.auth.google.MailIntakeGoogleAuth", - "signature": "", + "signature": "MailIntakeGoogleAuth(credentials_path: str, store: CredentialStore[Any], scopes: Sequence[str])", "docstring": "Google OAuth provider for Gmail access.\n\nThis provider implements the `MailIntakeAuthProvider` interface using\nGoogle's OAuth 2.0 flow and credential management libraries.\n\nNotes:\n **Responsibilities:**\n\n - Load cached credentials from a credential store when available.\n - Refresh expired credentials when possible.\n - Initiate an interactive OAuth flow only when required.\n - Persist refreshed or newly obtained credentials via the store.\n\n **Guarantees:**\n\n - This class is synchronous by design and maintains a minimal\n internal state.", "members": { "credentials_path": { @@ -625,17 +492,10 @@ "name": "get_credentials", "kind": "function", "path": "mail_intake.auth.google.MailIntakeGoogleAuth.get_credentials", - "signature": "", + "signature": "get_credentials() -> Any", "docstring": "Retrieve valid Google OAuth credentials.\n\nReturns:\n Credentials:\n A `google.oauth2.credentials.Credentials` instance suitable\n for use with Google API clients.\n\nRaises:\n MailIntakeAuthError:\n If credentials cannot be loaded, refreshed,\n or obtained via interactive authentication.\n\nNotes:\n **Lifecycle:**\n\n - Load cached credentials from the configured credential store.\n - Refresh expired credentials when possible.\n - Perform an interactive OAuth login as a fallback.\n - Persist valid credentials for future use." } } - }, - "Any": { - "name": "Any", - "kind": "alias", - "path": "mail_intake.auth.google.Any", - "signature": "", - "docstring": null } } } @@ -652,28 +512,28 @@ "name": "CredentialStore", "kind": "class", "path": "mail_intake.credentials.CredentialStore", - "signature": "", + "signature": null, "docstring": "Abstract base class defining a generic persistence interface.\n\nUsed for authentication credentials across different backends.\n\nNotes:\n **Responsibilities:**\n\n - Provide persistent storage separating life-cycle management from\n storage mechanics.\n - Keep implementation focused only on persistence.\n\n **Constraints:**\n\n - The store is intentionally agnostic to:\n - The concrete credential type being stored.\n - The serialization format used to persist credentials.\n - The underlying storage backend or durability guarantees.", "members": { "load": { "name": "load", "kind": "function", "path": "mail_intake.credentials.CredentialStore.load", - "signature": "", + "signature": "load()", "docstring": "Load previously persisted credentials.\n\nReturns:\n T | None:\n An instance of type `T` if credentials are available and\n loadable; otherwise `None`.\n\nNotes:\n **Guarantees:**\n\n - Implementations should return `None` when no credentials are\n present or when stored credentials cannot be successfully\n decoded or deserialized.\n - The store must not attempt to validate, refresh, or otherwise\n interpret the returned credentials." }, "save": { "name": "save", "kind": "function", "path": "mail_intake.credentials.CredentialStore.save", - "signature": "", + "signature": "save(credentials: T)", "docstring": "Persist credentials to the underlying storage backend.\n\nArgs:\n credentials (T):\n The credential object to persist.\n\nNotes:\n **Lifecycle:**\n\n - This method is invoked when credentials are newly obtained or have been refreshed and are known to be valid at the time of persistence\n\n **Responsibilities:**\n\n - Ensuring durability appropriate to the deployment context\n - Applying encryption or access controls where required\n - Overwriting any previously stored credentials" }, "clear": { "name": "clear", "kind": "function", "path": "mail_intake.credentials.CredentialStore.clear", - "signature": "", + "signature": "clear()", "docstring": "Remove any persisted credentials from the store.\n\nNotes:\n **Lifecycle:**\n\n - This method is called when credentials are known to be invalid, revoked, corrupted, or otherwise unusable\n - Must ensure that no stale authentication material remains accessible\n\n **Guarantees:**\n\n - Implementations should treat this operation as idempotent" } } @@ -682,35 +542,35 @@ "name": "PickleCredentialStore", "kind": "class", "path": "mail_intake.credentials.PickleCredentialStore", - "signature": "", + "signature": "PickleCredentialStore(path: str)", "docstring": "Filesystem-backed credential store using pickle serialization.\n\nThis store persists credentials as a pickled object on the local\nfilesystem. It is a simple implementation intended primarily for\ndevelopment, testing, and single-process execution contexts.\n\nNotes:\n **Guarantees:**\n\n - Stores credentials on the local filesystem.\n - Uses `pickle` for serialization and deserialization.\n - Does not provide encryption, locking, or concurrency guarantees.\n\n **Constraints:**\n\n - Credential lifecycle management, validation, and refresh logic are\n explicitly out of scope for this class.", "members": { "path": { "name": "path", "kind": "attribute", "path": "mail_intake.credentials.PickleCredentialStore.path", - "signature": "", + "signature": null, "docstring": null }, "load": { "name": "load", "kind": "function", "path": "mail_intake.credentials.PickleCredentialStore.load", - "signature": "", + "signature": "load()", "docstring": "Load credentials from the local filesystem.\n\nReturns:\n T | None:\n An instance of type `T` if credentials are present and\n successfully deserialized; otherwise `None`.\n\nNotes:\n **Guarantees:**\n\n - If the credential file does not exist or cannot be successfully\n deserialized, this method returns `None`.\n - The store does not attempt to validate or interpret the\n returned credentials." }, "save": { "name": "save", "kind": "function", "path": "mail_intake.credentials.PickleCredentialStore.save", - "signature": "", + "signature": "save(credentials: T)", "docstring": "Persist credentials to the local filesystem.\n\nArgs:\n credentials (T):\n The credential object to persist.\n\nNotes:\n **Responsibilities:**\n\n - Any previously stored credentials at the configured path are overwritten" }, "clear": { "name": "clear", "kind": "function", "path": "mail_intake.credentials.PickleCredentialStore.clear", - "signature": "", + "signature": "clear()", "docstring": "Remove persisted credentials from the local filesystem.\n\nNotes:\n **Lifecycle:**\n\n - This method deletes the credential file if it exists and should be treated as an idempotent operation" } } @@ -719,63 +579,63 @@ "name": "RedisCredentialStore", "kind": "class", "path": "mail_intake.credentials.RedisCredentialStore", - "signature": "", + "signature": "RedisCredentialStore(redis_client: Any, key: str, serialize: Callable[[T], bytes], deserialize: Callable[[bytes], T], ttl_seconds: int | None = None)", "docstring": "Redis-backed implementation of `CredentialStore`.\n\nThis store persists credentials in Redis and is suitable for\ndistributed and horizontally scaled deployments where credentials\nmust be shared across multiple processes or nodes.\n\nNotes:\n **Responsibilities:**\n\n - This class is responsible only for persistence and retrieval.\n - It does not interpret, validate, refresh, or otherwise manage the\n lifecycle of the credentials being stored.\n\n **Guarantees:**\n\n - The store is intentionally generic and delegates all serialization\n concerns to caller-provided functions.\n - This avoids unsafe mechanisms such as `pickle` and allows\n credential formats to be explicitly controlled and audited.", "members": { "redis": { "name": "redis", "kind": "attribute", "path": "mail_intake.credentials.RedisCredentialStore.redis", - "signature": "", + "signature": null, "docstring": null }, "key": { "name": "key", "kind": "attribute", "path": "mail_intake.credentials.RedisCredentialStore.key", - "signature": "", + "signature": null, "docstring": null }, "serialize": { "name": "serialize", "kind": "attribute", "path": "mail_intake.credentials.RedisCredentialStore.serialize", - "signature": "", + "signature": null, "docstring": null }, "deserialize": { "name": "deserialize", "kind": "attribute", "path": "mail_intake.credentials.RedisCredentialStore.deserialize", - "signature": "", + "signature": null, "docstring": null }, "ttl_seconds": { "name": "ttl_seconds", "kind": "attribute", "path": "mail_intake.credentials.RedisCredentialStore.ttl_seconds", - "signature": "", + "signature": null, "docstring": null }, "load": { "name": "load", "kind": "function", "path": "mail_intake.credentials.RedisCredentialStore.load", - "signature": "", + "signature": "load()", "docstring": "Load credentials from Redis.\n\nReturns:\n T | None:\n An instance of type `T` if credentials are present and\n successfully deserialized; otherwise `None`.\n\nNotes:\n **Guarantees:**\n\n - If no value exists for the configured key, or if the stored\n payload cannot be successfully deserialized, this method\n returns `None`.\n - The store does not attempt to validate the returned\n credentials or determine whether they are expired or\n otherwise usable." }, "save": { "name": "save", "kind": "function", "path": "mail_intake.credentials.RedisCredentialStore.save", - "signature": "", + "signature": "save(credentials: T)", "docstring": "Persist credentials to Redis.\n\nArgs:\n credentials (T):\n The credential object to persist.\n\nNotes:\n **Responsibilities:**\n\n - Any previously stored credentials under the same key are overwritten\n - If a TTL is configured, the credentials will expire automatically after the specified duration" }, "clear": { "name": "clear", "kind": "function", "path": "mail_intake.credentials.RedisCredentialStore.clear", - "signature": "", + "signature": "clear()", "docstring": "Remove stored credentials from Redis.\n\nNotes:\n **Lifecycle:**\n\n - This operation deletes the configured Redis key if it exists\n - Implementations should treat this method as idempotent" } } @@ -787,46 +647,32 @@ "signature": null, "docstring": "# Summary\n\nLocal filesystem–based credential persistence for Mail Intake.\n\nThis module provides a file-backed implementation of the\n`CredentialStore` abstraction using Python's `pickle` module.\n\nThe `pickle`-based credential store is intended for local development,\nsingle-node deployments, and controlled environments where credentials\ndo not need to be shared across processes or machines.\n\nDue to the security and portability risks associated with `pickle`-based\nserialization, this implementation is not suitable for distributed or\nuntrusted environments.", "members": { - "pickle": { - "name": "pickle", - "kind": "alias", - "path": "mail_intake.credentials.pickle.pickle", - "signature": "", - "docstring": null - }, - "TypeVar": { - "name": "TypeVar", - "kind": "alias", - "path": "mail_intake.credentials.pickle.TypeVar", - "signature": "", - "docstring": null - }, "CredentialStore": { "name": "CredentialStore", "kind": "class", "path": "mail_intake.credentials.pickle.CredentialStore", - "signature": "", + "signature": null, "docstring": "Abstract base class defining a generic persistence interface.\n\nUsed for authentication credentials across different backends.\n\nNotes:\n **Responsibilities:**\n\n - Provide persistent storage separating life-cycle management from\n storage mechanics.\n - Keep implementation focused only on persistence.\n\n **Constraints:**\n\n - The store is intentionally agnostic to:\n - The concrete credential type being stored.\n - The serialization format used to persist credentials.\n - The underlying storage backend or durability guarantees.", "members": { "load": { "name": "load", "kind": "function", "path": "mail_intake.credentials.pickle.CredentialStore.load", - "signature": "", + "signature": "load()", "docstring": "Load previously persisted credentials.\n\nReturns:\n T | None:\n An instance of type `T` if credentials are available and\n loadable; otherwise `None`.\n\nNotes:\n **Guarantees:**\n\n - Implementations should return `None` when no credentials are\n present or when stored credentials cannot be successfully\n decoded or deserialized.\n - The store must not attempt to validate, refresh, or otherwise\n interpret the returned credentials." }, "save": { "name": "save", "kind": "function", "path": "mail_intake.credentials.pickle.CredentialStore.save", - "signature": "", + "signature": "save(credentials: T)", "docstring": "Persist credentials to the underlying storage backend.\n\nArgs:\n credentials (T):\n The credential object to persist.\n\nNotes:\n **Lifecycle:**\n\n - This method is invoked when credentials are newly obtained or have been refreshed and are known to be valid at the time of persistence\n\n **Responsibilities:**\n\n - Ensuring durability appropriate to the deployment context\n - Applying encryption or access controls where required\n - Overwriting any previously stored credentials" }, "clear": { "name": "clear", "kind": "function", "path": "mail_intake.credentials.pickle.CredentialStore.clear", - "signature": "", + "signature": "clear()", "docstring": "Remove any persisted credentials from the store.\n\nNotes:\n **Lifecycle:**\n\n - This method is called when credentials are known to be invalid, revoked, corrupted, or otherwise unusable\n - Must ensure that no stale authentication material remains accessible\n\n **Guarantees:**\n\n - Implementations should treat this operation as idempotent" } } @@ -842,7 +688,7 @@ "name": "PickleCredentialStore", "kind": "class", "path": "mail_intake.credentials.pickle.PickleCredentialStore", - "signature": "", + "signature": "PickleCredentialStore(path: str)", "docstring": "Filesystem-backed credential store using pickle serialization.\n\nThis store persists credentials as a pickled object on the local\nfilesystem. It is a simple implementation intended primarily for\ndevelopment, testing, and single-process execution contexts.\n\nNotes:\n **Guarantees:**\n\n - Stores credentials on the local filesystem.\n - Uses `pickle` for serialization and deserialization.\n - Does not provide encryption, locking, or concurrency guarantees.\n\n **Constraints:**\n\n - Credential lifecycle management, validation, and refresh logic are\n explicitly out of scope for this class.", "members": { "path": { @@ -856,21 +702,21 @@ "name": "load", "kind": "function", "path": "mail_intake.credentials.pickle.PickleCredentialStore.load", - "signature": "", + "signature": "load() -> T | None", "docstring": "Load credentials from the local filesystem.\n\nReturns:\n T | None:\n An instance of type `T` if credentials are present and\n successfully deserialized; otherwise `None`.\n\nNotes:\n **Guarantees:**\n\n - If the credential file does not exist or cannot be successfully\n deserialized, this method returns `None`.\n - The store does not attempt to validate or interpret the\n returned credentials." }, "save": { "name": "save", "kind": "function", "path": "mail_intake.credentials.pickle.PickleCredentialStore.save", - "signature": "", + "signature": "save(credentials: T) -> None", "docstring": "Persist credentials to the local filesystem.\n\nArgs:\n credentials (T):\n The credential object to persist.\n\nNotes:\n **Responsibilities:**\n\n - Any previously stored credentials at the configured path are overwritten" }, "clear": { "name": "clear", "kind": "function", "path": "mail_intake.credentials.pickle.PickleCredentialStore.clear", - "signature": "", + "signature": "clear() -> None", "docstring": "Remove persisted credentials from the local filesystem.\n\nNotes:\n **Lifecycle:**\n\n - This method deletes the credential file if it exists and should be treated as an idempotent operation" } } @@ -884,53 +730,32 @@ "signature": null, "docstring": "# Summary\n\nRedis-backed credential persistence for Mail Intake.\n\nThis module provides a Redis-based implementation of the\n`CredentialStore` abstraction, enabling credential persistence\nacross distributed and horizontally scaled deployments.\n\nThe Redis credential store is designed for environments where\nauthentication credentials must be shared safely across multiple\nprocesses, containers, or nodes, such as container orchestration\nplatforms and microservice architectures.\n\nKey characteristics:\n\n- Distributed-safe, shared storage using Redis.\n- Explicit, caller-defined serialization and deserialization.\n- No reliance on unsafe mechanisms such as `pickle`.\n- Optional time-to-live (TTL) support for automatic credential expiry.\n\nThis module is responsible solely for persistence concerns.\nCredential validation, refresh, rotation, and acquisition remain the\nresponsibility of authentication provider implementations.", "members": { - "Callable": { - "name": "Callable", - "kind": "alias", - "path": "mail_intake.credentials.redis.Callable", - "signature": "", - "docstring": null - }, - "Any": { - "name": "Any", - "kind": "alias", - "path": "mail_intake.credentials.redis.Any", - "signature": "", - "docstring": null - }, - "TypeVar": { - "name": "TypeVar", - "kind": "alias", - "path": "mail_intake.credentials.redis.TypeVar", - "signature": "", - "docstring": null - }, "CredentialStore": { "name": "CredentialStore", "kind": "class", "path": "mail_intake.credentials.redis.CredentialStore", - "signature": "", + "signature": null, "docstring": "Abstract base class defining a generic persistence interface.\n\nUsed for authentication credentials across different backends.\n\nNotes:\n **Responsibilities:**\n\n - Provide persistent storage separating life-cycle management from\n storage mechanics.\n - Keep implementation focused only on persistence.\n\n **Constraints:**\n\n - The store is intentionally agnostic to:\n - The concrete credential type being stored.\n - The serialization format used to persist credentials.\n - The underlying storage backend or durability guarantees.", "members": { "load": { "name": "load", "kind": "function", "path": "mail_intake.credentials.redis.CredentialStore.load", - "signature": "", + "signature": "load()", "docstring": "Load previously persisted credentials.\n\nReturns:\n T | None:\n An instance of type `T` if credentials are available and\n loadable; otherwise `None`.\n\nNotes:\n **Guarantees:**\n\n - Implementations should return `None` when no credentials are\n present or when stored credentials cannot be successfully\n decoded or deserialized.\n - The store must not attempt to validate, refresh, or otherwise\n interpret the returned credentials." }, "save": { "name": "save", "kind": "function", "path": "mail_intake.credentials.redis.CredentialStore.save", - "signature": "", + "signature": "save(credentials: T)", "docstring": "Persist credentials to the underlying storage backend.\n\nArgs:\n credentials (T):\n The credential object to persist.\n\nNotes:\n **Lifecycle:**\n\n - This method is invoked when credentials are newly obtained or have been refreshed and are known to be valid at the time of persistence\n\n **Responsibilities:**\n\n - Ensuring durability appropriate to the deployment context\n - Applying encryption or access controls where required\n - Overwriting any previously stored credentials" }, "clear": { "name": "clear", "kind": "function", "path": "mail_intake.credentials.redis.CredentialStore.clear", - "signature": "", + "signature": "clear()", "docstring": "Remove any persisted credentials from the store.\n\nNotes:\n **Lifecycle:**\n\n - This method is called when credentials are known to be invalid, revoked, corrupted, or otherwise unusable\n - Must ensure that no stale authentication material remains accessible\n\n **Guarantees:**\n\n - Implementations should treat this operation as idempotent" } } @@ -946,7 +771,7 @@ "name": "RedisCredentialStore", "kind": "class", "path": "mail_intake.credentials.redis.RedisCredentialStore", - "signature": "", + "signature": "RedisCredentialStore(redis_client: Any, key: str, serialize: Callable[[T], bytes], deserialize: Callable[[bytes], T], ttl_seconds: int | None = None)", "docstring": "Redis-backed implementation of `CredentialStore`.\n\nThis store persists credentials in Redis and is suitable for\ndistributed and horizontally scaled deployments where credentials\nmust be shared across multiple processes or nodes.\n\nNotes:\n **Responsibilities:**\n\n - This class is responsible only for persistence and retrieval.\n - It does not interpret, validate, refresh, or otherwise manage the\n lifecycle of the credentials being stored.\n\n **Guarantees:**\n\n - The store is intentionally generic and delegates all serialization\n concerns to caller-provided functions.\n - This avoids unsafe mechanisms such as `pickle` and allows\n credential formats to be explicitly controlled and audited.", "members": { "redis": { @@ -988,21 +813,21 @@ "name": "load", "kind": "function", "path": "mail_intake.credentials.redis.RedisCredentialStore.load", - "signature": "", + "signature": "load() -> T | None", "docstring": "Load credentials from Redis.\n\nReturns:\n T | None:\n An instance of type `T` if credentials are present and\n successfully deserialized; otherwise `None`.\n\nNotes:\n **Guarantees:**\n\n - If no value exists for the configured key, or if the stored\n payload cannot be successfully deserialized, this method\n returns `None`.\n - The store does not attempt to validate the returned\n credentials or determine whether they are expired or\n otherwise usable." }, "save": { "name": "save", "kind": "function", "path": "mail_intake.credentials.redis.RedisCredentialStore.save", - "signature": "", + "signature": "save(credentials: T) -> None", "docstring": "Persist credentials to Redis.\n\nArgs:\n credentials (T):\n The credential object to persist.\n\nNotes:\n **Responsibilities:**\n\n - Any previously stored credentials under the same key are overwritten\n - If a TTL is configured, the credentials will expire automatically after the specified duration" }, "clear": { "name": "clear", "kind": "function", "path": "mail_intake.credentials.redis.RedisCredentialStore.clear", - "signature": "", + "signature": "clear() -> None", "docstring": "Remove stored credentials from Redis.\n\nNotes:\n **Lifecycle:**\n\n - This operation deletes the configured Redis key if it exists\n - Implementations should treat this method as idempotent" } } @@ -1016,34 +841,6 @@ "signature": null, "docstring": "# Summary\n\nCredential persistence abstractions for Mail Intake.\n\nThis module defines the generic persistence contract used to store and\nretrieve authentication credentials across Mail Intake components.\n\nThe `CredentialStore` abstraction establishes a strict separation\nbetween credential *lifecycle management* and credential *storage*.\nAuthentication providers are responsible for acquiring, validating,\nrefreshing, and revoking credentials, while concrete store\nimplementations are responsible solely for persistence concerns.\n\nBy remaining agnostic to credential structure, serialization format,\nand storage backend, this module enables multiple persistence\nstrategiesβ€”such as local files, in-memory caches, distributed stores,\nor secrets managersβ€”without coupling authentication logic to any\nspecific storage mechanism.", "members": { - "ABC": { - "name": "ABC", - "kind": "alias", - "path": "mail_intake.credentials.store.ABC", - "signature": "", - "docstring": null - }, - "abstractmethod": { - "name": "abstractmethod", - "kind": "alias", - "path": "mail_intake.credentials.store.abstractmethod", - "signature": "", - "docstring": null - }, - "Generic": { - "name": "Generic", - "kind": "alias", - "path": "mail_intake.credentials.store.Generic", - "signature": "", - "docstring": null - }, - "TypeVar": { - "name": "TypeVar", - "kind": "alias", - "path": "mail_intake.credentials.store.TypeVar", - "signature": "", - "docstring": null - }, "T": { "name": "T", "kind": "attribute", @@ -1055,28 +852,28 @@ "name": "CredentialStore", "kind": "class", "path": "mail_intake.credentials.store.CredentialStore", - "signature": "", + "signature": null, "docstring": "Abstract base class defining a generic persistence interface.\n\nUsed for authentication credentials across different backends.\n\nNotes:\n **Responsibilities:**\n\n - Provide persistent storage separating life-cycle management from\n storage mechanics.\n - Keep implementation focused only on persistence.\n\n **Constraints:**\n\n - The store is intentionally agnostic to:\n - The concrete credential type being stored.\n - The serialization format used to persist credentials.\n - The underlying storage backend or durability guarantees.", "members": { "load": { "name": "load", "kind": "function", "path": "mail_intake.credentials.store.CredentialStore.load", - "signature": "", + "signature": "load() -> T | None", "docstring": "Load previously persisted credentials.\n\nReturns:\n T | None:\n An instance of type `T` if credentials are available and\n loadable; otherwise `None`.\n\nNotes:\n **Guarantees:**\n\n - Implementations should return `None` when no credentials are\n present or when stored credentials cannot be successfully\n decoded or deserialized.\n - The store must not attempt to validate, refresh, or otherwise\n interpret the returned credentials." }, "save": { "name": "save", "kind": "function", "path": "mail_intake.credentials.store.CredentialStore.save", - "signature": "", + "signature": "save(credentials: T) -> None", "docstring": "Persist credentials to the underlying storage backend.\n\nArgs:\n credentials (T):\n The credential object to persist.\n\nNotes:\n **Lifecycle:**\n\n - This method is invoked when credentials are newly obtained or have been refreshed and are known to be valid at the time of persistence\n\n **Responsibilities:**\n\n - Ensuring durability appropriate to the deployment context\n - Applying encryption or access controls where required\n - Overwriting any previously stored credentials" }, "clear": { "name": "clear", "kind": "function", "path": "mail_intake.credentials.store.CredentialStore.clear", - "signature": "", + "signature": "clear() -> None", "docstring": "Remove any persisted credentials from the store.\n\nNotes:\n **Lifecycle:**\n\n - This method is called when credentials are known to be invalid, revoked, corrupted, or otherwise unusable\n - Must ensure that no stale authentication material remains accessible\n\n **Guarantees:**\n\n - Implementations should treat this operation as idempotent" } } @@ -1096,21 +893,21 @@ "name": "MailIntakeReader", "kind": "class", "path": "mail_intake.ingestion.MailIntakeReader", - "signature": "", + "signature": "MailIntakeReader(adapter: MailIntakeAdapter)", "docstring": "High-level read-only ingestion interface.\n\nNotes:\n **Responsibilities:**\n\n - This class is the primary entry point for consumers of the\n Mail Intake library.\n - It orchestrates the full ingestion pipeline:\n - Querying the adapter for message references.\n - Fetching raw provider messages.\n - Parsing and normalizing message data.\n - Constructing domain models.\n\n **Constraints:**\n\n - This class is intentionally: Provider-agnostic, stateless beyond\n iteration scope, read-only.", "members": { "iter_messages": { "name": "iter_messages", "kind": "function", "path": "mail_intake.ingestion.MailIntakeReader.iter_messages", - "signature": "", + "signature": "iter_messages(query: str)", "docstring": "Iterate over parsed messages matching a provider query.\n\nArgs:\n query (str):\n Provider-specific query string used to filter messages.\n\nYields:\n MailIntakeMessage:\n Fully parsed and normalized `MailIntakeMessage` instances.\n\nRaises:\n MailIntakeParsingError:\n If a message cannot be parsed." }, "iter_threads": { "name": "iter_threads", "kind": "function", "path": "mail_intake.ingestion.MailIntakeReader.iter_threads", - "signature": "", + "signature": "iter_threads(query: str)", "docstring": "Iterate over threads constructed from messages matching a query.\n\nArgs:\n query (str):\n Provider-specific query string used to filter messages.\n\nReturns:\n Iterator[MailIntakeThread]:\n An iterator over `MailIntakeThread` instances.\n\nRaises:\n `MailIntakeParsingError`:\n If a message cannot be parsed.\n\nNotes:\n **Guarantees:**\n\n - Messages are grouped by `thread_id` and yielded as complete\n thread objects containing all associated messages." } } @@ -1122,53 +919,32 @@ "signature": null, "docstring": "# Summary\n\nHigh-level mail ingestion orchestration for Mail Intake.\n\nThis module provides the primary, provider-agnostic entry point for\nreading and processing mail data.\n\nIt coordinates:\n\n- Mail adapter access.\n- Message and thread iteration.\n- Header and body parsing.\n- Normalization and model construction.\n\nNo provider-specific logic or API semantics are permitted in this layer.", "members": { - "Iterator": { - "name": "Iterator", - "kind": "alias", - "path": "mail_intake.ingestion.reader.Iterator", - "signature": "", - "docstring": null - }, - "datetime": { - "name": "datetime", - "kind": "alias", - "path": "mail_intake.ingestion.reader.datetime", - "signature": "", - "docstring": null - }, - "Any": { - "name": "Any", - "kind": "alias", - "path": "mail_intake.ingestion.reader.Any", - "signature": "", - "docstring": null - }, "MailIntakeAdapter": { "name": "MailIntakeAdapter", "kind": "class", "path": "mail_intake.ingestion.reader.MailIntakeAdapter", - "signature": "", + "signature": null, "docstring": "Base adapter interface for mail providers.\n\nNotes:\n **Guarantees:**\n\n - Discover messages matching a query.\n - Retrieve full message payloads.\n - Retrieve full thread payloads.\n\n **Lifecycle:**\n\n - Adapters are intentionally read-only and must not mutate provider state.", "members": { "iter_message_refs": { "name": "iter_message_refs", "kind": "function", "path": "mail_intake.ingestion.reader.MailIntakeAdapter.iter_message_refs", - "signature": "", + "signature": "iter_message_refs(query: str)", "docstring": "Iterate over lightweight message references matching a query.\n\nArgs:\n query (str):\n Provider-specific query string used to filter messages.\n\nReturns:\n Iterator[dict[str, str]]:\n An iterator over lightweight message reference dictionaries.\n\nYields:\n dict[str, str]:\n Dictionaries containing message and thread identifiers.\n\nNotes:\n **Guarantees:**\n\n - Implementations must yield dictionaries containing at least\n `message_id` and `thread_id`.\n\nExample:\n Typical yield:\n\n ```python\n {\n \"message_id\": \"...\",\n \"thread_id\": \"...\"\n }\n ```" }, "fetch_message": { "name": "fetch_message", "kind": "function", "path": "mail_intake.ingestion.reader.MailIntakeAdapter.fetch_message", - "signature": "", + "signature": "fetch_message(message_id: str)", "docstring": "Fetch a full raw message by message identifier.\n\nArgs:\n message_id (str):\n Provider-specific message identifier.\n\nReturns:\n dict[str, Any]:\n Provider-native message payload (e.g., Gmail message JSON structure)." }, "fetch_thread": { "name": "fetch_thread", "kind": "function", "path": "mail_intake.ingestion.reader.MailIntakeAdapter.fetch_thread", - "signature": "", + "signature": "fetch_thread(thread_id: str)", "docstring": "Fetch a full raw thread by thread identifier.\n\nArgs:\n thread_id (str):\n Provider-specific thread identifier.\n\nReturns:\n dict[str, Any]:\n Provider-native thread payload." } } @@ -1177,77 +953,77 @@ "name": "MailIntakeParsingError", "kind": "class", "path": "mail_intake.ingestion.reader.MailIntakeParsingError", - "signature": "", + "signature": null, "docstring": "Errors encountered while parsing message content.\n\nNotes:\n **Lifecycle:**\n\n - Raised when raw provider payloads cannot be interpreted or\n normalized into internal domain models." }, "MailIntakeMessage": { "name": "MailIntakeMessage", "kind": "class", "path": "mail_intake.ingestion.reader.MailIntakeMessage", - "signature": "", + "signature": "MailIntakeMessage(message_id: str, thread_id: str, timestamp: datetime, from_email: str, from_name: str | None, subject: str, body_text: str, snippet: str, raw_headers: dict[str, str])", "docstring": "Canonical internal representation of a single email message.\n\nNotes:\n **Guarantees:**\n\n - This model represents a fully parsed and normalized email message.\n - It is intentionally provider-agnostic and suitable for\n persistence, indexing, and downstream processing.\n\n **Constraints:**\n\n - No provider-specific identifiers, payloads, or API semantics\n should appear in this model.", "members": { "message_id": { "name": "message_id", "kind": "attribute", "path": "mail_intake.ingestion.reader.MailIntakeMessage.message_id", - "signature": "", + "signature": null, "docstring": "Provider-specific message identifier." }, "thread_id": { "name": "thread_id", "kind": "attribute", "path": "mail_intake.ingestion.reader.MailIntakeMessage.thread_id", - "signature": "", + "signature": null, "docstring": "Provider-specific thread identifier to which this message belongs." }, "timestamp": { "name": "timestamp", "kind": "attribute", "path": "mail_intake.ingestion.reader.MailIntakeMessage.timestamp", - "signature": "", + "signature": null, "docstring": "Message timestamp as a timezone-naive UTC datetime." }, "from_email": { "name": "from_email", "kind": "attribute", "path": "mail_intake.ingestion.reader.MailIntakeMessage.from_email", - "signature": "", + "signature": null, "docstring": "Sender email address." }, "from_name": { "name": "from_name", "kind": "attribute", "path": "mail_intake.ingestion.reader.MailIntakeMessage.from_name", - "signature": "", + "signature": null, "docstring": "Optional human-readable sender name." }, "subject": { "name": "subject", "kind": "attribute", "path": "mail_intake.ingestion.reader.MailIntakeMessage.subject", - "signature": "", + "signature": null, "docstring": "Raw subject line of the message." }, "body_text": { "name": "body_text", "kind": "attribute", "path": "mail_intake.ingestion.reader.MailIntakeMessage.body_text", - "signature": "", + "signature": null, "docstring": "Extracted plain-text body content of the message." }, "snippet": { "name": "snippet", "kind": "attribute", "path": "mail_intake.ingestion.reader.MailIntakeMessage.snippet", - "signature": "", + "signature": null, "docstring": "Short provider-supplied preview snippet of the message." }, "raw_headers": { "name": "raw_headers", "kind": "attribute", "path": "mail_intake.ingestion.reader.MailIntakeMessage.raw_headers", - "signature": "", + "signature": null, "docstring": "Normalized mapping of message headers (header name β†’ value)." } } @@ -1256,49 +1032,49 @@ "name": "MailIntakeThread", "kind": "class", "path": "mail_intake.ingestion.reader.MailIntakeThread", - "signature": "", + "signature": "MailIntakeThread(thread_id: str, normalized_subject: str, participants: set[str] = ..., messages: list[MailIntakeMessage] = ..., last_activity_at: datetime | None = ...)", "docstring": "Canonical internal representation of an email thread.\n\nNotes:\n **Guarantees:**\n\n - A thread groups multiple related messages under a single subject\n and participant set.\n - It is designed to support reasoning over conversational context\n such as job applications, interviews, follow-ups, and ongoing discussions.\n - This model is provider-agnostic and safe to persist.", "members": { "thread_id": { "name": "thread_id", "kind": "attribute", "path": "mail_intake.ingestion.reader.MailIntakeThread.thread_id", - "signature": "", + "signature": null, "docstring": "Provider-specific thread identifier." }, "normalized_subject": { "name": "normalized_subject", "kind": "attribute", "path": "mail_intake.ingestion.reader.MailIntakeThread.normalized_subject", - "signature": "", + "signature": null, "docstring": "Normalized subject line used to group related messages." }, "participants": { "name": "participants", "kind": "attribute", "path": "mail_intake.ingestion.reader.MailIntakeThread.participants", - "signature": "", + "signature": null, "docstring": "Set of unique participant email addresses observed in the thread." }, "messages": { "name": "messages", "kind": "attribute", "path": "mail_intake.ingestion.reader.MailIntakeThread.messages", - "signature": "", + "signature": null, "docstring": "Ordered list of messages belonging to this thread." }, "last_activity_at": { "name": "last_activity_at", "kind": "attribute", "path": "mail_intake.ingestion.reader.MailIntakeThread.last_activity_at", - "signature": "", + "signature": null, "docstring": "Timestamp of the most recent message in the thread." }, "add_message": { "name": "add_message", "kind": "function", "path": "mail_intake.ingestion.reader.MailIntakeThread.add_message", - "signature": "", + "signature": "add_message(message: MailIntakeMessage)", "docstring": "Add a message to the thread and update derived fields.\n\nArgs:\n message (MailIntakeMessage):\n Parsed mail message to add to the thread.\n\nNotes:\n **Responsibilities:**\n\n - Appends the message to the thread.\n - Tracks unique participants.\n - Updates the last activity timestamp." } } @@ -1307,49 +1083,49 @@ "name": "extract_body", "kind": "function", "path": "mail_intake.ingestion.reader.extract_body", - "signature": "", + "signature": "extract_body(payload: dict[str, Any])", "docstring": "Extract the best-effort message body from a Gmail payload.\n\nPriority:\n\n1. `text/plain`\n2. `text/html` (stripped to text)\n3. Single-part body\n4. Empty string (if nothing usable found)\n\nArgs:\n payload (dict[str, Any]):\n Provider-native message payload dictionary.\n\nReturns:\n str:\n Extracted plain-text message body." }, "extract_sender": { "name": "extract_sender", "kind": "function", "path": "mail_intake.ingestion.reader.extract_sender", - "signature": "", + "signature": "extract_sender(headers: dict[str, str])", "docstring": "Extract sender email and optional display name from headers.\n\nArgs:\n headers (dict[str, str]):\n Normalized header dictionary as returned by `parse_headers()`.\n\nReturns:\n tuple[str, str | None]:\n A tuple `(email, name)` where `email` is the sender email address\n and `name` is the display name, or `None` if unavailable.\n\nNotes:\n **Responsibilities:**\n\n - This function parses the `From` header and attempts to extract\n sender email address and optional human-readable display name.\n\nExample:\n Typical values:\n\n - `\"John Doe \"` -> `(\"john@example.com\", \"John Doe\")`\n - `\"john@example.com\"` -> `(\"john@example.com\", None)`" }, "parse_headers": { "name": "parse_headers", "kind": "function", "path": "mail_intake.ingestion.reader.parse_headers", - "signature": "", + "signature": "parse_headers(raw_headers: list[dict[str, str]])", "docstring": "Convert a list of Gmail-style headers into a normalized dict.\n\nArgs:\n raw_headers (list[dict[str, str]]):\n List of header dictionaries, each containing `name` and `value` keys.\n\nReturns:\n dict[str, str]:\n Dictionary mapping lowercase header names to stripped values.\n\nNotes:\n **Guarantees:**\n\n - Provider payloads (such as Gmail) typically represent headers as a\n list of name/value mappings.\n - This function normalizes them into a case-insensitive dictionary\n keyed by lowercase header names.\n\nExample:\n Typical usage:\n\n ```python\n Input:\n [\n {\"name\": \"From\", \"value\": \"John Doe \"},\n {\"name\": \"Subject\", \"value\": \"Re: Interview Update\"},\n ]\n\n Output:\n {\n \"from\": \"John Doe \",\n \"subject\": \"Re: Interview Update\",\n }\n ```" }, "normalize_subject": { "name": "normalize_subject", "kind": "function", "path": "mail_intake.ingestion.reader.normalize_subject", - "signature": "", + "signature": "normalize_subject(subject: str)", "docstring": "Normalize an email subject for thread-level comparison.\n\nArgs:\n subject (str):\n Raw subject line from a message header.\n\nReturns:\n str:\n Normalized subject string suitable for thread grouping.\n\nNotes:\n **Responsibilities:**\n\n - Strips common prefixes such as `Re:`, `Fwd:`, and `FW:`.\n - Repeats prefix stripping to handle stacked prefixes.\n - Collapses excessive whitespace.\n - Preserves original casing (no lowercasing).\n\n **Guarantees:**\n\n - This function is intentionally conservative and avoids aggressive\n transformations that could alter the semantic meaning of the subject." }, "MailIntakeReader": { "name": "MailIntakeReader", "kind": "class", "path": "mail_intake.ingestion.reader.MailIntakeReader", - "signature": "", + "signature": "MailIntakeReader(adapter: MailIntakeAdapter)", "docstring": "High-level read-only ingestion interface.\n\nNotes:\n **Responsibilities:**\n\n - This class is the primary entry point for consumers of the\n Mail Intake library.\n - It orchestrates the full ingestion pipeline:\n - Querying the adapter for message references.\n - Fetching raw provider messages.\n - Parsing and normalizing message data.\n - Constructing domain models.\n\n **Constraints:**\n\n - This class is intentionally: Provider-agnostic, stateless beyond\n iteration scope, read-only.", "members": { "iter_messages": { "name": "iter_messages", "kind": "function", "path": "mail_intake.ingestion.reader.MailIntakeReader.iter_messages", - "signature": "", + "signature": "iter_messages(query: str) -> Iterator[MailIntakeMessage]", "docstring": "Iterate over parsed messages matching a provider query.\n\nArgs:\n query (str):\n Provider-specific query string used to filter messages.\n\nYields:\n MailIntakeMessage:\n Fully parsed and normalized `MailIntakeMessage` instances.\n\nRaises:\n MailIntakeParsingError:\n If a message cannot be parsed." }, "iter_threads": { "name": "iter_threads", "kind": "function", "path": "mail_intake.ingestion.reader.MailIntakeReader.iter_threads", - "signature": "", + "signature": "iter_threads(query: str) -> Iterator[MailIntakeThread]", "docstring": "Iterate over threads constructed from messages matching a query.\n\nArgs:\n query (str):\n Provider-specific query string used to filter messages.\n\nReturns:\n Iterator[MailIntakeThread]:\n An iterator over `MailIntakeThread` instances.\n\nRaises:\n `MailIntakeParsingError`:\n If a message cannot be parsed.\n\nNotes:\n **Guarantees:**\n\n - Messages are grouped by `thread_id` and yielded as complete\n thread objects containing all associated messages." } } @@ -1369,70 +1145,70 @@ "name": "MailIntakeMessage", "kind": "class", "path": "mail_intake.models.MailIntakeMessage", - "signature": "", + "signature": "MailIntakeMessage(message_id: str, thread_id: str, timestamp: datetime, from_email: str, from_name: str | None, subject: str, body_text: str, snippet: str, raw_headers: dict[str, str])", "docstring": "Canonical internal representation of a single email message.\n\nNotes:\n **Guarantees:**\n\n - This model represents a fully parsed and normalized email message.\n - It is intentionally provider-agnostic and suitable for\n persistence, indexing, and downstream processing.\n\n **Constraints:**\n\n - No provider-specific identifiers, payloads, or API semantics\n should appear in this model.", "members": { "message_id": { "name": "message_id", "kind": "attribute", "path": "mail_intake.models.MailIntakeMessage.message_id", - "signature": "", + "signature": null, "docstring": "Provider-specific message identifier." }, "thread_id": { "name": "thread_id", "kind": "attribute", "path": "mail_intake.models.MailIntakeMessage.thread_id", - "signature": "", + "signature": null, "docstring": "Provider-specific thread identifier to which this message belongs." }, "timestamp": { "name": "timestamp", "kind": "attribute", "path": "mail_intake.models.MailIntakeMessage.timestamp", - "signature": "", + "signature": null, "docstring": "Message timestamp as a timezone-naive UTC datetime." }, "from_email": { "name": "from_email", "kind": "attribute", "path": "mail_intake.models.MailIntakeMessage.from_email", - "signature": "", + "signature": null, "docstring": "Sender email address." }, "from_name": { "name": "from_name", "kind": "attribute", "path": "mail_intake.models.MailIntakeMessage.from_name", - "signature": "", + "signature": null, "docstring": "Optional human-readable sender name." }, "subject": { "name": "subject", "kind": "attribute", "path": "mail_intake.models.MailIntakeMessage.subject", - "signature": "", + "signature": null, "docstring": "Raw subject line of the message." }, "body_text": { "name": "body_text", "kind": "attribute", "path": "mail_intake.models.MailIntakeMessage.body_text", - "signature": "", + "signature": null, "docstring": "Extracted plain-text body content of the message." }, "snippet": { "name": "snippet", "kind": "attribute", "path": "mail_intake.models.MailIntakeMessage.snippet", - "signature": "", + "signature": null, "docstring": "Short provider-supplied preview snippet of the message." }, "raw_headers": { "name": "raw_headers", "kind": "attribute", "path": "mail_intake.models.MailIntakeMessage.raw_headers", - "signature": "", + "signature": null, "docstring": "Normalized mapping of message headers (header name β†’ value)." } } @@ -1441,49 +1217,49 @@ "name": "MailIntakeThread", "kind": "class", "path": "mail_intake.models.MailIntakeThread", - "signature": "", + "signature": "MailIntakeThread(thread_id: str, normalized_subject: str, participants: set[str] = ..., messages: list[MailIntakeMessage] = ..., last_activity_at: datetime | None = ...)", "docstring": "Canonical internal representation of an email thread.\n\nNotes:\n **Guarantees:**\n\n - A thread groups multiple related messages under a single subject\n and participant set.\n - It is designed to support reasoning over conversational context\n such as job applications, interviews, follow-ups, and ongoing discussions.\n - This model is provider-agnostic and safe to persist.", "members": { "thread_id": { "name": "thread_id", "kind": "attribute", "path": "mail_intake.models.MailIntakeThread.thread_id", - "signature": "", + "signature": null, "docstring": "Provider-specific thread identifier." }, "normalized_subject": { "name": "normalized_subject", "kind": "attribute", "path": "mail_intake.models.MailIntakeThread.normalized_subject", - "signature": "", + "signature": null, "docstring": "Normalized subject line used to group related messages." }, "participants": { "name": "participants", "kind": "attribute", "path": "mail_intake.models.MailIntakeThread.participants", - "signature": "", + "signature": null, "docstring": "Set of unique participant email addresses observed in the thread." }, "messages": { "name": "messages", "kind": "attribute", "path": "mail_intake.models.MailIntakeThread.messages", - "signature": "", + "signature": null, "docstring": "Ordered list of messages belonging to this thread." }, "last_activity_at": { "name": "last_activity_at", "kind": "attribute", "path": "mail_intake.models.MailIntakeThread.last_activity_at", - "signature": "", + "signature": null, "docstring": "Timestamp of the most recent message in the thread." }, "add_message": { "name": "add_message", "kind": "function", "path": "mail_intake.models.MailIntakeThread.add_message", - "signature": "", + "signature": "add_message(message: MailIntakeMessage)", "docstring": "Add a message to the thread and update derived fields.\n\nArgs:\n message (MailIntakeMessage):\n Parsed mail message to add to the thread.\n\nNotes:\n **Responsibilities:**\n\n - Appends the message to the thread.\n - Tracks unique participants.\n - Updates the last activity timestamp." } } @@ -1495,25 +1271,11 @@ "signature": null, "docstring": "# Summary\n\nMessage domain models for Mail Intake.\n\nThis module defines the **canonical, provider-agnostic representation**\nof an individual email message as used internally by the Mail Intake\ningestion pipeline.\n\nModels in this module are safe to persist and must not contain any\nprovider-specific fields or semantics.", "members": { - "dataclass": { - "name": "dataclass", - "kind": "alias", - "path": "mail_intake.models.message.dataclass", - "signature": "", - "docstring": null - }, - "datetime": { - "name": "datetime", - "kind": "alias", - "path": "mail_intake.models.message.datetime", - "signature": "", - "docstring": null - }, "MailIntakeMessage": { "name": "MailIntakeMessage", "kind": "class", "path": "mail_intake.models.message.MailIntakeMessage", - "signature": "", + "signature": "MailIntakeMessage(message_id: str, thread_id: str, timestamp: datetime, from_email: str, from_name: str | None, subject: str, body_text: str, snippet: str, raw_headers: dict[str, str])", "docstring": "Canonical internal representation of a single email message.\n\nNotes:\n **Guarantees:**\n\n - This model represents a fully parsed and normalized email message.\n - It is intentionally provider-agnostic and suitable for\n persistence, indexing, and downstream processing.\n\n **Constraints:**\n\n - No provider-specific identifiers, payloads, or API semantics\n should appear in this model.", "members": { "message_id": { @@ -1590,95 +1352,74 @@ "signature": null, "docstring": "# Summary\n\nThread domain models for Mail Intake.\n\nThis module defines the **canonical, provider-agnostic representation**\nof an email thread as used internally by the Mail Intake ingestion pipeline.\n\nThreads group related messages and serve as the primary unit of reasoning\nfor higher-level correspondence workflows.", "members": { - "dataclass": { - "name": "dataclass", - "kind": "alias", - "path": "mail_intake.models.thread.dataclass", - "signature": "", - "docstring": null - }, - "field": { - "name": "field", - "kind": "alias", - "path": "mail_intake.models.thread.field", - "signature": "", - "docstring": null - }, - "datetime": { - "name": "datetime", - "kind": "alias", - "path": "mail_intake.models.thread.datetime", - "signature": "", - "docstring": null - }, "MailIntakeMessage": { "name": "MailIntakeMessage", "kind": "class", "path": "mail_intake.models.thread.MailIntakeMessage", - "signature": "", + "signature": "MailIntakeMessage(message_id: str, thread_id: str, timestamp: datetime, from_email: str, from_name: str | None, subject: str, body_text: str, snippet: str, raw_headers: dict[str, str])", "docstring": "Canonical internal representation of a single email message.\n\nNotes:\n **Guarantees:**\n\n - This model represents a fully parsed and normalized email message.\n - It is intentionally provider-agnostic and suitable for\n persistence, indexing, and downstream processing.\n\n **Constraints:**\n\n - No provider-specific identifiers, payloads, or API semantics\n should appear in this model.", "members": { "message_id": { "name": "message_id", "kind": "attribute", "path": "mail_intake.models.thread.MailIntakeMessage.message_id", - "signature": "", + "signature": null, "docstring": "Provider-specific message identifier." }, "thread_id": { "name": "thread_id", "kind": "attribute", "path": "mail_intake.models.thread.MailIntakeMessage.thread_id", - "signature": "", + "signature": null, "docstring": "Provider-specific thread identifier to which this message belongs." }, "timestamp": { "name": "timestamp", "kind": "attribute", "path": "mail_intake.models.thread.MailIntakeMessage.timestamp", - "signature": "", + "signature": null, "docstring": "Message timestamp as a timezone-naive UTC datetime." }, "from_email": { "name": "from_email", "kind": "attribute", "path": "mail_intake.models.thread.MailIntakeMessage.from_email", - "signature": "", + "signature": null, "docstring": "Sender email address." }, "from_name": { "name": "from_name", "kind": "attribute", "path": "mail_intake.models.thread.MailIntakeMessage.from_name", - "signature": "", + "signature": null, "docstring": "Optional human-readable sender name." }, "subject": { "name": "subject", "kind": "attribute", "path": "mail_intake.models.thread.MailIntakeMessage.subject", - "signature": "", + "signature": null, "docstring": "Raw subject line of the message." }, "body_text": { "name": "body_text", "kind": "attribute", "path": "mail_intake.models.thread.MailIntakeMessage.body_text", - "signature": "", + "signature": null, "docstring": "Extracted plain-text body content of the message." }, "snippet": { "name": "snippet", "kind": "attribute", "path": "mail_intake.models.thread.MailIntakeMessage.snippet", - "signature": "", + "signature": null, "docstring": "Short provider-supplied preview snippet of the message." }, "raw_headers": { "name": "raw_headers", "kind": "attribute", "path": "mail_intake.models.thread.MailIntakeMessage.raw_headers", - "signature": "", + "signature": null, "docstring": "Normalized mapping of message headers (header name β†’ value)." } } @@ -1687,7 +1428,7 @@ "name": "MailIntakeThread", "kind": "class", "path": "mail_intake.models.thread.MailIntakeThread", - "signature": "", + "signature": "MailIntakeThread(thread_id: str, normalized_subject: str, participants: set[str] = ..., messages: list[MailIntakeMessage] = ..., last_activity_at: datetime | None = ...)", "docstring": "Canonical internal representation of an email thread.\n\nNotes:\n **Guarantees:**\n\n - A thread groups multiple related messages under a single subject\n and participant set.\n - It is designed to support reasoning over conversational context\n such as job applications, interviews, follow-ups, and ongoing discussions.\n - This model is provider-agnostic and safe to persist.", "members": { "thread_id": { @@ -1729,7 +1470,7 @@ "name": "add_message", "kind": "function", "path": "mail_intake.models.thread.MailIntakeThread.add_message", - "signature": "", + "signature": "add_message(message: MailIntakeMessage) -> None", "docstring": "Add a message to the thread and update derived fields.\n\nArgs:\n message (MailIntakeMessage):\n Parsed mail message to add to the thread.\n\nNotes:\n **Responsibilities:**\n\n - Appends the message to the thread.\n - Tracks unique participants.\n - Updates the last activity timestamp." } } @@ -1749,28 +1490,28 @@ "name": "extract_body", "kind": "function", "path": "mail_intake.parsers.extract_body", - "signature": "", + "signature": "extract_body(payload: dict[str, Any])", "docstring": "Extract the best-effort message body from a Gmail payload.\n\nPriority:\n\n1. `text/plain`\n2. `text/html` (stripped to text)\n3. Single-part body\n4. Empty string (if nothing usable found)\n\nArgs:\n payload (dict[str, Any]):\n Provider-native message payload dictionary.\n\nReturns:\n str:\n Extracted plain-text message body." }, "parse_headers": { "name": "parse_headers", "kind": "function", "path": "mail_intake.parsers.parse_headers", - "signature": "", + "signature": "parse_headers(raw_headers: list[dict[str, str]])", "docstring": "Convert a list of Gmail-style headers into a normalized dict.\n\nArgs:\n raw_headers (list[dict[str, str]]):\n List of header dictionaries, each containing `name` and `value` keys.\n\nReturns:\n dict[str, str]:\n Dictionary mapping lowercase header names to stripped values.\n\nNotes:\n **Guarantees:**\n\n - Provider payloads (such as Gmail) typically represent headers as a\n list of name/value mappings.\n - This function normalizes them into a case-insensitive dictionary\n keyed by lowercase header names.\n\nExample:\n Typical usage:\n\n ```python\n Input:\n [\n {\"name\": \"From\", \"value\": \"John Doe \"},\n {\"name\": \"Subject\", \"value\": \"Re: Interview Update\"},\n ]\n\n Output:\n {\n \"from\": \"John Doe \",\n \"subject\": \"Re: Interview Update\",\n }\n ```" }, "extract_sender": { "name": "extract_sender", "kind": "function", "path": "mail_intake.parsers.extract_sender", - "signature": "", + "signature": "extract_sender(headers: dict[str, str])", "docstring": "Extract sender email and optional display name from headers.\n\nArgs:\n headers (dict[str, str]):\n Normalized header dictionary as returned by `parse_headers()`.\n\nReturns:\n tuple[str, str | None]:\n A tuple `(email, name)` where `email` is the sender email address\n and `name` is the display name, or `None` if unavailable.\n\nNotes:\n **Responsibilities:**\n\n - This function parses the `From` header and attempts to extract\n sender email address and optional human-readable display name.\n\nExample:\n Typical values:\n\n - `\"John Doe \"` -> `(\"john@example.com\", \"John Doe\")`\n - `\"john@example.com\"` -> `(\"john@example.com\", None)`" }, "normalize_subject": { "name": "normalize_subject", "kind": "function", "path": "mail_intake.parsers.normalize_subject", - "signature": "", + "signature": "normalize_subject(subject: str)", "docstring": "Normalize an email subject for thread-level comparison.\n\nArgs:\n subject (str):\n Raw subject line from a message header.\n\nReturns:\n str:\n Normalized subject string suitable for thread grouping.\n\nNotes:\n **Responsibilities:**\n\n - Strips common prefixes such as `Re:`, `Fwd:`, and `FW:`.\n - Repeats prefix stripping to handle stacked prefixes.\n - Collapses excessive whitespace.\n - Preserves original casing (no lowercasing).\n\n **Guarantees:**\n\n - This function is intentionally conservative and avoids aggressive\n transformations that could alter the semantic meaning of the subject." }, "body": { @@ -1780,39 +1521,18 @@ "signature": null, "docstring": "# Summary\n\nMessage body extraction utilities for Mail Intake.\n\nThis module contains helper functions for extracting a best-effort\nplain-text body from provider-native message payloads.\n\nThe logic is intentionally tolerant of malformed or partial data and\nprefers human-readable text over fidelity to original formatting.", "members": { - "base64": { - "name": "base64", - "kind": "alias", - "path": "mail_intake.parsers.body.base64", - "signature": "", - "docstring": null - }, - "Any": { - "name": "Any", - "kind": "alias", - "path": "mail_intake.parsers.body.Any", - "signature": "", - "docstring": null - }, - "BeautifulSoup": { - "name": "BeautifulSoup", - "kind": "alias", - "path": "mail_intake.parsers.body.BeautifulSoup", - "signature": "", - "docstring": null - }, "MailIntakeParsingError": { "name": "MailIntakeParsingError", "kind": "class", "path": "mail_intake.parsers.body.MailIntakeParsingError", - "signature": "", + "signature": null, "docstring": "Errors encountered while parsing message content.\n\nNotes:\n **Lifecycle:**\n\n - Raised when raw provider payloads cannot be interpreted or\n normalized into internal domain models." }, "extract_body": { "name": "extract_body", "kind": "function", "path": "mail_intake.parsers.body.extract_body", - "signature": "", + "signature": "extract_body(payload: dict[str, Any]) -> str", "docstring": "Extract the best-effort message body from a Gmail payload.\n\nPriority:\n\n1. `text/plain`\n2. `text/html` (stripped to text)\n3. Single-part body\n4. Empty string (if nothing usable found)\n\nArgs:\n payload (dict[str, Any]):\n Provider-native message payload dictionary.\n\nReturns:\n str:\n Extracted plain-text message body." } } @@ -1828,14 +1548,14 @@ "name": "parse_headers", "kind": "function", "path": "mail_intake.parsers.headers.parse_headers", - "signature": "", + "signature": "parse_headers(raw_headers: list[dict[str, str]]) -> dict[str, str]", "docstring": "Convert a list of Gmail-style headers into a normalized dict.\n\nArgs:\n raw_headers (list[dict[str, str]]):\n List of header dictionaries, each containing `name` and `value` keys.\n\nReturns:\n dict[str, str]:\n Dictionary mapping lowercase header names to stripped values.\n\nNotes:\n **Guarantees:**\n\n - Provider payloads (such as Gmail) typically represent headers as a\n list of name/value mappings.\n - This function normalizes them into a case-insensitive dictionary\n keyed by lowercase header names.\n\nExample:\n Typical usage:\n\n ```python\n Input:\n [\n {\"name\": \"From\", \"value\": \"John Doe \"},\n {\"name\": \"Subject\", \"value\": \"Re: Interview Update\"},\n ]\n\n Output:\n {\n \"from\": \"John Doe \",\n \"subject\": \"Re: Interview Update\",\n }\n ```" }, "extract_sender": { "name": "extract_sender", "kind": "function", "path": "mail_intake.parsers.headers.extract_sender", - "signature": "", + "signature": "extract_sender(headers: dict[str, str]) -> tuple[str, str | None]", "docstring": "Extract sender email and optional display name from headers.\n\nArgs:\n headers (dict[str, str]):\n Normalized header dictionary as returned by `parse_headers()`.\n\nReturns:\n tuple[str, str | None]:\n A tuple `(email, name)` where `email` is the sender email address\n and `name` is the display name, or `None` if unavailable.\n\nNotes:\n **Responsibilities:**\n\n - This function parses the `From` header and attempts to extract\n sender email address and optional human-readable display name.\n\nExample:\n Typical values:\n\n - `\"John Doe \"` -> `(\"john@example.com\", \"John Doe\")`\n - `\"john@example.com\"` -> `(\"john@example.com\", None)`" } } @@ -1847,18 +1567,11 @@ "signature": null, "docstring": "# Summary\n\nSubject line normalization utilities for Mail Intake.\n\nThis module provides helper functions for normalizing email subject lines\nto enable reliable thread-level comparison and grouping.\n\nNormalization is intentionally conservative to avoid altering semantic\nmeaning while removing common reply and forward prefixes.", "members": { - "re": { - "name": "re", - "kind": "alias", - "path": "mail_intake.parsers.subject.re", - "signature": "", - "docstring": null - }, "normalize_subject": { "name": "normalize_subject", "kind": "function", "path": "mail_intake.parsers.subject.normalize_subject", - "signature": "", + "signature": "normalize_subject(subject: str) -> str", "docstring": "Normalize an email subject for thread-level comparison.\n\nArgs:\n subject (str):\n Raw subject line from a message header.\n\nReturns:\n str:\n Normalized subject string suitable for thread grouping.\n\nNotes:\n **Responsibilities:**\n\n - Strips common prefixes such as `Re:`, `Fwd:`, and `FW:`.\n - Repeats prefix stripping to handle stacked prefixes.\n - Collapses excessive whitespace.\n - Preserves original casing (no lowercasing).\n\n **Guarantees:**\n\n - This function is intentionally conservative and avoids aggressive\n transformations that could alter the semantic meaning of the subject." } } diff --git a/docs/mcp/modules/mail_intake.models.json b/docs/mcp/modules/mail_intake.models.json index f33e351..78fd77e 100644 --- a/docs/mcp/modules/mail_intake.models.json +++ b/docs/mcp/modules/mail_intake.models.json @@ -8,70 +8,70 @@ "name": "MailIntakeMessage", "kind": "class", "path": "mail_intake.models.MailIntakeMessage", - "signature": "", + "signature": "MailIntakeMessage(message_id: str, thread_id: str, timestamp: datetime, from_email: str, from_name: str | None, subject: str, body_text: str, snippet: str, raw_headers: dict[str, str])", "docstring": "Canonical internal representation of a single email message.\n\nNotes:\n **Guarantees:**\n\n - This model represents a fully parsed and normalized email message.\n - It is intentionally provider-agnostic and suitable for\n persistence, indexing, and downstream processing.\n\n **Constraints:**\n\n - No provider-specific identifiers, payloads, or API semantics\n should appear in this model.", "members": { "message_id": { "name": "message_id", "kind": "attribute", "path": "mail_intake.models.MailIntakeMessage.message_id", - "signature": "", + "signature": null, "docstring": "Provider-specific message identifier." }, "thread_id": { "name": "thread_id", "kind": "attribute", "path": "mail_intake.models.MailIntakeMessage.thread_id", - "signature": "", + "signature": null, "docstring": "Provider-specific thread identifier to which this message belongs." }, "timestamp": { "name": "timestamp", "kind": "attribute", "path": "mail_intake.models.MailIntakeMessage.timestamp", - "signature": "", + "signature": null, "docstring": "Message timestamp as a timezone-naive UTC datetime." }, "from_email": { "name": "from_email", "kind": "attribute", "path": "mail_intake.models.MailIntakeMessage.from_email", - "signature": "", + "signature": null, "docstring": "Sender email address." }, "from_name": { "name": "from_name", "kind": "attribute", "path": "mail_intake.models.MailIntakeMessage.from_name", - "signature": "", + "signature": null, "docstring": "Optional human-readable sender name." }, "subject": { "name": "subject", "kind": "attribute", "path": "mail_intake.models.MailIntakeMessage.subject", - "signature": "", + "signature": null, "docstring": "Raw subject line of the message." }, "body_text": { "name": "body_text", "kind": "attribute", "path": "mail_intake.models.MailIntakeMessage.body_text", - "signature": "", + "signature": null, "docstring": "Extracted plain-text body content of the message." }, "snippet": { "name": "snippet", "kind": "attribute", "path": "mail_intake.models.MailIntakeMessage.snippet", - "signature": "", + "signature": null, "docstring": "Short provider-supplied preview snippet of the message." }, "raw_headers": { "name": "raw_headers", "kind": "attribute", "path": "mail_intake.models.MailIntakeMessage.raw_headers", - "signature": "", + "signature": null, "docstring": "Normalized mapping of message headers (header name β†’ value)." } } @@ -80,49 +80,49 @@ "name": "MailIntakeThread", "kind": "class", "path": "mail_intake.models.MailIntakeThread", - "signature": "", + "signature": "MailIntakeThread(thread_id: str, normalized_subject: str, participants: set[str] = ..., messages: list[MailIntakeMessage] = ..., last_activity_at: datetime | None = ...)", "docstring": "Canonical internal representation of an email thread.\n\nNotes:\n **Guarantees:**\n\n - A thread groups multiple related messages under a single subject\n and participant set.\n - It is designed to support reasoning over conversational context\n such as job applications, interviews, follow-ups, and ongoing discussions.\n - This model is provider-agnostic and safe to persist.", "members": { "thread_id": { "name": "thread_id", "kind": "attribute", "path": "mail_intake.models.MailIntakeThread.thread_id", - "signature": "", + "signature": null, "docstring": "Provider-specific thread identifier." }, "normalized_subject": { "name": "normalized_subject", "kind": "attribute", "path": "mail_intake.models.MailIntakeThread.normalized_subject", - "signature": "", + "signature": null, "docstring": "Normalized subject line used to group related messages." }, "participants": { "name": "participants", "kind": "attribute", "path": "mail_intake.models.MailIntakeThread.participants", - "signature": "", + "signature": null, "docstring": "Set of unique participant email addresses observed in the thread." }, "messages": { "name": "messages", "kind": "attribute", "path": "mail_intake.models.MailIntakeThread.messages", - "signature": "", + "signature": null, "docstring": "Ordered list of messages belonging to this thread." }, "last_activity_at": { "name": "last_activity_at", "kind": "attribute", "path": "mail_intake.models.MailIntakeThread.last_activity_at", - "signature": "", + "signature": null, "docstring": "Timestamp of the most recent message in the thread." }, "add_message": { "name": "add_message", "kind": "function", "path": "mail_intake.models.MailIntakeThread.add_message", - "signature": "", + "signature": "add_message(message: MailIntakeMessage)", "docstring": "Add a message to the thread and update derived fields.\n\nArgs:\n message (MailIntakeMessage):\n Parsed mail message to add to the thread.\n\nNotes:\n **Responsibilities:**\n\n - Appends the message to the thread.\n - Tracks unique participants.\n - Updates the last activity timestamp." } } @@ -134,25 +134,11 @@ "signature": null, "docstring": "# Summary\n\nMessage domain models for Mail Intake.\n\nThis module defines the **canonical, provider-agnostic representation**\nof an individual email message as used internally by the Mail Intake\ningestion pipeline.\n\nModels in this module are safe to persist and must not contain any\nprovider-specific fields or semantics.", "members": { - "dataclass": { - "name": "dataclass", - "kind": "alias", - "path": "mail_intake.models.message.dataclass", - "signature": "", - "docstring": null - }, - "datetime": { - "name": "datetime", - "kind": "alias", - "path": "mail_intake.models.message.datetime", - "signature": "", - "docstring": null - }, "MailIntakeMessage": { "name": "MailIntakeMessage", "kind": "class", "path": "mail_intake.models.message.MailIntakeMessage", - "signature": "", + "signature": "MailIntakeMessage(message_id: str, thread_id: str, timestamp: datetime, from_email: str, from_name: str | None, subject: str, body_text: str, snippet: str, raw_headers: dict[str, str])", "docstring": "Canonical internal representation of a single email message.\n\nNotes:\n **Guarantees:**\n\n - This model represents a fully parsed and normalized email message.\n - It is intentionally provider-agnostic and suitable for\n persistence, indexing, and downstream processing.\n\n **Constraints:**\n\n - No provider-specific identifiers, payloads, or API semantics\n should appear in this model.", "members": { "message_id": { @@ -229,95 +215,74 @@ "signature": null, "docstring": "# Summary\n\nThread domain models for Mail Intake.\n\nThis module defines the **canonical, provider-agnostic representation**\nof an email thread as used internally by the Mail Intake ingestion pipeline.\n\nThreads group related messages and serve as the primary unit of reasoning\nfor higher-level correspondence workflows.", "members": { - "dataclass": { - "name": "dataclass", - "kind": "alias", - "path": "mail_intake.models.thread.dataclass", - "signature": "", - "docstring": null - }, - "field": { - "name": "field", - "kind": "alias", - "path": "mail_intake.models.thread.field", - "signature": "", - "docstring": null - }, - "datetime": { - "name": "datetime", - "kind": "alias", - "path": "mail_intake.models.thread.datetime", - "signature": "", - "docstring": null - }, "MailIntakeMessage": { "name": "MailIntakeMessage", "kind": "class", "path": "mail_intake.models.thread.MailIntakeMessage", - "signature": "", + "signature": "MailIntakeMessage(message_id: str, thread_id: str, timestamp: datetime, from_email: str, from_name: str | None, subject: str, body_text: str, snippet: str, raw_headers: dict[str, str])", "docstring": "Canonical internal representation of a single email message.\n\nNotes:\n **Guarantees:**\n\n - This model represents a fully parsed and normalized email message.\n - It is intentionally provider-agnostic and suitable for\n persistence, indexing, and downstream processing.\n\n **Constraints:**\n\n - No provider-specific identifiers, payloads, or API semantics\n should appear in this model.", "members": { "message_id": { "name": "message_id", "kind": "attribute", "path": "mail_intake.models.thread.MailIntakeMessage.message_id", - "signature": "", + "signature": null, "docstring": "Provider-specific message identifier." }, "thread_id": { "name": "thread_id", "kind": "attribute", "path": "mail_intake.models.thread.MailIntakeMessage.thread_id", - "signature": "", + "signature": null, "docstring": "Provider-specific thread identifier to which this message belongs." }, "timestamp": { "name": "timestamp", "kind": "attribute", "path": "mail_intake.models.thread.MailIntakeMessage.timestamp", - "signature": "", + "signature": null, "docstring": "Message timestamp as a timezone-naive UTC datetime." }, "from_email": { "name": "from_email", "kind": "attribute", "path": "mail_intake.models.thread.MailIntakeMessage.from_email", - "signature": "", + "signature": null, "docstring": "Sender email address." }, "from_name": { "name": "from_name", "kind": "attribute", "path": "mail_intake.models.thread.MailIntakeMessage.from_name", - "signature": "", + "signature": null, "docstring": "Optional human-readable sender name." }, "subject": { "name": "subject", "kind": "attribute", "path": "mail_intake.models.thread.MailIntakeMessage.subject", - "signature": "", + "signature": null, "docstring": "Raw subject line of the message." }, "body_text": { "name": "body_text", "kind": "attribute", "path": "mail_intake.models.thread.MailIntakeMessage.body_text", - "signature": "", + "signature": null, "docstring": "Extracted plain-text body content of the message." }, "snippet": { "name": "snippet", "kind": "attribute", "path": "mail_intake.models.thread.MailIntakeMessage.snippet", - "signature": "", + "signature": null, "docstring": "Short provider-supplied preview snippet of the message." }, "raw_headers": { "name": "raw_headers", "kind": "attribute", "path": "mail_intake.models.thread.MailIntakeMessage.raw_headers", - "signature": "", + "signature": null, "docstring": "Normalized mapping of message headers (header name β†’ value)." } } @@ -326,7 +291,7 @@ "name": "MailIntakeThread", "kind": "class", "path": "mail_intake.models.thread.MailIntakeThread", - "signature": "", + "signature": "MailIntakeThread(thread_id: str, normalized_subject: str, participants: set[str] = ..., messages: list[MailIntakeMessage] = ..., last_activity_at: datetime | None = ...)", "docstring": "Canonical internal representation of an email thread.\n\nNotes:\n **Guarantees:**\n\n - A thread groups multiple related messages under a single subject\n and participant set.\n - It is designed to support reasoning over conversational context\n such as job applications, interviews, follow-ups, and ongoing discussions.\n - This model is provider-agnostic and safe to persist.", "members": { "thread_id": { @@ -368,7 +333,7 @@ "name": "add_message", "kind": "function", "path": "mail_intake.models.thread.MailIntakeThread.add_message", - "signature": "", + "signature": "add_message(message: MailIntakeMessage) -> None", "docstring": "Add a message to the thread and update derived fields.\n\nArgs:\n message (MailIntakeMessage):\n Parsed mail message to add to the thread.\n\nNotes:\n **Responsibilities:**\n\n - Appends the message to the thread.\n - Tracks unique participants.\n - Updates the last activity timestamp." } } diff --git a/docs/mcp/modules/mail_intake.models.message.json b/docs/mcp/modules/mail_intake.models.message.json index c5d1973..22f1ff8 100644 --- a/docs/mcp/modules/mail_intake.models.message.json +++ b/docs/mcp/modules/mail_intake.models.message.json @@ -4,25 +4,11 @@ "path": "mail_intake.models.message", "docstring": "# Summary\n\nMessage domain models for Mail Intake.\n\nThis module defines the **canonical, provider-agnostic representation**\nof an individual email message as used internally by the Mail Intake\ningestion pipeline.\n\nModels in this module are safe to persist and must not contain any\nprovider-specific fields or semantics.", "objects": { - "dataclass": { - "name": "dataclass", - "kind": "alias", - "path": "mail_intake.models.message.dataclass", - "signature": "", - "docstring": null - }, - "datetime": { - "name": "datetime", - "kind": "alias", - "path": "mail_intake.models.message.datetime", - "signature": "", - "docstring": null - }, "MailIntakeMessage": { "name": "MailIntakeMessage", "kind": "class", "path": "mail_intake.models.message.MailIntakeMessage", - "signature": "", + "signature": "MailIntakeMessage(message_id: str, thread_id: str, timestamp: datetime, from_email: str, from_name: str | None, subject: str, body_text: str, snippet: str, raw_headers: dict[str, str])", "docstring": "Canonical internal representation of a single email message.\n\nNotes:\n **Guarantees:**\n\n - This model represents a fully parsed and normalized email message.\n - It is intentionally provider-agnostic and suitable for\n persistence, indexing, and downstream processing.\n\n **Constraints:**\n\n - No provider-specific identifiers, payloads, or API semantics\n should appear in this model.", "members": { "message_id": { diff --git a/docs/mcp/modules/mail_intake.models.thread.json b/docs/mcp/modules/mail_intake.models.thread.json index c91ea04..c4aec2b 100644 --- a/docs/mcp/modules/mail_intake.models.thread.json +++ b/docs/mcp/modules/mail_intake.models.thread.json @@ -4,95 +4,74 @@ "path": "mail_intake.models.thread", "docstring": "# Summary\n\nThread domain models for Mail Intake.\n\nThis module defines the **canonical, provider-agnostic representation**\nof an email thread as used internally by the Mail Intake ingestion pipeline.\n\nThreads group related messages and serve as the primary unit of reasoning\nfor higher-level correspondence workflows.", "objects": { - "dataclass": { - "name": "dataclass", - "kind": "alias", - "path": "mail_intake.models.thread.dataclass", - "signature": "", - "docstring": null - }, - "field": { - "name": "field", - "kind": "alias", - "path": "mail_intake.models.thread.field", - "signature": "", - "docstring": null - }, - "datetime": { - "name": "datetime", - "kind": "alias", - "path": "mail_intake.models.thread.datetime", - "signature": "", - "docstring": null - }, "MailIntakeMessage": { "name": "MailIntakeMessage", "kind": "class", "path": "mail_intake.models.thread.MailIntakeMessage", - "signature": "", + "signature": "MailIntakeMessage(message_id: str, thread_id: str, timestamp: datetime, from_email: str, from_name: str | None, subject: str, body_text: str, snippet: str, raw_headers: dict[str, str])", "docstring": "Canonical internal representation of a single email message.\n\nNotes:\n **Guarantees:**\n\n - This model represents a fully parsed and normalized email message.\n - It is intentionally provider-agnostic and suitable for\n persistence, indexing, and downstream processing.\n\n **Constraints:**\n\n - No provider-specific identifiers, payloads, or API semantics\n should appear in this model.", "members": { "message_id": { "name": "message_id", "kind": "attribute", "path": "mail_intake.models.thread.MailIntakeMessage.message_id", - "signature": "", + "signature": null, "docstring": "Provider-specific message identifier." }, "thread_id": { "name": "thread_id", "kind": "attribute", "path": "mail_intake.models.thread.MailIntakeMessage.thread_id", - "signature": "", + "signature": null, "docstring": "Provider-specific thread identifier to which this message belongs." }, "timestamp": { "name": "timestamp", "kind": "attribute", "path": "mail_intake.models.thread.MailIntakeMessage.timestamp", - "signature": "", + "signature": null, "docstring": "Message timestamp as a timezone-naive UTC datetime." }, "from_email": { "name": "from_email", "kind": "attribute", "path": "mail_intake.models.thread.MailIntakeMessage.from_email", - "signature": "", + "signature": null, "docstring": "Sender email address." }, "from_name": { "name": "from_name", "kind": "attribute", "path": "mail_intake.models.thread.MailIntakeMessage.from_name", - "signature": "", + "signature": null, "docstring": "Optional human-readable sender name." }, "subject": { "name": "subject", "kind": "attribute", "path": "mail_intake.models.thread.MailIntakeMessage.subject", - "signature": "", + "signature": null, "docstring": "Raw subject line of the message." }, "body_text": { "name": "body_text", "kind": "attribute", "path": "mail_intake.models.thread.MailIntakeMessage.body_text", - "signature": "", + "signature": null, "docstring": "Extracted plain-text body content of the message." }, "snippet": { "name": "snippet", "kind": "attribute", "path": "mail_intake.models.thread.MailIntakeMessage.snippet", - "signature": "", + "signature": null, "docstring": "Short provider-supplied preview snippet of the message." }, "raw_headers": { "name": "raw_headers", "kind": "attribute", "path": "mail_intake.models.thread.MailIntakeMessage.raw_headers", - "signature": "", + "signature": null, "docstring": "Normalized mapping of message headers (header name β†’ value)." } } @@ -101,7 +80,7 @@ "name": "MailIntakeThread", "kind": "class", "path": "mail_intake.models.thread.MailIntakeThread", - "signature": "", + "signature": "MailIntakeThread(thread_id: str, normalized_subject: str, participants: set[str] = ..., messages: list[MailIntakeMessage] = ..., last_activity_at: datetime | None = ...)", "docstring": "Canonical internal representation of an email thread.\n\nNotes:\n **Guarantees:**\n\n - A thread groups multiple related messages under a single subject\n and participant set.\n - It is designed to support reasoning over conversational context\n such as job applications, interviews, follow-ups, and ongoing discussions.\n - This model is provider-agnostic and safe to persist.", "members": { "thread_id": { @@ -143,7 +122,7 @@ "name": "add_message", "kind": "function", "path": "mail_intake.models.thread.MailIntakeThread.add_message", - "signature": "", + "signature": "add_message(message: MailIntakeMessage) -> None", "docstring": "Add a message to the thread and update derived fields.\n\nArgs:\n message (MailIntakeMessage):\n Parsed mail message to add to the thread.\n\nNotes:\n **Responsibilities:**\n\n - Appends the message to the thread.\n - Tracks unique participants.\n - Updates the last activity timestamp." } } diff --git a/docs/mcp/modules/mail_intake.parsers.body.json b/docs/mcp/modules/mail_intake.parsers.body.json index b0f11ab..a8cbcea 100644 --- a/docs/mcp/modules/mail_intake.parsers.body.json +++ b/docs/mcp/modules/mail_intake.parsers.body.json @@ -4,39 +4,18 @@ "path": "mail_intake.parsers.body", "docstring": "# Summary\n\nMessage body extraction utilities for Mail Intake.\n\nThis module contains helper functions for extracting a best-effort\nplain-text body from provider-native message payloads.\n\nThe logic is intentionally tolerant of malformed or partial data and\nprefers human-readable text over fidelity to original formatting.", "objects": { - "base64": { - "name": "base64", - "kind": "alias", - "path": "mail_intake.parsers.body.base64", - "signature": "", - "docstring": null - }, - "Any": { - "name": "Any", - "kind": "alias", - "path": "mail_intake.parsers.body.Any", - "signature": "", - "docstring": null - }, - "BeautifulSoup": { - "name": "BeautifulSoup", - "kind": "alias", - "path": "mail_intake.parsers.body.BeautifulSoup", - "signature": "", - "docstring": null - }, "MailIntakeParsingError": { "name": "MailIntakeParsingError", "kind": "class", "path": "mail_intake.parsers.body.MailIntakeParsingError", - "signature": "", + "signature": null, "docstring": "Errors encountered while parsing message content.\n\nNotes:\n **Lifecycle:**\n\n - Raised when raw provider payloads cannot be interpreted or\n normalized into internal domain models." }, "extract_body": { "name": "extract_body", "kind": "function", "path": "mail_intake.parsers.body.extract_body", - "signature": "", + "signature": "extract_body(payload: dict[str, Any]) -> str", "docstring": "Extract the best-effort message body from a Gmail payload.\n\nPriority:\n\n1. `text/plain`\n2. `text/html` (stripped to text)\n3. Single-part body\n4. Empty string (if nothing usable found)\n\nArgs:\n payload (dict[str, Any]):\n Provider-native message payload dictionary.\n\nReturns:\n str:\n Extracted plain-text message body." } } diff --git a/docs/mcp/modules/mail_intake.parsers.headers.json b/docs/mcp/modules/mail_intake.parsers.headers.json index 71096fc..1752e12 100644 --- a/docs/mcp/modules/mail_intake.parsers.headers.json +++ b/docs/mcp/modules/mail_intake.parsers.headers.json @@ -8,14 +8,14 @@ "name": "parse_headers", "kind": "function", "path": "mail_intake.parsers.headers.parse_headers", - "signature": "", + "signature": "parse_headers(raw_headers: list[dict[str, str]]) -> dict[str, str]", "docstring": "Convert a list of Gmail-style headers into a normalized dict.\n\nArgs:\n raw_headers (list[dict[str, str]]):\n List of header dictionaries, each containing `name` and `value` keys.\n\nReturns:\n dict[str, str]:\n Dictionary mapping lowercase header names to stripped values.\n\nNotes:\n **Guarantees:**\n\n - Provider payloads (such as Gmail) typically represent headers as a\n list of name/value mappings.\n - This function normalizes them into a case-insensitive dictionary\n keyed by lowercase header names.\n\nExample:\n Typical usage:\n\n ```python\n Input:\n [\n {\"name\": \"From\", \"value\": \"John Doe \"},\n {\"name\": \"Subject\", \"value\": \"Re: Interview Update\"},\n ]\n\n Output:\n {\n \"from\": \"John Doe \",\n \"subject\": \"Re: Interview Update\",\n }\n ```" }, "extract_sender": { "name": "extract_sender", "kind": "function", "path": "mail_intake.parsers.headers.extract_sender", - "signature": "", + "signature": "extract_sender(headers: dict[str, str]) -> tuple[str, str | None]", "docstring": "Extract sender email and optional display name from headers.\n\nArgs:\n headers (dict[str, str]):\n Normalized header dictionary as returned by `parse_headers()`.\n\nReturns:\n tuple[str, str | None]:\n A tuple `(email, name)` where `email` is the sender email address\n and `name` is the display name, or `None` if unavailable.\n\nNotes:\n **Responsibilities:**\n\n - This function parses the `From` header and attempts to extract\n sender email address and optional human-readable display name.\n\nExample:\n Typical values:\n\n - `\"John Doe \"` -> `(\"john@example.com\", \"John Doe\")`\n - `\"john@example.com\"` -> `(\"john@example.com\", None)`" } } diff --git a/docs/mcp/modules/mail_intake.parsers.json b/docs/mcp/modules/mail_intake.parsers.json index 8a350b3..7d1e973 100644 --- a/docs/mcp/modules/mail_intake.parsers.json +++ b/docs/mcp/modules/mail_intake.parsers.json @@ -8,28 +8,28 @@ "name": "extract_body", "kind": "function", "path": "mail_intake.parsers.extract_body", - "signature": "", + "signature": "extract_body(payload: dict[str, Any])", "docstring": "Extract the best-effort message body from a Gmail payload.\n\nPriority:\n\n1. `text/plain`\n2. `text/html` (stripped to text)\n3. Single-part body\n4. Empty string (if nothing usable found)\n\nArgs:\n payload (dict[str, Any]):\n Provider-native message payload dictionary.\n\nReturns:\n str:\n Extracted plain-text message body." }, "parse_headers": { "name": "parse_headers", "kind": "function", "path": "mail_intake.parsers.parse_headers", - "signature": "", + "signature": "parse_headers(raw_headers: list[dict[str, str]])", "docstring": "Convert a list of Gmail-style headers into a normalized dict.\n\nArgs:\n raw_headers (list[dict[str, str]]):\n List of header dictionaries, each containing `name` and `value` keys.\n\nReturns:\n dict[str, str]:\n Dictionary mapping lowercase header names to stripped values.\n\nNotes:\n **Guarantees:**\n\n - Provider payloads (such as Gmail) typically represent headers as a\n list of name/value mappings.\n - This function normalizes them into a case-insensitive dictionary\n keyed by lowercase header names.\n\nExample:\n Typical usage:\n\n ```python\n Input:\n [\n {\"name\": \"From\", \"value\": \"John Doe \"},\n {\"name\": \"Subject\", \"value\": \"Re: Interview Update\"},\n ]\n\n Output:\n {\n \"from\": \"John Doe \",\n \"subject\": \"Re: Interview Update\",\n }\n ```" }, "extract_sender": { "name": "extract_sender", "kind": "function", "path": "mail_intake.parsers.extract_sender", - "signature": "", + "signature": "extract_sender(headers: dict[str, str])", "docstring": "Extract sender email and optional display name from headers.\n\nArgs:\n headers (dict[str, str]):\n Normalized header dictionary as returned by `parse_headers()`.\n\nReturns:\n tuple[str, str | None]:\n A tuple `(email, name)` where `email` is the sender email address\n and `name` is the display name, or `None` if unavailable.\n\nNotes:\n **Responsibilities:**\n\n - This function parses the `From` header and attempts to extract\n sender email address and optional human-readable display name.\n\nExample:\n Typical values:\n\n - `\"John Doe \"` -> `(\"john@example.com\", \"John Doe\")`\n - `\"john@example.com\"` -> `(\"john@example.com\", None)`" }, "normalize_subject": { "name": "normalize_subject", "kind": "function", "path": "mail_intake.parsers.normalize_subject", - "signature": "", + "signature": "normalize_subject(subject: str)", "docstring": "Normalize an email subject for thread-level comparison.\n\nArgs:\n subject (str):\n Raw subject line from a message header.\n\nReturns:\n str:\n Normalized subject string suitable for thread grouping.\n\nNotes:\n **Responsibilities:**\n\n - Strips common prefixes such as `Re:`, `Fwd:`, and `FW:`.\n - Repeats prefix stripping to handle stacked prefixes.\n - Collapses excessive whitespace.\n - Preserves original casing (no lowercasing).\n\n **Guarantees:**\n\n - This function is intentionally conservative and avoids aggressive\n transformations that could alter the semantic meaning of the subject." }, "body": { @@ -39,39 +39,18 @@ "signature": null, "docstring": "# Summary\n\nMessage body extraction utilities for Mail Intake.\n\nThis module contains helper functions for extracting a best-effort\nplain-text body from provider-native message payloads.\n\nThe logic is intentionally tolerant of malformed or partial data and\nprefers human-readable text over fidelity to original formatting.", "members": { - "base64": { - "name": "base64", - "kind": "alias", - "path": "mail_intake.parsers.body.base64", - "signature": "", - "docstring": null - }, - "Any": { - "name": "Any", - "kind": "alias", - "path": "mail_intake.parsers.body.Any", - "signature": "", - "docstring": null - }, - "BeautifulSoup": { - "name": "BeautifulSoup", - "kind": "alias", - "path": "mail_intake.parsers.body.BeautifulSoup", - "signature": "", - "docstring": null - }, "MailIntakeParsingError": { "name": "MailIntakeParsingError", "kind": "class", "path": "mail_intake.parsers.body.MailIntakeParsingError", - "signature": "", + "signature": null, "docstring": "Errors encountered while parsing message content.\n\nNotes:\n **Lifecycle:**\n\n - Raised when raw provider payloads cannot be interpreted or\n normalized into internal domain models." }, "extract_body": { "name": "extract_body", "kind": "function", "path": "mail_intake.parsers.body.extract_body", - "signature": "", + "signature": "extract_body(payload: dict[str, Any]) -> str", "docstring": "Extract the best-effort message body from a Gmail payload.\n\nPriority:\n\n1. `text/plain`\n2. `text/html` (stripped to text)\n3. Single-part body\n4. Empty string (if nothing usable found)\n\nArgs:\n payload (dict[str, Any]):\n Provider-native message payload dictionary.\n\nReturns:\n str:\n Extracted plain-text message body." } } @@ -87,14 +66,14 @@ "name": "parse_headers", "kind": "function", "path": "mail_intake.parsers.headers.parse_headers", - "signature": "", + "signature": "parse_headers(raw_headers: list[dict[str, str]]) -> dict[str, str]", "docstring": "Convert a list of Gmail-style headers into a normalized dict.\n\nArgs:\n raw_headers (list[dict[str, str]]):\n List of header dictionaries, each containing `name` and `value` keys.\n\nReturns:\n dict[str, str]:\n Dictionary mapping lowercase header names to stripped values.\n\nNotes:\n **Guarantees:**\n\n - Provider payloads (such as Gmail) typically represent headers as a\n list of name/value mappings.\n - This function normalizes them into a case-insensitive dictionary\n keyed by lowercase header names.\n\nExample:\n Typical usage:\n\n ```python\n Input:\n [\n {\"name\": \"From\", \"value\": \"John Doe \"},\n {\"name\": \"Subject\", \"value\": \"Re: Interview Update\"},\n ]\n\n Output:\n {\n \"from\": \"John Doe \",\n \"subject\": \"Re: Interview Update\",\n }\n ```" }, "extract_sender": { "name": "extract_sender", "kind": "function", "path": "mail_intake.parsers.headers.extract_sender", - "signature": "", + "signature": "extract_sender(headers: dict[str, str]) -> tuple[str, str | None]", "docstring": "Extract sender email and optional display name from headers.\n\nArgs:\n headers (dict[str, str]):\n Normalized header dictionary as returned by `parse_headers()`.\n\nReturns:\n tuple[str, str | None]:\n A tuple `(email, name)` where `email` is the sender email address\n and `name` is the display name, or `None` if unavailable.\n\nNotes:\n **Responsibilities:**\n\n - This function parses the `From` header and attempts to extract\n sender email address and optional human-readable display name.\n\nExample:\n Typical values:\n\n - `\"John Doe \"` -> `(\"john@example.com\", \"John Doe\")`\n - `\"john@example.com\"` -> `(\"john@example.com\", None)`" } } @@ -106,18 +85,11 @@ "signature": null, "docstring": "# Summary\n\nSubject line normalization utilities for Mail Intake.\n\nThis module provides helper functions for normalizing email subject lines\nto enable reliable thread-level comparison and grouping.\n\nNormalization is intentionally conservative to avoid altering semantic\nmeaning while removing common reply and forward prefixes.", "members": { - "re": { - "name": "re", - "kind": "alias", - "path": "mail_intake.parsers.subject.re", - "signature": "", - "docstring": null - }, "normalize_subject": { "name": "normalize_subject", "kind": "function", "path": "mail_intake.parsers.subject.normalize_subject", - "signature": "", + "signature": "normalize_subject(subject: str) -> str", "docstring": "Normalize an email subject for thread-level comparison.\n\nArgs:\n subject (str):\n Raw subject line from a message header.\n\nReturns:\n str:\n Normalized subject string suitable for thread grouping.\n\nNotes:\n **Responsibilities:**\n\n - Strips common prefixes such as `Re:`, `Fwd:`, and `FW:`.\n - Repeats prefix stripping to handle stacked prefixes.\n - Collapses excessive whitespace.\n - Preserves original casing (no lowercasing).\n\n **Guarantees:**\n\n - This function is intentionally conservative and avoids aggressive\n transformations that could alter the semantic meaning of the subject." } } diff --git a/docs/mcp/modules/mail_intake.parsers.subject.json b/docs/mcp/modules/mail_intake.parsers.subject.json index b393fff..7b678fd 100644 --- a/docs/mcp/modules/mail_intake.parsers.subject.json +++ b/docs/mcp/modules/mail_intake.parsers.subject.json @@ -4,18 +4,11 @@ "path": "mail_intake.parsers.subject", "docstring": "# Summary\n\nSubject line normalization utilities for Mail Intake.\n\nThis module provides helper functions for normalizing email subject lines\nto enable reliable thread-level comparison and grouping.\n\nNormalization is intentionally conservative to avoid altering semantic\nmeaning while removing common reply and forward prefixes.", "objects": { - "re": { - "name": "re", - "kind": "alias", - "path": "mail_intake.parsers.subject.re", - "signature": "", - "docstring": null - }, "normalize_subject": { "name": "normalize_subject", "kind": "function", "path": "mail_intake.parsers.subject.normalize_subject", - "signature": "", + "signature": "normalize_subject(subject: str) -> str", "docstring": "Normalize an email subject for thread-level comparison.\n\nArgs:\n subject (str):\n Raw subject line from a message header.\n\nReturns:\n str:\n Normalized subject string suitable for thread grouping.\n\nNotes:\n **Responsibilities:**\n\n - Strips common prefixes such as `Re:`, `Fwd:`, and `FW:`.\n - Repeats prefix stripping to handle stacked prefixes.\n - Collapses excessive whitespace.\n - Preserves original casing (no lowercasing).\n\n **Guarantees:**\n\n - This function is intentionally conservative and avoids aggressive\n transformations that could alter the semantic meaning of the subject." } } diff --git a/docs/mkdocs.wiki.yml b/docs/mkdocs.wiki.yml new file mode 100644 index 0000000..252c263 --- /dev/null +++ b/docs/mkdocs.wiki.yml @@ -0,0 +1,69 @@ +site_name: Mail Intake Documentation +docs_dir: wiki +site_dir: ../site/wiki + +nav: +- Home: index.md +- Overview: 01_overview.md +- How to Use: 02_how_to_use.md +- Extending Mail Intake: 03_extending.md +- Development: 04_development.md + +theme: + name: material + palette: + scheme: slate + primary: blue grey + accent: teal + font: + text: Roboto + code: JetBrains Mono + features: + - navigation.sections + - navigation.expand + - navigation.top + - navigation.instant + - navigation.tracking + - navigation.indexes + - content.code.copy + - content.code.annotate + - content.tabs.link + - content.action.edit + - search.highlight + - search.share + - search.suggest + - navigation.tabs + - toc.integrate + - header.autohide + - announce.dismiss + - footer.social + - content.code.select + - content.code.line_numbers + - content.tooltips + icon: + logo: material/inbox + repo: fontawesome/brands/github +markdown_extensions: +- pymdownx.superfences +- pymdownx.inlinehilite +- pymdownx.snippets +- admonition +- pymdownx.details +- pymdownx.highlight: + linenums: true + anchor_linenums: true + line_spans: __span + pygments_lang_class: true +- pymdownx.tabbed: + alternate_style: true +- pymdownx.tasklist: + custom_checkbox: true +- tables +- footnotes +- pymdownx.caret +- pymdownx.tilde +- pymdownx.mark +extra_css: +- https://unpkg.com/dracula-prism/dist/css/dracula-prism.css +plugins: +- search \ No newline at end of file diff --git a/docs/wiki/01_overview.md b/docs/wiki/01_overview.md new file mode 100644 index 0000000..43c3f27 --- /dev/null +++ b/docs/wiki/01_overview.md @@ -0,0 +1,91 @@ +# 🧱 Overview + +Mail Intake is a **contract-first ingestion pipeline**. Adapters handle +transport to a provider, parsers normalize provider payloads, and the reader +orchestrates the whole flow into canonical domain models. + +--- + +## πŸ—οΈ Architecture + +```text + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ External Provider (e.g. Gmail API) β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ MailIntakeAdapter (transport) β”‚ provider API calls + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ provider-native payloads + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ Parsers (normalization) β”‚ headers, body, subject + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ composed + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ MailIntakeReader (orchestration) β”‚ iter_messages / iter_threads + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ MailIntakeMessage / Thread β”‚ canonical domain models + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +Layers: + +1. **Adapters** (`mail_intake.adapters`) β€” provider-specific, read-only + transport. Return provider-native payloads; never interpret them. +2. **Auth** (`mail_intake.auth`) β€” credential acquisition and lifecycle + management, decoupled from adapters. +3. **Credentials** (`mail_intake.credentials`) β€” persistence of auth tokens; + `PickleCredentialStore` locally, `RedisCredentialStore` for production. +4. **Parsers** (`mail_intake.parsers`) β€” extract headers, body text, sender, + and normalized subjects from provider payloads. +5. **Ingestion** (`mail_intake.ingestion`) β€” `MailIntakeReader` wires an + adapter + parsers into iterators over canonical models. +6. **Models** (`mail_intake.models`) β€” provider-agnostic `MailIntakeMessage` + and `MailIntakeThread`. + +--- + +## πŸ“¦ Domain models + +`MailIntakeMessage`: + +| Field | Type | Meaning | +|---|---|---| +| `message_id` | `str` | Provider message id | +| `thread_id` | `str` | Conversation thread id | +| `timestamp` | `datetime` | Message timestamp | +| `from_email` | `str` | Sender email | +| `from_name` | `str \| None` | Sender display name | +| `subject` | `str` | Message subject | +| `body_text` | `str` | Extracted plain-text body | +| `snippet` | `str` | Provider snippet | +| `raw_headers` | `dict[str, str]` | Unmodified headers | + +`MailIntakeThread`: + +| Field | Type | Meaning | +|---|---|---| +| `thread_id` | `str` | Conversation id | +| `normalized_subject` | `str` | Normalized subject (threads share one) | +| `participants` | `set[str]` | Distinct senders | +| `messages` | `list[MailIntakeMessage]` | Ordered messages | +| `last_activity_at` | `datetime \| None` | Latest message time | + +--- + +## πŸ”’ Design guarantees + +- Read-only access β€” no mutation of provider state. +- Provider-agnostic domain models. +- Explicit configuration and dependency injection (no implicit env reads). +- Extensible via public contracts; built-in adapters are reference + implementations and may change internally. + +--- + +## πŸ“š Read Next + +- [How to Use](02_how_to_use.md) β€” the Gmail ingestion flow. +- [Extending Mail Intake](03_extending.md) β€” custom adapters and stores. \ No newline at end of file diff --git a/docs/wiki/02_how_to_use.md b/docs/wiki/02_how_to_use.md new file mode 100644 index 0000000..41f8e20 --- /dev/null +++ b/docs/wiki/02_how_to_use.md @@ -0,0 +1,105 @@ +# πŸ–₯️ How to Use + +This page walks through authenticating, ingesting, and parsing mail with the +built-in Gmail support. + +--- + +## πŸ” Authentication + +Create a credential store and an auth provider: + +```python +from mail_intake.auth import MailIntakeGoogleAuth +from mail_intake.credentials import PickleCredentialStore, RedisCredentialStore + +store = PickleCredentialStore(path="token.pickle") # local dev + +auth = MailIntakeGoogleAuth( + credentials_path="credentials.json", # your OAuth client file + store=store, + scopes=["https://www.googleapis.com/auth/gmail.readonly"], +) +``` + +> OAuth credentials come from the Google Cloud Console and are provided via +> file paths β€” never hard-code tokens or secrets in source. Once authorized, +> the token is persisted by the credential store and refreshed automatically. + +For distributed deployments, use Redis instead of pickle: + +```python +store = RedisCredentialStore(redis_client=redis_client) # production +``` + +--- + +## πŸ“₯ Ingesting messages + +Build an adapter and a reader, then iterate: + +```python +from mail_intake.ingestion import MailIntakeReader +from mail_intake.adapters import MailIntakeGmailAdapter + +adapter = MailIntakeGmailAdapter(auth_provider=auth) +reader = MailIntakeReader(adapter) + +for message in reader.iter_messages("from:recruiter@example.com"): + print(message.subject, message.from_email, message.timestamp) +``` + +Access the full model: + +```python +message.message_id # provider id +message.thread_id +message.body_text # plain-text body +message.raw_headers # unmodified headers dict +``` + +--- + +## πŸ”– Ingesting threads + +```python +for thread in reader.iter_threads("subject:Interview"): + print(thread.normalized_subject) + print(thread.participants) + print(len(thread.messages)) + print(thread.last_activity_at) +``` + +`MailIntakeThread` aggregates its messages, participants, and last activity. + +--- + +## πŸ§ͺ Parsers + +Parsers normalize provider payloads and are used by the reader internally. +They are also importable on their own: + +```python +from mail_intake.parsers import extract_body, parse_headers, normalize_subject +``` + +- `extract_body(...)` β€” plain-text body extraction. +- `parse_headers(...)` β€” structured header parsing. +- `extract_sender(...)` β€” sender email/name extraction. +- `normalize_subject(...)` β€” subject normalization for threading. + +--- + +## βœ… Checklist + +1. Provide OAuth credentials via a file path and a credential store. +2. Build the `MailIntakeGoogleAuth` provider with the Gmail read-only scope. +3. Wrap the adapter in a `MailIntakeReader`. +4. Consume `iter_messages` / `iter_threads`; never call provider APIs directly. + +--- + +## πŸ“š Read Next + +- [Overview](01_overview.md) β€” layers and domain models. +- [Extending Mail Intake](03_extending.md) β€” custom providers and stores. \ No newline at end of file diff --git a/docs/wiki/03_extending.md b/docs/wiki/03_extending.md new file mode 100644 index 0000000..e9bf6e6 --- /dev/null +++ b/docs/wiki/03_extending.md @@ -0,0 +1,106 @@ +# 🧩 Extending Mail Intake + +Mail Intake is designed to be extended through its **public contracts**. +Implement your own adapter, auth provider, or credential store to support a +new provider or storage backend. + +--- + +## πŸ“¬ Custom adapters + +Subclass `MailIntakeAdapter` to integrate a new provider. Adapters perform +read-only transport and return provider-native payloads: + +```python +from mail_intake.adapters import MailIntakeAdapter + +class ExchangeAdapter(MailIntakeAdapter): + def __init__(self, auth_provider): + self._auth = auth_provider + + def fetch_messages(self, query): + # call the provider API, return native payloads + ... + + def fetch_threads(self, query): + ... +``` + +> **Do not** subclass built-in adapters like `MailIntakeGmailAdapter` β€” they +> are reference implementations and may change internally without notice. + +--- + +## πŸ” Custom auth providers + +Subclass `MailIntakeAuthProvider[T]` to own a different credential flow: + +```python +from mail_intake.auth import MailIntakeAuthProvider + +class ExchangeAuth(MailIntakeAuthProvider[exchange_credentials]): + def get_credentials(self): + return self._store.load() + + def refresh(self): + ... +``` + +Auth providers remain decoupled from adapter logic β€” they only manage +credentials. + +--- + +## πŸ—„οΈ Custom credential stores + +Implement the `CredentialStore[T]` contract for a new persistence backend: + +```python +from mail_intake.credentials import CredentialStore + +class S3CredentialStore(CredentialStore): + def save(self, credentials): + ... + + def load(self): + ... + + def delete(self): + ... +``` + +The store abstraction keeps tokens out of config and rotates safely. + +--- + +## πŸ§ͺ Wiring a custom backend + +```python +from mail_intake.ingestion import MailIntakeReader + +auth = ExchangeAuth(store=S3CredentialStore(...)) +adapter = ExchangeAdapter(auth_provider=auth) +reader = MailIntakeReader(adapter) + +for message in reader.iter_messages("query"): + print(message.subject) +``` + +The reader only depends on the adapter contract, so the rest of the pipeline +keeps working unchanged. + +--- + +## βœ… Extension checklist + +1. Implement the **public contract** β€” never subclass built-in adapters. +2. Keep transport in the adapter, parsing in parsers, auth in the provider. +3. Return the provider-native payload and let parsers normalize it. +4. Inject dependencies explicitly β€” no global state or env reads. + +--- + +## πŸ“š Read Next + +- [How to Use](02_how_to_use.md) β€” the built-in Gmail flow. +- [Development](04_development.md) β€” running tests and docs. \ No newline at end of file diff --git a/docs/wiki/04_development.md b/docs/wiki/04_development.md new file mode 100644 index 0000000..b55c933 --- /dev/null +++ b/docs/wiki/04_development.md @@ -0,0 +1,88 @@ +# πŸ› οΈ Development + +Working on `mail-intake` itself. + +--- + +## πŸ“‚ Repository layout + +| Path | Purpose | +|---|---| +| `mail_intake/` | The library package (adapters, auth, credentials, parsers, ingestion, models) | +| `mail_intake/*.pyi` | Type stubs kept in sync with implementations | +| `tests/` | Unit and integration tests (mock transports, no live mail) | +| `docs/lib/` | Generated library reference (docforge, flat layout) | +| `docs/mcp/` | Machine-readable bundle served by the MCP server | +| `docs/wiki/` | This hand-written wiki | + +--- + +## πŸ”§ Setup + +```bash +python -m venv .venv +.venv/Scripts/pip install -e ".[dev]" +``` + +> OAuth credential files (`credentials*.json`, `token.pickle`, +> `client_secret_*.json`) are gitignored β€” keep them out of the repository. + +--- + +## πŸ§ͺ Tests + +Run the suite (no network or live Gmail required): + +```bash +.venv/Scripts/pytest +``` + +Coverage spans ingestion flows, credential stores, parsers, and auth against +mock providers. + +--- + +## βœ… Quality gates + +The CI quality gate runs, matching the Drone pipeline: + +```bash +.venv/Scripts/black --check . +.venv/Scripts/ruff check . +.venv/Scripts/mypy +.venv/Scripts/pytest +``` + +--- + +## πŸ“ Building documentation (docforge) + +The site is generated by [`docforge`](https://git.aetoskia.com/aetos/doc-forge) +and served per kind under `site/{kind}`: + +```bash +doc-forge build \ + --mkdocs --mcp --wiki \ + --module-is-source --module mail_intake \ + --site-name "Mail Intake" +``` + +- `--module-is-source` renders the flat `docs/lib/` layout (no nesting under + `mail_intake/`), matching `docforge.nav.yml` and `docs/mkdocs.lib.yml`. +- `--mcp` regenerates the structured bundle in `docs/mcp/`. +- `--wiki` builds this wiki. + +Preview locally: + +```bash +doc-forge serve --lib +doc-forge serve --wiki +doc-forge serve --mcp +``` + +--- + +## πŸ“š Read Next + +- [Extending Mail Intake](03_extending.md) β€” custom adapters and stores. +- [Overview](01_overview.md) β€” the core architecture. \ No newline at end of file diff --git a/docs/wiki/index.md b/docs/wiki/index.md new file mode 100644 index 0000000..27c3a64 --- /dev/null +++ b/docs/wiki/index.md @@ -0,0 +1,71 @@ +# πŸ“¬ Mail Intake β€” Provider-Agnostic Email Ingestion + +`Mail Intake` is a contract-first, read-only email ingestion framework. It +pulls mail from external providers (such as Gmail), parses and normalizes it +into clean, provider-agnostic domain models β€” ready to persist, index, or +analyze downstream. + +> **Doc model:** this wiki is written for humans β€” how‑to guides and extension +> recipes. The authoritative API contracts live in the code (GSDFC docstrings) +> and the machine‑readable bundle under `docs/mcp/`. + +--- + +## πŸš€ Key Features + +* πŸ“¬ **Read-only ingestion** β€” never mutates provider state +* 🧩 **Contract-first layers** β€” adapters, parsers, and readers separated +* βœ‰οΈ **Provider-agnostic models** β€” `MailIntakeMessage` / `MailIntakeThread` + have no provider internals +* πŸ” **Extensible auth** β€” pluggable auth providers and credential stores + (pickle for dev, Redis for production) +* πŸ§ͺ **Deterministic & testable** β€” no implicit global state or env reads +* πŸ“Š **Gmail support** β€” reference adapter built on the official Google APIs + +--- + +## ⚑ Quick Start + +```python +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) +``` + +--- + +## πŸ“ Documentation Structure + +| Section | What you'll find | +|---|---| +| [Overview](01_overview.md) | Layers, domain models, and design guarantees | +| [How to Use](02_how_to_use.md) | Gmail ingestion, parsing, and credential stores | +| [Extending Mail Intake](03_extending.md) | Custom adapters, auth providers, stores | +| [Development](04_development.md) | Setup, tests, and regenerating docs | + +--- + +## πŸ”— Related Resources + +* **Source Code:** [Gitea Repository](https://git.aetoskia.com/aetos/mail-intake) +* **Internal PyPI:** [pip.aetoskia.com/simple/mail-intake](https://pip.aetoskia.com/simple/mail-intake) +* **CI:** Builds and publishes tagged releases, gated on black / ruff / mypy / pytest. + +--- + +Β© Aetoskia Internal β€” `mail-intake` 0.0.2 \ No newline at end of file