87 lines
2.8 KiB
TypeScript
87 lines
2.8 KiB
TypeScript
import fs from 'fs';
|
|
import nodemailer from 'nodemailer';
|
|
import type SMTPTransport from 'nodemailer/lib/smtp-transport';
|
|
import path from 'path';
|
|
|
|
type MailOptions = {
|
|
to: string;
|
|
subject: string;
|
|
text: string;
|
|
html?: string;
|
|
};
|
|
|
|
async function createTransport() {
|
|
const {
|
|
SMTP_HOST,
|
|
SMTP_PORT,
|
|
SMTP_USER,
|
|
SMTP_PASS,
|
|
SMTP_FROM,
|
|
SMTP_TLS,
|
|
SMTP_SSL,
|
|
SMTP_REJECT_UNAUTHORIZED,
|
|
DKIM_SELECTOR,
|
|
DKIM_DOMAIN,
|
|
DKIM_PRIVATE_KEY_PATH,
|
|
} = process.env;
|
|
|
|
if (!SMTP_HOST || !SMTP_PORT || !SMTP_USER || !SMTP_PASS || !SMTP_FROM) {
|
|
throw new Error('SMTP configuration is missing required environment variables');
|
|
}
|
|
|
|
const secure = SMTP_SSL === 'true';
|
|
const requireTLS = SMTP_TLS === 'true';
|
|
|
|
const transporterOptions: SMTPTransport.Options = {
|
|
host: SMTP_HOST,
|
|
port: Number(SMTP_PORT),
|
|
secure,
|
|
requireTLS,
|
|
auth: { user: SMTP_USER, pass: SMTP_PASS },
|
|
};
|
|
|
|
if (SMTP_REJECT_UNAUTHORIZED === 'false') {
|
|
transporterOptions.tls = { rejectUnauthorized: false };
|
|
}
|
|
|
|
if (DKIM_SELECTOR && DKIM_DOMAIN && DKIM_PRIVATE_KEY_PATH) {
|
|
const keyPath = path.resolve(process.cwd(), DKIM_PRIVATE_KEY_PATH);
|
|
if (fs.existsSync(keyPath)) {
|
|
transporterOptions.dkim = {
|
|
domainName: DKIM_DOMAIN,
|
|
keySelector: DKIM_SELECTOR,
|
|
privateKey: fs.readFileSync(keyPath, 'utf8'),
|
|
};
|
|
}
|
|
}
|
|
|
|
return nodemailer.createTransport(transporterOptions);
|
|
}
|
|
|
|
let cachedTransport: nodemailer.Transporter | null = null;
|
|
|
|
async function getTransport() {
|
|
if (cachedTransport) return cachedTransport;
|
|
cachedTransport = await createTransport();
|
|
return cachedTransport;
|
|
}
|
|
|
|
export async function sendMail({ to, subject, text, html }: MailOptions) {
|
|
const transporter = await getTransport();
|
|
const from = process.env.SMTP_FROM!;
|
|
return transporter.sendMail({ from, to, subject, text, html: html ?? text });
|
|
}
|
|
|
|
export async function sendVerificationEmail(to: string, link: string) {
|
|
const subject = 'Verify your email for lomavuokraus.fi';
|
|
const text = `Please verify your email by visiting: ${link}\n\nIf you did not request this, you can ignore this email.`;
|
|
const html = `<p>Please verify your email by clicking <a href="${link}">this link</a>.</p><p>If you did not request this, you can ignore this email.</p>`;
|
|
return sendMail({ to, subject, text, html });
|
|
}
|
|
|
|
export async function sendPasswordResetEmail(to: string, link: string) {
|
|
const subject = 'Reset your password for lomavuokraus.fi';
|
|
const text = `We received a request to reset your password.\n\nReset here: ${link}\n\nIf you did not request this, you can ignore this email.`;
|
|
const html = `<p>We received a request to reset your password.</p><p><a href="${link}">Reset your password</a></p><p>If you did not request this, you can ignore this email.</p>`;
|
|
return sendMail({ to, subject, text, html });
|
|
}
|