Files
cfw-auth/src/email.ts
2026-06-10 02:27:02 -07:00

81 lines
1.9 KiB
TypeScript

import type { Env } from "./env";
export type AuthEmailKind = "verify-email" | "reset-password" | "email-otp" | "magic-link";
export interface AuthEmailInput {
kind: AuthEmailKind;
to: string;
url?: string;
otp?: string;
}
export interface EmailMessage {
to: string;
subject: string;
text: string;
}
export function buildAuthEmail(input: AuthEmailInput): EmailMessage {
if (input.kind === "email-otp") {
return {
to: input.to,
subject: "Your sign-in code",
text: `Your sign-in code is ${input.otp ?? ""}.`,
};
}
if (input.kind === "reset-password") {
return {
to: input.to,
subject: "Reset your password",
text: `Use this link to reset your password: ${input.url ?? ""}`,
};
}
if (input.kind === "magic-link") {
return {
to: input.to,
subject: "Sign in to your account",
text: `Use this link to sign in: ${input.url ?? ""}`,
};
}
return {
to: input.to,
subject: "Verify your email",
text: `Use this link to verify your email: ${input.url ?? ""}`,
};
}
export async function sendEmail(env: Env, message: EmailMessage): Promise<void> {
if (!env.MAIL_PROVIDER) {
throw new Error("MAIL_PROVIDER is not configured");
}
if (env.MAIL_PROVIDER !== "resend") {
throw new Error(`Unsupported MAIL_PROVIDER: ${env.MAIL_PROVIDER}`);
}
if (!env.RESEND_API_KEY || !env.MAIL_FROM) {
throw new Error("RESEND_API_KEY and MAIL_FROM are required for resend");
}
const response = await fetch("https://api.resend.com/emails", {
method: "POST",
headers: {
Authorization: `Bearer ${env.RESEND_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
from: env.MAIL_FROM,
to: message.to,
subject: message.subject,
text: message.text,
}),
});
if (!response.ok) {
throw new Error(`Email provider failed: ${response.status}`);
}
}