Send SvelteKit email from the server file, not the component. Private env in, accepted ID out.
Queue transactional mail behind a form action or server route, return the accepted message ID, and handle the delivery result on a separate signed webhook path.
✓Import the key from $env/dynamic/private, never $env/public.
One request, complete trace
Request
POST /api/v1/emails
Authorization: Bearer aem_…
Idempotency-Key: welcome-8f21
{ "to": "[email protected]", "template": "welcome" }
202 Accepted
{ "id": "msg_7ca31", "status": "queued" }
[ 01 / 03 ]Integration shape
Let SvelteKit's file boundary protect the integration.
Use server routes and form actions
Use a form action for a page mutation or +server.ts for a focused API boundary; both can read private environment values.
Publish product events
Publish events after the server-side mutation succeeds, so flows follow trusted state instead of client activity.
Verify the webhook
A +server.ts route reading await request.text() before parsing.
[ 02 / 03 ]Server quickstart
Queue one email from SvelteKit +server.ts.
The server route protects the key and returns an accepted message ID while delivery continues independently.
Use a server route so private environment values never enter the client build.
export const POST: RequestHandler = async ({ request }) => {
const input = await request.json();
return fetch(EMAIL_URL, { method: "POST",
headers: authHeaders(`welcome-${input.userId}`),
body: JSON.stringify({ to: input.email, template: "welcome" }) });
};Accepted response
{ "id": "msg_7ca31", "status": "queued" }[ 03 / 03 ]Related
Keep building with SvelteKit
Questions people ask us
Give SvelteKit email a private, traceable path.
Queue the message from a server file and verify the event that reports delivery.