import nodemailer from "nodemailer" import { query } from "@/lib/db" const ADMIN_EMAIL = process.env.ADMIN_EMAIL || "" const SMTP_HOST = process.env.SMTP_HOST || "" const SMTP_PORT = parseInt(process.env.SMTP_PORT || "587", 10) const SMTP_USER = process.env.SMTP_USER || "" const SMTP_PASS = process.env.SMTP_PASS || "" const EMAIL_FROM = process.env.EMAIL_FROM || "noreply@coastit.co.za" function createTransporter() { const hasAuth = !!(SMTP_USER && SMTP_PASS) const isLocal = SMTP_HOST === "127.0.0.1" || SMTP_HOST === "localhost" const tlsOptions = hasAuth && !isLocal ? { rejectUnauthorized: true } : { rejectUnauthorized: false } return nodemailer.createTransport({ host: SMTP_HOST, port: SMTP_PORT, secure: SMTP_PORT === 465, requireTLS: hasAuth && !isLocal, ...(hasAuth ? { auth: { user: SMTP_USER, pass: SMTP_PASS } } : {}), tls: tlsOptions, connectionTimeout: 5000, greetingTimeout: 5000, }) } function formatDate(iso: string) { return new Date(iso).toLocaleDateString("en-US", { weekday: "long", month: "long", day: "numeric", year: "numeric", }) } function formatTime(iso: string) { return new Date(iso).toLocaleTimeString("en-US", { hour: "numeric", minute: "2-digit", hour12: true, }) } function formatDuration(min: number) { if (min < 60) return `${min} minutes` const h = Math.floor(min / 60) const m = min % 60 return m > 0 ? `${h}h ${m}m` : `${h} hour${h > 1 ? "s" : ""}` } export interface EventConfirmationInput { creatorName: string creatorEmail: string participantName: string | null participantEmail: string | null title: string description?: string eventType: string startTime: string endTime?: string durationMinutes?: number } function buildEmail(event: EventConfirmationInput, variant: "scheduled" | "rescheduled" = "scheduled") { const dateStr = formatDate(event.startTime) const timeStr = formatTime(event.startTime) const durStr = event.durationMinutes ? formatDuration(event.durationMinutes) : "" const typeLabel = event.eventType.charAt(0).toUpperCase() + event.eventType.slice(1) const heading = variant === "rescheduled" ? "Event Rescheduled" : "Event Scheduled" const badge = variant === "rescheduled" ? '
This event has been rescheduled
' : "" const html = `

${heading}

${badge}

${event.title}

${durStr ? `` : ""} ${event.description ? `` : ""} ${event.participantName ? `` : ""}
Type${typeLabel}
Date${dateStr}
Time${timeStr}
Duration${durStr}
Notes${event.description}
Created by${event.creatorName}
With${event.participantName}

Automated confirmation from CRM.

` const text = `${variant === "rescheduled" ? "[RESCHEDULED] " : ""}Event: ${event.title} Type: ${typeLabel} Date: ${dateStr} Time: ${timeStr} ${durStr ? `Duration: ${durStr}` : ""} ${event.description ? `Notes: ${event.description}` : ""} Created by: ${event.creatorName} ${event.participantName ? `With: ${event.participantName}` : ""}` const prefix = variant === "rescheduled" ? "🔄 Rescheduled: " : "" const subject = `${prefix}${event.title} — ${dateStr}` return { html, text, subject, dateStr } } export async function sendEventConfirmation(event: EventConfirmationInput) { const { html, text, subject } = buildEmail(event) const recipients: string[] = [] if (event.creatorEmail) recipients.push(event.creatorEmail) if (event.participantEmail && !recipients.includes(event.participantEmail)) recipients.push(event.participantEmail) if (ADMIN_EMAIL && !recipients.includes(ADMIN_EMAIL)) recipients.push(ADMIN_EMAIL) // 1. Always store in database for (const to of recipients) { await query( `INSERT INTO sent_emails (recipient, subject, body_html, body_text) VALUES ($1, $2, $3, $4)`, [to, subject, html, text], ).catch(() => {}) } if (recipients.length === 0) return // 2. Send via SMTP if configured if (SMTP_HOST) { const transporter = createTransporter() await transporter.sendMail({ from: EMAIL_FROM, to: recipients.join(", "), subject, text, html, }).catch(() => {}) return } // 3. Fallback: log to console with instructions console.log("=".repeat(60)) console.log(`📧 Email ready — ${subject}`) console.log(` To: ${recipients.join(", ")}`) console.log(` Body:\n${text}`) console.log("=".repeat(60)) console.log("💡 To send real emails:") console.log(" Fill in SMTP_HOST in .env (maildev works at localhost:1025 with no auth)") console.log(" Or set SMTP_HOST/SMTP_USER/SMTP_PASS for authenticated relays") } export async function sendEventRescheduled(event: EventConfirmationInput) { const { html, text, subject } = buildEmail(event, "rescheduled") const recipients: string[] = [] if (event.creatorEmail) recipients.push(event.creatorEmail) if (event.participantEmail && !recipients.includes(event.participantEmail)) recipients.push(event.participantEmail) if (ADMIN_EMAIL && !recipients.includes(ADMIN_EMAIL)) recipients.push(ADMIN_EMAIL) for (const to of recipients) { await query( `INSERT INTO sent_emails (recipient, subject, body_html, body_text) VALUES ($1, $2, $3, $4)`, [to, subject, html, text], ).catch(() => {}) } if (recipients.length === 0) return if (SMTP_HOST) { const transporter = createTransporter() await transporter.sendMail({ from: EMAIL_FROM, to: recipients.join(", "), subject, text, html, }).catch(() => {}) return } console.log("=".repeat(60)) console.log(`🔄 Reschedule email ready — ${subject}`) console.log(` To: ${recipients.join(", ")}`) console.log(` Body:\n${text}`) console.log("=".repeat(60)) }