import type { ValidatedMailMessage } from "./message.js"; /** * The seam between Ekklesia's mail contract and whatever actually delivers a message. * * This is the **portability boundary made executable**, exactly as `StorageProvider` is for object * storage. Everything above it — the message contract, validation, the sender policy, diagnostics — * is provider-agnostic and would be identical under a future standalone host. Everything below it is * one implementation (`createSmtpMailProvider`) that could be replaced by a provider HTTP API * without any calling feature changing a line. * * It speaks only in **already-validated** messages: recipients, subject, and bodies have been * checked and normalized by `validateMailMessage` before anything reaches here, so a provider never * re-implements those rules and two providers can never disagree about what a caller may send. * * Deliberately absent: any way to ask for the sender, the host, the port, or a credential. A * provider is given configuration at construction and exposes none of it afterwards. */ export interface MailProvider { /** * Sends one message. Resolves with a provider message id when the service accepted it. * * **This is a single bounded attempt, not a delivery guarantee.** Acceptance means the next hop * took responsibility, not that anyone received anything — and a failure after the message data * has been transmitted is genuinely ambiguous, because the server may have accepted it and only * the acknowledgement was lost. Nothing here retries; see ADR 0037. */ send(message: ValidatedMailMessage): Promise; /** * Opens a connection and, when credentials are configured, authenticates — then closes, **without * sending anything**. For diagnostics only. * * Its result is never persisted and never influences module lifecycle state: a mail service being * briefly unreachable is an operational condition, not an administrative decision. */ verify(): Promise; /** Releases provider connections. Called once, during API shutdown. */ close(): Promise; } export interface MailSendResult { /** * The provider's own identifier for the accepted message, when it supplies one. * * Safe to log: it identifies a message in the provider's records and contains no recipient, no * subject, and no body. It is deliberately the *only* thing about a sent message this contract * hands back, because a verification or reset email's contents are exactly what must not end up * in an operator's log (ADR 0037). */ readonly messageId?: string; }