Guide
How to send email with Astro
Send email from an Astro server endpoint with fetch - no SDK needed.
In short
Create a Sendpository account, verify your domain, put your API key inSENDPOSITORY_API_KEY, and send with the code below - one HTTPS request per email, from server-side code only.1. Verify your sending domain
Add your domain in the dashboard and publish the three DNS records it shows - SPF and a bounce record on an sp. subdomain, and a DKIM key on your apex. Your existing records are never edited. Verification usually lands in a few minutes, and you can set up the code below while you wait.
2. Create a key
Create an API key with the sending permission. It is shown once, so put it straight into your secrets. Put SENDPOSITORY_API_KEY in .env (no PUBLIC_ prefix) so Astro keeps it on the server and reads it through import.meta.env.
3. Send an email
// src/pages/api/signup.ts
import type { APIRoute } from "astro";
// Endpoints run per request only when they are not prerendered.
export const prerender = false;
export const POST: APIRoute = async ({ request }) => {
const { email } = await request.json();
const r = await fetch("https://api.sendpository.com/v1/emails", {
method: "POST",
headers: {
Authorization: `Bearer ${import.meta.env.SENDPOSITORY_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
from: "Your App <hello@mail.yourdomain.com>",
to: [email],
subject: "Confirm your email",
html: "<p>Click the link to confirm.</p>",
}),
});
const data = await r.json();
if (!r.ok) return new Response(JSON.stringify({ error: data.error.message }), { status: 502 });
return new Response(JSON.stringify({ id: data.id }), { status: 200 });
};A success returns { "id": "..." } - the message’s id for looking it up later. A failure returns { "error": { "type", "message" } } with a 4xx or 5xx status.
Where the send belongs
In a server endpoint or an Astro Action, never in a component's frontmatter that runs at build time - a prerendered page would send once, during the build, and never again.
Call it from your form with fetch (or a plain form POST), and return as soon as the API answers; the send itself takes one request.
Testing it
- Run `astro dev` with a test key in .env and point the from address at a domain you have verified, so a real send can be checked in the logs.
- Rate-limit the endpoint if the form is public. A signup or contact form is the first thing a spammer finds.
Things to know
- The endpoint needs an adapter (Node, Vercel, Netlify, Cloudflare) and must not be prerendered - a static build has no server to hold the key.
- Never prefix the key with PUBLIC_: Astro inlines PUBLIC_ variables into the browser bundle.
Questions
Can I send email from a static Astro site?
Not from the static output itself - there is no server to keep the API key secret. Add an adapter and mark the sending endpoint `prerender = false`, or post the form to a serverless function on your host.
How do I send email with Astro?
Verify your sending domain, create an API key, put it in an environment variable, and POST the message as JSON to https://api.sendpository.com/v1/emails from server-side Astro code. The example on this page runs as written once the domain is verified.
Can I send email with Astro without SMTP?
Yes. This is plain HTTPS, so Astro needs no mail library and no SMTP port - which matters on hosts that block outbound 25 and 587. Failures come back as a status code on the call instead of as a bounce message hours later.
More guides
Send email with Node.js
Send email from any Node.js app with the typed SDK or plain fetch.
Send email with Next.js
Send transactional email from a Next.js App Router server action or route handler.
Send your first email in minutes
6,000 emails a month (up to 200 a day), free forever. No card needed.