Files
pn-new-crm/src/lib/email/index.ts

57 lines
1.5 KiB
TypeScript
Raw Normal View History

import nodemailer, { type Transporter } from 'nodemailer';
import { env } from '@/lib/env';
import { logger } from '@/lib/logger';
/**
* Creates and returns a new Nodemailer SMTP transporter.
*
* A new instance is created on each call so the factory can be used in
* contexts where connection pooling is managed externally (e.g. per-request
* in serverless, or once at worker startup).
*/
export function createTransporter(): Transporter {
return nodemailer.createTransport({
host: env.SMTP_HOST,
port: env.SMTP_PORT,
// Implicitly secure when port is 465; STARTTLS for all other ports.
secure: env.SMTP_PORT === 465,
});
}
export interface SendEmailOptions {
to: string | string[];
subject: string;
html: string;
from?: string;
}
/**
* Sends a single email via SMTP.
*
* Returns the nodemailer info object on success. Propagates errors to the
* caller callers in background jobs should wrap in try/catch and handle
* retries via BullMQ.
*/
export async function sendEmail(
to: string | string[],
subject: string,
html: string,
from?: string,
text?: string,
): Promise<nodemailer.SentMessageInfo> {
const transporter = createTransporter();
const info = await transporter.sendMail({
from: from ?? `Port Nimara CRM <noreply@${env.SMTP_HOST}>`,
to: Array.isArray(to) ? to.join(', ') : to,
subject,
html,
...(text ? { text } : {}),
});
logger.debug({ messageId: info.messageId, to, subject }, 'Email sent');
return info;
}