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.0The SDK is a pinned optional peer. It is needed only when you import this subpath.
Setup
Eusend.layerConfig() reads these variables:
| Variable | Required | Value |
|---|---|---|
EUSEND_API_KEY | yes | API 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:
| Text | HTML | Both | Sender name | Cc | Bcc | Reply-to | Headers | Attachments | Inline images | Idempotency |
|---|---|---|---|---|---|---|---|---|---|---|
| yes | yes | yes | yes | yes | yes | multiple | yes | yes | yes | replay |
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.
field | Raised when |
|---|---|
timeout | The timeout is not finite and positive. |
token | The API key is not printable ASCII without spaces. |
baseUrl | The URL is not http or https, or has credentials, a query or a fragment. |
| eusend error name | Reason |
|---|---|
UNAUTHORIZED | AuthenticationError |
FORBIDDEN, DOMAIN_NOT_VERIFIED, SENDING_SUSPENDED, ACCOUNT_RESTRICTED, WORKSPACE_INACTIVE, SENDER_NOT_PERMITTED | PermissionDeniedError |
MONTHLY_LIMIT_EXCEEDED, DAILY_LIMIT_EXCEEDED, PLAN_LIMIT_EXCEEDED | QuotaExceededError |
ALL_SUPPRESSED, RECIPIENT_DOMAIN_UNDELIVERABLE | MessageRejectedError |
RATE_LIMITED | RateLimitedError |
CONFLICT | IdempotencyConflictError |
application_error | TransportError |
SERVICE_PAUSED, ATTACHMENT_STORAGE_ERROR, INTERNAL_ERROR | ProviderUnavailableError |
The error name is kept as providerCode and its status as statusCode. Names not listed use the status with the shared mapping.