Skip to content

๐Ÿงฉ 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:

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:

1
2
3
4
5
6
7
8
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:

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

1
2
3
4
5
6
7
8
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.