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

Scaleway

Send email through Scaleway Transactional Email with the @effect-kit/emails/scaleway Layer.

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

Installation

npm install @effect-kit/emails effect @scaleway/sdk-tem@2.16.3 @scaleway/sdk-client@2.16.0

Both packages are pinned peers and optional until you import this subpath.

Setup

Scaleway.layerConfig() reads these variables:

VariableRequiredValue
SCW_ACCESS_KEYyesAccess key
SCW_SECRET_KEYyesSecret key
SCW_PROJECT_IDyesProject UUID
SCW_REGIONyesfr-par

Example (Sending a Message With Scaleway Transactional Email)

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

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

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

.(.(.()));

Use a from address your Scaleway Transactional Email account is allowed to send from.

Options

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

Prop

Type

Capabilities

Scaleway Transactional Email reports this in email.capabilities:

TextHTMLBothSender nameCcBccReply-toHeadersAttachmentsInline imagesIdempotency
yesyesyesyesyesyesmultipleyesyesnono

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

  • An attachment with a contentId (feature inlineAttachments).
  • An idempotencyKey (feature idempotency).

Idempotency

Not supported. A key fails with UnsupportedFeatureError before sending.

Provider notes

  • fr-par is the only accepted region.
  • The owned client uses the global fetch as its HTTP client. Scaleway has no inline image support here, so a contentId fails before sending with feature inlineAttachments.
  • Scaleway always receives both bodies. A missing text or html is sent as an empty string.
  • The receipt has one reference per email id Scaleway returns.

Using your own client

layerClient takes any object with createEmail(message, { signal }), which a Scaleway Temv1alpha1.API has. Its options are required, because they carry projectId and region.

Example (Borrowing a Scaleway Transactional Email Client)

import { createAdvancedClient, withProfile } from "@scaleway/sdk-client";
import { Temv1alpha1 } from "@scaleway/sdk-tem";
import * as Scaleway from "@effect-kit/emails/scaleway";

const client = createAdvancedClient(
  withProfile({ accessKey: "SCWFAKEACCESSKEY", secretKey: "fake-secret" }),
);

const EmailLive = Scaleway.layerClient(new Temv1alpha1.API(client), {
  projectId: "11111111-1111-4111-8111-111111111111",
  region: "fr-par",
});

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: "scaleway" 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 secret key is not printable ASCII without spaces.
projectIdThe project id is not a UUID.
regionThe region is not fr-par.
accessKeyThe access key has characters other than letters and digits.
credentialsThe SDK client could not be created from the keys.
Scaleway failureReason
SDK QuotasExceededErrorQuotaExceededError
SDK AbortErrorTransportError

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".