Skip to main content

Email sending provider

@template-harness/email is a small server-side package for submitting one transactional email through Resend. It does not start a service, read process environment variables, consume SQS messages, or choose a deployment target. A future Lambda, edge function, or other consumer reads its own configuration and passes it explicitly to createResendEmailSender.

Configuration​

The process that sends email needs these private values:

VariablePurpose
RESEND_API_KEYResend API key with sending access, scoped to the sending domain where possible.
EMAIL_FROMSender address, optionally with a display name, such as Bookygram <mail@example.com>.

Store both values in the deployment platform's secret store. Do not place them in browser-visible configuration or commit them to an environment file. The current Fastify API does not use either setting, so it does not require them at startup.

Before deploying a sender, add and verify the domain used by EMAIL_FROM in Resend. Resend accepts a send request before it reaches an inbox; a returned email ID means the provider accepted the request, not that the recipient has received it.

Sending a message​

import { createResendEmailSender } from "@template-harness/email";

const sender = createResendEmailSender({
apiKey: process.env.RESEND_API_KEY ?? "",
from: process.env.EMAIL_FROM ?? "",
});

const result = await sender.send({
to: "reader@example.com",
subject: "Welcome",
text: "Thanks for joining.",
idempotencyKey: "welcome-user/user-123",
});

console.log(result.id);

Every request needs an idempotency key from 1 through 256 characters. Reuse the same key and message content when retrying the same logical email. Resend keeps the key for 24 hours, so a delivery runtime that retries beyond that window must provide its own duplicate-prevention policy.

The package returns a safe failure when Resend rejects or cannot acknowledge a request. It does not log credentials, recipients, subjects, content, or raw provider errors.

Relation to SQS​

The API can already submit opaque bodies to its semantic email queue. This package does not define that body, consume a queue, or decide acknowledgement, retry, or dead-letter behavior. Those choices belong to the future feature and delivery runtime that will send the emails.

See SQS job boundary for the current producer contract.