import * as nodemailer from 'nodemailer'; export namespace MailService { const transporter = nodemailer.createTransport({ host: process.env.EMAIL_HOST, pool: true, port: 465, secure: true, auth: { user: process.env.EMAIL_USERNAME, pass: process.env.EMAIL_PASSWORD }, tls: {rejectUnauthorized: false} }); export interface MailAttachment { filename: string; content: string | Buffer; contentType?: string; } export interface SendMailOptions { html?: string; attachments?: MailAttachment[]; } // Builds a fresh options object per call rather than mutating a shared // module-level one - the transporter is pooled, so overlapping sendMail // calls (e.g. two guests redeeming at once) previously risked one // call's recipient/subject/body being overwritten by another's before // transporter.sendMail() read it. export const sendMail = async (recipientAddress: string, subject: string, body: string, options?: SendMailOptions) => { await transporter.sendMail({ from: 'noreply@nachklang.art', to: recipientAddress, subject: subject, text: body, html: options?.html, attachments: options?.attachments }); }; }