50 lines
1.4 KiB
TypeScript
50 lines
1.4 KiB
TypeScript
import { mkdir, writeFile } from 'node:fs/promises';
|
|
import path from 'node:path';
|
|
import { randomUUID } from 'node:crypto';
|
|
import nodemailer from 'nodemailer';
|
|
import { getMailConfig, getServerPaths } from './config.js';
|
|
|
|
export type MailMessage = {
|
|
to: string;
|
|
subject: string;
|
|
text: string;
|
|
};
|
|
|
|
export async function sendMail(message: MailMessage): Promise<'local' | 'smtp'> {
|
|
const config = getMailConfig();
|
|
if (config.transport === 'local') {
|
|
const outbox = getServerPaths().mailOutbox;
|
|
await mkdir(outbox, { recursive: true, mode: 0o700 });
|
|
const filename = `${new Date().toISOString().replaceAll(':', '-')}-${randomUUID()}.json`;
|
|
await writeFile(
|
|
path.join(outbox, filename),
|
|
JSON.stringify({ from: config.from, ...message }, null, 2),
|
|
{ encoding: 'utf8', mode: 0o600 }
|
|
);
|
|
return 'local';
|
|
}
|
|
|
|
if (
|
|
!config.host ||
|
|
!config.from ||
|
|
!Number.isInteger(config.port) ||
|
|
config.port < 1 ||
|
|
config.port > 65_535 ||
|
|
Boolean(config.user) !== Boolean(config.password)
|
|
) {
|
|
throw new Error('Die SMTP-Konfiguration ist unvollständig.');
|
|
}
|
|
const transporter = nodemailer.createTransport({
|
|
host: config.host,
|
|
port: config.port,
|
|
secure: config.secure,
|
|
requireTLS: !config.secure,
|
|
connectionTimeout: 10_000,
|
|
greetingTimeout: 10_000,
|
|
socketTimeout: 20_000,
|
|
auth: config.user ? { user: config.user, pass: config.password } : undefined
|
|
});
|
|
await transporter.sendMail({ from: config.from, ...message });
|
|
return 'smtp';
|
|
}
|