45 lines
1.6 KiB
TypeScript
45 lines
1.6 KiB
TypeScript
import 'server-only';
|
|
import { env } from '@/lib/env';
|
|
|
|
export type EmailMessage = { to: string; subject: string; html: string };
|
|
export type EmailResult = { id: string; provider: string };
|
|
|
|
export interface EmailProvider {
|
|
name: string;
|
|
send(message: EmailMessage): Promise<EmailResult>;
|
|
}
|
|
|
|
/** Default provider: no keys needed — logs the message and returns a synthetic id. */
|
|
export class LogProvider implements EmailProvider {
|
|
name = 'log';
|
|
async send(message: EmailMessage): Promise<EmailResult> {
|
|
console.log(`[email:log] to=${message.to} subject="${message.subject}"`);
|
|
return { id: `log_${Date.now().toString(36)}`, provider: this.name };
|
|
}
|
|
}
|
|
|
|
/** Real provider, activated by RESEND_API_KEY. */
|
|
export class ResendProvider implements EmailProvider {
|
|
name = 'resend';
|
|
constructor(private apiKey: string, private from: string) {}
|
|
async send(message: EmailMessage): Promise<EmailResult> {
|
|
const res = await fetch('https://api.resend.com/emails', {
|
|
method: 'POST',
|
|
headers: { Authorization: `Bearer ${this.apiKey}`, 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ from: this.from, to: message.to, subject: message.subject, html: message.html }),
|
|
});
|
|
if (!res.ok) throw new Error(`Resend error ${res.status}: ${await res.text()}`);
|
|
const data = (await res.json()) as { id: string };
|
|
return { id: data.id, provider: this.name };
|
|
}
|
|
}
|
|
|
|
export function getEmail(): EmailProvider {
|
|
if (env.RESEND_API_KEY) return new ResendProvider(env.RESEND_API_KEY, env.EMAIL_FROM);
|
|
return new LogProvider();
|
|
}
|
|
|
|
export function sendEmail(message: EmailMessage): Promise<EmailResult> {
|
|
return getEmail().send(message);
|
|
}
|