Destination
An Account models IMAP and SMTP capability independently. Connect succeeds when IMAP verifies; an SMTP failure is recorded rather than fatal, surfaced on the accounts list, re-checkable on demand, and gates sending until it clears.
Resolved answers fold back into Connect and store a mail account's acceptance criteria (connect behaviour) and Reply within a conversation's (send gating). This map produces no code itself.
Motivation, concretely: a real T-Online mailbox flagged for outbound spam authenticates fine over IMAP (logs in, lists 10 folders) but returns 535 Authentication rejected over SMTP. _verify requires both, so that account cannot be connected at all and its mail cannot be read — a sending problem taking down reading.
Notes
Domain: account connection and verification. Relevant code: src/mailchat/accounts/{service,models,routes,templates}.py, src/mailchat/sync/{imap_client,smtp_client}.py, src/mailchat/shared/db.py.
_verify (accounts/service.py:103) proves IMAP then SMTP in one worker thread and aborts the whole connect on either failure; connect() only creates the Account if it returns. Account (accounts/models.py:11) has no capability columns today.
There is no migration tooling — init_db is Base.metadata.create_all (shared/db.py:35), which creates missing tables but never alters existing ones. Any new column therefore needs an explicit story for databases that already exist.
Prior art for a per-account, user-resolved setting: sent_folder — nullable, unset until the user acts, with a Choose sent folder button on the accounts list that re-lists from the server. An SMTP re-check control should probably mirror it.
Stack decisions from Spec: MailChat MVP — email-as-chat are locked — don't reopen them. Use /grilling per ticket.
Decisions so far
Not yet specified
- Whether capability state should also be updated by sync-time failures rather than only explicit checks. Leans toward the health model ruled out below, but the boundary isn't sharp enough to ticket.
- How a re-check interacts with the sync worker's poll loop — shared connection or separate, and whether a failed poll counts as a capability signal.
- Whether provider-specific diagnosis (e.g. "T-Online blocks SMTP for mailboxes flagged for spam") belongs in the error surface at all, or whether raw server text is enough.
Out of scope
- A general connection-health model — ongoing health derived from sync failures, credential expiry, re-auth prompts, retry/backoff policy. Considered and consciously set aside when this destination was named; returns only as a fresh effort.
- Everything Spec: MailChat MVP — email-as-chat already ruled out (Gmail OAuth, WebSocket push, search/attachments, multi-user auth, native packaging, a generic JSON API, the deployment target).
Destination
An
Accountmodels IMAP and SMTP capability independently. Connect succeeds when IMAP verifies; an SMTP failure is recorded rather than fatal, surfaced on the accounts list, re-checkable on demand, and gates sending until it clears.Resolved answers fold back into Connect and store a mail account's acceptance criteria (connect behaviour) and Reply within a conversation's (send gating). This map produces no code itself.
Motivation, concretely: a real T-Online mailbox flagged for outbound spam authenticates fine over IMAP (logs in, lists 10 folders) but returns
535 Authentication rejectedover SMTP._verifyrequires both, so that account cannot be connected at all and its mail cannot be read — a sending problem taking down reading.Notes
Domain: account connection and verification. Relevant code:
src/mailchat/accounts/{service,models,routes,templates}.py,src/mailchat/sync/{imap_client,smtp_client}.py,src/mailchat/shared/db.py._verify(accounts/service.py:103) proves IMAP then SMTP in one worker thread and aborts the whole connect on either failure;connect()only creates theAccountif it returns.Account(accounts/models.py:11) has no capability columns today.There is no migration tooling —
init_dbisBase.metadata.create_all(shared/db.py:35), which creates missing tables but never alters existing ones. Any new column therefore needs an explicit story for databases that already exist.Prior art for a per-account, user-resolved setting:
sent_folder— nullable, unset until the user acts, with aChoose sent folderbutton on the accounts list that re-lists from the server. An SMTP re-check control should probably mirror it.Stack decisions from Spec: MailChat MVP — email-as-chat are locked — don't reopen them. Use
/grillingper ticket.Decisions so far
Not yet specified
Out of scope