resend http api

This commit is contained in:
2026-02-24 23:29:41 +00:00
parent 98761e0692
commit e95c5de70d
3 changed files with 67 additions and 26 deletions
+21 -3
View File
@@ -11,14 +11,32 @@ type SendMailArgs = {
};
export async function sendMail({ template, subject, to, data, from }: SendMailArgs) {
const { transport, from: configuredFrom } = await getTransport();
const sender = from ?? configuredFrom ?? 'officerdev <no-reply@officer.dev>';
const result = await getTransport();
const sender = from ?? result.from ?? 'officerdev <no-reply@officer.dev>';
const theTemplate = templates[template];
const templated = theTemplate(data);
const emailHtml = await render(templated);
await transport.sendMail({ from: sender, to, subject, html: emailHtml });
if (result.type === 'resend') {
const res = await fetch('https://api.resend.com/emails', {
method: 'POST',
headers: {
'Authorization': `Bearer ${result.apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ from: sender, to, subject, html: emailHtml }),
});
if (!res.ok) {
const err = await res.json();
throw new Error(err.message ?? `Resend API error: ${res.status}`);
}
return;
}
await result.transport.sendMail({ from: sender, to, subject, html: emailHtml });
}
export { getTransport, templates };
export type { TransportResult } from './transport';
+12 -10
View File
@@ -21,9 +21,6 @@ let cachedTransport: Transporter | null = null;
let cachedConfigHash: string | null = null;
function buildTransportUrl(config: SmtpConfig): string {
if (config.provider === 'resend') {
return `smtps://resend:${config.apiKey}@smtp.resend.com:465`;
}
if (config.provider === 'mailhog') {
return `smtp://${config.host ?? 'localhost'}:${config.port ?? 1025}`;
}
@@ -32,10 +29,9 @@ function buildTransportUrl(config: SmtpConfig): string {
return `${protocol}://${auth}${config.host}:${config.port ?? 587}`;
}
type TransportResult = {
transport: Transporter;
from: string | null;
};
type SmtpTransport = { type: 'smtp'; transport: Transporter; from: string | null };
type ResendTransport = { type: 'resend'; apiKey: string; from: string };
export type TransportResult = SmtpTransport | ResendTransport;
export async function getTransport(): Promise<TransportResult> {
try {
@@ -44,14 +40,20 @@ export async function getTransport(): Promise<TransportResult> {
const settings = await file.json();
const smtp: SmtpConfig | undefined = settings.smtp;
if (smtp) {
const from = `${smtp.fromName} <${smtp.fromEmail}>`;
if (smtp.provider === 'resend') {
return { type: 'resend', apiKey: smtp.apiKey ?? '', from };
}
const hash = JSON.stringify(smtp);
if (cachedTransport && cachedConfigHash === hash) {
return { transport: cachedTransport, from: `${smtp.fromName} <${smtp.fromEmail}>` };
return { type: 'smtp', transport: cachedTransport, from };
}
const url = buildTransportUrl(smtp);
cachedTransport = createTransport(url);
cachedConfigHash = hash;
return { transport: cachedTransport, from: `${smtp.fromName} <${smtp.fromEmail}>` };
return { type: 'smtp', transport: cachedTransport, from };
}
}
} catch {
@@ -63,7 +65,7 @@ export async function getTransport(): Promise<TransportResult> {
cachedTransport = createTransport(MAIL_TRANSPORT);
cachedConfigHash = 'env';
}
return { transport: cachedTransport, from: null };
return { type: 'smtp', transport: cachedTransport, from: null };
}
throw new Error('No email transport configured');