Documentation for agents: an index at /llms.txt, every docs page in one file at /llms-full.txt, and Markdown for any docs page by adding .md to its URL.

Effect KitEmails

Capabilities

Inspect what a provider supports and understand the checks that run before any request is sent.

Each provider layer declares what it can send. email.send compares your message against those capabilities before it calls the provider, so an unsupported field fails with no network request.

Example (Failing Before the Request)

import {  } from "effect";
import {  } from "@effect-kit/emails";
import * as  from "@effect-kit/emails/mailersend";

const  = .(function* () {
  const  = yield* ;
  return yield* .({
    : "billing@example.com",
    : "ada@example.com",
    : "Invoice",
    : "Your invoice is attached.",
    : [
      {
        : "invoice.pdf",
        : "application/pdf",
        : new ([37, 80, 68, 70]),
      },
    ],
  });
}).(
  .("EmailError", "UnsupportedFeatureError", () =>
    .(`unsupported: ${.}`),
  ),
  .(.()),
);
// Output: "unsupported: attachments"

The failure is an EmailError with acceptance: "notSubmitted" and an UnsupportedFeatureError reason. Its feature names the first check that failed.

Reading capabilities

The service exposes email.provider and email.capabilities. Read them to adapt a message before sending.

Example (Passing a Key Only When Supported)

import {  } from "effect";
import {  } from "@effect-kit/emails";

const  = .(function* () {
  const  = yield* ;
  const {  } = .;
  return yield* .(
    {
      : "hello@example.com",
      : "ada@example.com",
      : "Welcome",
      : "Your account is ready.",
    },
    . === "unsupported" ? {} : { : "welcome/account-123" },
  );
});

EmailCapabilities has eleven fields.

FieldTypeMeaning
textbooleanAccepts a text body.
htmlbooleanAccepts an html body.
htmlAndTextbooleanAccepts both bodies in one message.
senderNamebooleanAccepts a display name on from.
ccbooleanAccepts cc.
bccbooleanAccepts bcc.
replyTo"none" | "single" | "multiple"How many reply-to addresses are allowed.
headersbooleanAccepts custom headers.
attachmentsbooleanAccepts attachments.
inlineAttachmentsbooleanAccepts attachments with a contentId.
idempotency{ mode }"unsupported", "replay" or "reject", with an optional retention.

The per-provider values are in the capability matrix and in Capabilities reference.

Check order

The core runs the checks in this order and reports the first failure. Only one feature is named per attempt, so fixing one field can surface the next.

OrderfeatureFails when
1texttext is set and the provider has no text bodies.
2htmlhtml is set and the provider has no HTML bodies.
3htmlAndTextBoth are set and the provider cannot take both.
4senderNamefrom has a name.
5cccc is set.
6bccbcc is set.
7replyToreplyTo is set and replyTo is "none".
8multipleReplyToMore than one reply-to address and replyTo is "single".
9headersAny custom header is set.
10attachmentsAny attachment is set.
11inlineAttachmentsAn attachment has a contentId.
12idempotencyAn idempotencyKey is passed and the mode is "unsupported".

Provider checks come after

Some providers also reject a field for reasons that are not capability flags, such as a malformed idempotency key or an inline contentId that Lettermint needs to contain @. Those fail with InvalidMessageError, still with acceptance: "notSubmitted".