Initial commit: Port Nimara CRM (Layers 0-4)
Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM, PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source files covering clients, berths, interests/pipeline, documents/EOI, expenses/invoices, email, notifications, dashboard, admin, and client portal. CI/CD via Gitea Actions with Docker builds. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
57
src/lib/email/index.ts
Normal file
57
src/lib/email/index.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
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,
|
||||
): 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,
|
||||
});
|
||||
|
||||
logger.debug(
|
||||
{ messageId: info.messageId, to, subject },
|
||||
'Email sent',
|
||||
);
|
||||
|
||||
return info;
|
||||
}
|
||||
Reference in New Issue
Block a user