astro-mailkite
v0.1.0
Published
MailKite for Astro — receive inbound email as a signed webhook route in your Astro app, and send over your verified domain.
Maintainers
Readme
What it does
mailkite() injects a POST /api/mailkite/inbound endpoint into your Astro project. When mail
arrives at any address on your verified domain, MailKite POSTs a signed email.received event
there; the integration verifies the x-mailkite-signature header (HMAC-SHA256, no network call)
and hands the event to your handler module — src/mailkite.ts by default. It also exports
sendEmail() and the webhook reply helpers so an auto-reply bot is a one-file affair.
Install
npx astro add mailkitewon't find this package (third-party integration names don't auto-resolve) — install it manually:
npm install astro-mailkite// astro.config.mjs
import { defineConfig } from 'astro/config';
import node from '@astrojs/node';
import mailkite from 'astro-mailkite';
export default defineConfig({
adapter: node({ mode: 'standalone' }), // any SSR adapter: node, cloudflare, vercel…
integrations: [mailkite()],
});SSR required. The inbound endpoint is an on-demand route, so your project needs an adapter
(npx astro add node, cloudflare, or vercel). A fully static build cannot receive webhooks —
the integration fails the build with a clear error if no adapter is configured.
Receive email — an auto-reply bot in one file
Create src/mailkite.ts; its default export handles every verified inbound email:
// src/mailkite.ts
import { sendEmail, replyOk } from 'astro-mailkite';
import type { MailKiteInboundHandler } from 'astro-mailkite';
const handler: MailKiteInboundHandler = async (event) => {
const m = event.message;
if (event.type !== 'email.received' || !m) return replyOk();
await sendEmail({
from: '[email protected]', // an address on your verified domain
to: m.from,
subject: `Re: ${m.subject ?? 'your email'}`,
inReplyTo: m.messageId,
text: 'Thanks — got your message. A human will follow up soon.',
});
return replyOk();
};
export default handler;Point your MailKite domain webhook at https://your-site.com/api/mailkite/inbound
(dashboard → domain → Webhooks, or mk.setWebhook(...) from the mailkite SDK).
Your handler can return:
| Return value | Response sent to MailKite |
| --- | --- |
| undefined / void | replyOk() — acknowledge |
| a string — use replyOk(), replySpam(), replyDrop(), replyBlockSender() | sent verbatim (control-mode replies act on the message) |
| a plain object | JSON-serialized |
| a Response | returned as-is |
| a thrown error | 500 — MailKite retries the delivery |
No src/mailkite.ts yet? Deliveries are still verified, logged, and acknowledged — nothing is lost.
Send email
sendEmail() is a thin wrapper over the mailkite SDK's
send() that reads MAILKITE_API_KEY from the environment. Use it anywhere server-side —
handlers, Astro actions, API routes:
import { sendEmail } from 'astro-mailkite';
const { id, status } = await sendEmail({
from: '[email protected]',
to: '[email protected]',
subject: 'Your invoice #1042',
html: '<p>Thanks! Receipt attached.</p>',
});Need the full SDK surface (domains, templates, routes, broadcasts…)? Use mailkite directly —
it's already a dependency.
Environment variables
| Variable | Used by | Required | Where to get it |
| --- | --- | --- | --- |
| MAILKITE_WEBHOOK_SECRET | inbound endpoint (signature verification) | for receiving | dashboard → Webhooks |
| MAILKITE_API_KEY | sendEmail() | for sending | dashboard → API keys |
Resolution order at runtime: Cloudflare runtime bindings (locals.runtime.env) →
process.env (node/vercel) → import.meta.env (bundled .env files).
Options
mailkite({
inboundPath: '/api/mailkite/inbound', // route pattern for the injected endpoint
handler: 'src/mailkite.ts', // module whose default export handles inbound email
})| Option | Default | Notes |
| --- | --- | --- |
| inboundPath | /api/mailkite/inbound | Injected as an on-demand (prerender: false) POST route. |
| handler | src/mailkite.ts | Also probes .js/.mts/.mjs. An explicitly set path that doesn't exist fails the build. |
License
MIT © MailKite
