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

SendGrid

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

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

Installation

npm install @effect-kit/emails effect @sendgrid/mail@8.1.6

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

Setup

SendGrid.layerConfig() reads these variables:

VariableRequiredValue
SENDGRID_API_KEYyesAPI key

Example (Sending a Message With SendGrid)

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

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

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

.(.(.()));

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

Options

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

Prop

Type

Capabilities

SendGrid reports this in email.capabilities:

TextHTMLBothSender nameCcBccReply-toHeadersAttachmentsInline imagesIdempotency
yesyesyesyesyesyesoneyesyesyesno

These fail with UnsupportedFeatureError and acceptance: "notSubmitted" before any request:

  • More than one replyTo address (feature multipleReplyTo).
  • An idempotencyKey (feature idempotency).

Idempotency

Not supported. A key fails with UnsupportedFeatureError before sending.

Provider notes

  • SendGrid takes one reply-to address. A second replyTo address fails before sending with feature multipleReplyTo.
  • A send is accepted only on an HTTP 202 response. Any other success status fails with UnexpectedResponseError. The receipt's reference is the x-message-id response header, and references is empty when the header is missing.

Using your own client

layerClient takes any object with send(message), which the @sendgrid/mail mail service has. options is optional.

Example (Borrowing a SendGrid Client)

import sgMail from "@sendgrid/mail";
import * as SendGrid from "@effect-kit/emails/sendgrid";

sgMail.setApiKey("SG.fake_key");

const EmailLive = SendGrid.layerClient(sgMail);

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: "sendgrid" 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.
SendGrid failureReason
SDK error with a numeric codeMapped from that code as an HTTP status

Any other HTTP status uses the shared mapping: 401 is AuthenticationError, 403 PermissionDeniedError, 429 RateLimitedError, 400 and 422 InvalidMessageError, 5xx ProviderUnavailableError, and anything else ProviderError. acceptance is rejected for a 4xx status other than 409 and unknown otherwise. See Errors. A network failure with no status is TransportError, and ETIMEDOUT or ECONNABORTED is TimeoutError, both with acceptance: "unknown".