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

eusend

Send email through eusend with the @effect-kit/emails/eusend Layer.

The @effect-kit/emails/eusend subpath sends messages through eusend and provides the Email service.

Installation

npm install @effect-kit/emails effect @eusend_dev/sdk@0.19.0

The SDK is a pinned optional peer. It is needed only when you import this subpath.

Setup

Eusend.layerConfig() reads these variables:

VariableRequiredValue
EUSEND_API_KEYyesAPI key

Example (Sending a Message With eusend)

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

const  = .().(
  .(.(.())),
);

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

.(.(.()));

Use a from address your eusend account is allowed to send from.

Options

Eusend.layer takes these options. layerConfig builds the same object from a Config.

Prop

Type

Capabilities

eusend reports this in email.capabilities:

TextHTMLBothSender nameCcBccReply-toHeadersAttachmentsInline imagesIdempotency
yesyesyesyesyesyesmultipleyesyesyesreplay

Every message feature is supported, so no message fails the capability check.

Idempotency

Mode replay, with no retention declared. The package passes the key to eusend as the SDK's idempotencyKey option.

The key must be 1 to 255 printable ASCII characters and not blank, otherwise the send fails with InvalidMessageError (path idempotencyKey) and acceptance: "notSubmitted". A CONFLICT error from eusend fails with IdempotencyConflictError.

Example (Sending With an Idempotency Key)

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

const  = .(function* () {
  const  = yield* ;
  return yield* .(
    {
      : "hello@example.com",
      : "ada@example.com",
      : "Welcome",
      : "Your account is ready.",
    },
    { : "welcome-ada-2026-10-29" },
  );
});

Provider notes

The receipt's requestId comes from the x-request-id response header when eusend returns one.

Using your own client

layerClient takes any object with emails.send(message, { idempotencyKey }), which an Eusend client has. options is optional.

Example (Borrowing a eusend Client)

import { Eusend as EusendSdk } from "@eusend_dev/sdk";
import * as Eusend from "@effect-kit/emails/eusend";

const client = new EusendSdk("fake-key");

const EmailLive = Eusend.layerClient(client);

You own a borrowed client. The Layer never closes it, and the client keeps its own retry, timeout and logging policy.

Errors

ProviderConfigurationError carries provider: "eusend" and a field naming the bad option. Layer construction fails with it, and layerClient fails with it for the client options.

fieldRaised when
timeoutThe timeout is not finite and positive.
tokenThe API key is not printable ASCII without spaces.
baseUrlThe URL is not http or https, or has credentials, a query or a fragment.
eusend error nameReason
UNAUTHORIZEDAuthenticationError
FORBIDDEN, DOMAIN_NOT_VERIFIED, SENDING_SUSPENDED, ACCOUNT_RESTRICTED, WORKSPACE_INACTIVE, SENDER_NOT_PERMITTEDPermissionDeniedError
MONTHLY_LIMIT_EXCEEDED, DAILY_LIMIT_EXCEEDED, PLAN_LIMIT_EXCEEDEDQuotaExceededError
ALL_SUPPRESSED, RECIPIENT_DOMAIN_UNDELIVERABLEMessageRejectedError
RATE_LIMITEDRateLimitedError
CONFLICTIdempotencyConflictError
application_errorTransportError
SERVICE_PAUSED, ATTACHMENT_STORAGE_ERROR, INTERNAL_ERRORProviderUnavailableError

The error name is kept as providerCode and its status as statusCode. Names not listed use the status with the shared mapping.