Mailtrap
Send email through Mailtrap with the @effect-kit/emails/mailtrap Layer.
The @effect-kit/emails/mailtrap subpath sends messages through Mailtrap and provides the Email service.
Installation
npm install @effect-kit/emails effect mailtrap@5.0.0The SDK is a pinned optional peer. It is needed only when you import this subpath.
Setup
Mailtrap is the one provider whose layerConfig has no default Config. You pass one, so the package reads no variables by itself. The example below reads these:
| Variable | Value |
|---|---|
MAILTRAP_TOKEN | API token. The name is chosen in the example, the package reads none |
MAILTRAP_MODE | production or bulk. The name is chosen in the example |
Example (Sending a Message With Mailtrap)
import { , , , } from "effect";
import { } from "@effect-kit/emails";
import * as from "@effect-kit/emails/mailtrap";
const = .(
.({
: .("MAILTRAP_TOKEN"),
: .(["production", "bulk"], "MAILTRAP_MODE"),
}),
).(.(.(.())));
const = .(function* () {
const = yield* ;
return yield* .({
: "hello@example.com",
: "ada@example.com",
: "Welcome",
: "Your account is ready.",
});
});
.(.(.()));Use a from address your Mailtrap account is allowed to send from.
Options
Mailtrap.layer takes these options. layerConfig builds the same object from a Config.
Prop
Type
Capabilities
Mailtrap 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 | one | yes | yes | yes | no |
These fail with UnsupportedFeatureError and acceptance: "notSubmitted" before any request:
- More than one
replyToaddress (featuremultipleReplyTo). - An
idempotencyKey(featureidempotency).
Idempotency
Not supported. A key fails with UnsupportedFeatureError before sending.
Provider notes
modeselects the stream and changes the provider name on receipts and errors:mailtrapforproduction,mailtrap/bulkforbulk,mailtrap/sandboxforsandbox.sandboxdelivers to a Mailtrap test inbox and needsinboxId.productionandbulkreject aninboxId.- Mailtrap takes one reply-to address. A second
replyToaddress fails before sending with featuremultipleReplyTo. - The owned client's keep-alive agents are destroyed when the Layer's scope closes.
Using your own client
layerClient takes any object with send(message), which a MailtrapClient has. Its options are required, because they carry the mode that names the provider.
Example (Borrowing a Mailtrap Client)
import { MailtrapClient } from "mailtrap";
import * as Mailtrap from "@effect-kit/emails/mailtrap";
const client = new MailtrapClient({ token: "fake-token" });
const EmailLive = Mailtrap.layerClient(client, { mode: "production" });You own a borrowed client. The Layer never closes it, and the client keeps its own retry, timeout and logging policy. Pass the same mode you built the client for. The package does not inspect a borrowed client.
Errors
ProviderConfigurationError carries provider: "mailtrap" 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 token is not printable ASCII without spaces. |
mode | The mode is not production, sandbox or bulk. |
inboxId | Sandbox mode without a positive integer inbox id, or an inbox id in another mode. |
Send failures use the HTTP status with 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. A network failure with no status is TransportError, and ETIMEDOUT or ECONNABORTED is TimeoutError, both with acceptance: "unknown". See Errors.