@cfxlabsinc/b2b-services
    Preparing search index...
    EmailSendOutcome:
        | {
            reason: "NO_RECIPIENTS"
            | "NO_ACTIVE_TEMPLATE";
            sent: false;
            statusVariant: StoredEmailTemplate["statusVariant"];
        }
        | {
            reason: "IN_DOUBT";
            sent: false;
            statusVariant: StoredEmailTemplate["statusVariant"];
        }
        | {
            reason: "REJECTED";
            rejected: string[];
            sent: false;
            statusVariant: StoredEmailTemplate["statusVariant"];
        }
        | {
            alreadySent: string[];
            bodyText: string;
            contentHash: string;
            held: string[];
            recipients: string[];
            rejected: string[];
            sent: true;
            statusVariant: StoredEmailTemplate["statusVariant"];
            subject: string;
            templateKey: EmailTemplateKey;
            version: number;
        }

    What a send actually did. The skip arms are deterministic non-sends the caller may surface (the lambda logs them; admin sendTest reports them to the operator); the sent arm identifies the exact copy that went out, so an audit row can record it (emailTemplate.testSendRequested carries the content hash — EMAIL_TEMPLATES.md §4.6).

    Type Declaration

    • {
          reason: "NO_RECIPIENTS" | "NO_ACTIVE_TEMPLATE";
          sent: false;
          statusVariant: StoredEmailTemplate["statusVariant"];
      }
      • reason: "NO_RECIPIENTS" | "NO_ACTIVE_TEMPLATE"
      • sent: false
      • statusVariant: StoredEmailTemplate["statusVariant"]

        The variant the send looked up, so a skip can be recorded against it.

    • {
          reason: "IN_DOUBT";
          sent: false;
          statusVariant: StoredEmailTemplate["statusVariant"];
      }
      • reason: "IN_DOUBT"

        No recipient is known to be mailed, and another attempt holds the claim on at least one, so it may still be sending.

      • sent: false
      • statusVariant: StoredEmailTemplate["statusVariant"]
    • {
          reason: "REJECTED";
          rejected: string[];
          sent: false;
          statusVariant: StoredEmailTemplate["statusVariant"];
      }
      • reason: "REJECTED"

        SES refused every recipient's address. Any other refusal throws.

      • rejected: string[]
      • sent: false
      • statusVariant: StoredEmailTemplate["statusVariant"]
    • {
          alreadySent: string[];
          bodyText: string;
          contentHash: string;
          held: string[];
          recipients: string[];
          rejected: string[];
          sent: true;
          statusVariant: StoredEmailTemplate["statusVariant"];
          subject: string;
          templateKey: EmailTemplateKey;
          version: number;
      }
      • alreadySent: string[]

        Recipients an earlier attempt's send was accepted for.

      • bodyText: string

        Plain-text body of the first recipient, the Slack thread preview.

      • contentHash: string

        sha256 over the rendered version's subject + "\n" + body.

      • held: string[]

        Recipients another attempt holds, not mailed by this call. A caller that retries must not treat the send as complete while any remain.

      • recipients: string[]

        Deduped recipient emails SES accepted in this call.

      • rejected: string[]

        Recipients SES refused; the others were still mailed.

      • sent: true
      • statusVariant: StoredEmailTemplate["statusVariant"]
      • subject: string

        Subject rendered for the first recipient.

      • templateKey: EmailTemplateKey
      • version: number

        Human-facing version counter of the live template that rendered.