Skip to content
Corven Email SDK
Esc
↑↓navigate↵open⌘Jpreview
On this page

Private submission capture

Capture bounded private request/outcome payloads with explicit permission and retention controls.

Use capturedEmailSenderLayer from @corven/email-sdk/capture only when your application is authorized to retain message payloads:

import { Effect, Layer } from "effect";
import { Email, emailLayer } from "@corven/email-sdk";
import type { EmailMessageInput } from "@corven/email-sdk";
import { capturedEmailSenderLayer, EmailSubmissionCapture } from "@corven/email-sdk/capture";
import { recordingSenderLayer } from "@corven/email-sdk/testing";

export const captureSyntheticSubmission = Effect.fnUntraced(function* captureSyntheticSubmission(
  message: EmailMessageInput,
) {
  const email = yield* Email;
  const capture = yield* EmailSubmissionCapture;
  const receipt = yield* email.send(message);
  const snapshot = yield* capture.snapshot;
  const purgedRecordCount = yield* capture.purgeRecords;

  return { purgedRecordCount, receipt, snapshot };
});

export const capturedSyntheticEmailLayer = emailLayer().pipe(
  Layer.provideMerge(
    capturedEmailSenderLayer(recordingSenderLayer, {
      capacity: 10,
      maxBytes: 1_048_576,
      privateData: "AuthorizePayloadCapture",
    }),
  ),
);

The example uses a recorder, so it does not contact a provider. In production, substitute the configured sender without changing the capture/query ownership.

Configure retention

Supply capacity, maxBytes and privateData: "AuthorizePayloadCapture". Retention is bounded by record count and UTF-8 bytes. Oversized or evicted data is reflected in truncated; the view is not a complete audit log.

EmailSubmissionCapture.snapshot returns records, retainedBytes, closed and truncated. Each record’s payloadJson is Redacted. Unwrap and decode it only in an explicitly authorized private path using the exported payload Schema; do not log it as a diagnostic shortcut.

Purge the visible view

purgeRecords removes visible records and returns the count removed. It does not securely erase copies already returned to callers, clear every private application store or reset duplicate-prevention evidence.

Keep sending and querying in the same Layer acquisition. Define access control and retention outside the SDK before replacing the synthetic sender with a real account. Use minimal observations when payloads are unnecessary.