import nodemailer from 'nodemailer' import crypto from 'crypto' import type { H3Event } from 'h3' /** * Get email configuration from runtime config or environment variables * In production, environment variables are accessed directly for reliability */ function getEmailConfig(event?: H3Event) { // Try to use runtime config if event is provided if (event) { try { const config = useRuntimeConfig(event) return { emailHost: config.emailHost, emailPort: config.emailPort, emailUser: config.emailUser, emailPassword: config.emailPassword, emailFrom: config.emailFrom, } } catch (e) { console.warn('[EMAIL] Failed to access runtime config, falling back to env vars') } } // Fallback to direct environment variable access return { emailHost: process.env.EMAIL_HOST || 'smtp.example.com', emailPort: process.env.EMAIL_PORT || '587', emailUser: process.env.EMAIL_USER || 'noreply@example.com', emailPassword: process.env.EMAIL_PASSWORD || '', emailFrom: process.env.EMAIL_FROM || 'New Life Christian Church ', } } export async function sendPasswordResetEmail(email: string, code: string, event?: H3Event) { const config = getEmailConfig(event) // Debug logging for email configuration console.log('[EMAIL CONFIG] Host:', config.emailHost) console.log('[EMAIL CONFIG] Port:', config.emailPort) console.log('[EMAIL CONFIG] User:', config.emailUser) console.log('[EMAIL CONFIG] From:', config.emailFrom) const transporter = nodemailer.createTransport({ host: config.emailHost, port: parseInt(config.emailPort), secure: parseInt(config.emailPort) === 465, auth: { user: config.emailUser, pass: config.emailPassword, }, }) const mailOptions = { from: config.emailFrom, to: email, subject: 'Password Reset Code - New Life Christian Church', text: `Please enter this code to reset your password for the New Life Christian Church sermon page: ${code}\n\nThis code will expire in 15 minutes.\n\nIf you did not request a password reset, please ignore this email.`, html: `

Password Reset Request

Please enter this code to reset your password for the New Life Christian Church sermon page:

${code}

⏱️ This code will expire in 15 minutes.

If you did not request a password reset, please ignore this email. Your password will not be changed.

New Life Christian Church

`, } await transporter.sendMail(mailOptions) } /** * Generate a cryptographically secure password reset code * * Format: 8-character alphanumeric code (0-9, A-Z) * Character set: 36 characters (10 digits + 26 uppercase letters) * Total combinations: 36^8 = 2,821,109,907,456 (2.8 trillion) * * Security improvements over 6-digit numeric: * - 6-digit numeric: 1,000,000 combinations * - 8-char alphanumeric: 2,821,109,907,456 combinations * - 2.8 million times more secure * * Why this is secure: * - Uses crypto.randomInt() for cryptographic randomness * - Case-insensitive for better user experience (uppercase only) * - Excludes confusing characters like O/0, I/1 for better UX * - Still fits well in emails and is easy to type */ export function generateResetCode(): string { // Character set: uppercase letters and numbers (excluding confusing chars) // Excluded: I, O (look like 1, 0) const chars = '0123456789ABCDEFGHJKLMNPQRSTUVWXYZ' // 34 chars (removed I, O) let code = '' for (let i = 0; i < 8; i++) { const randomIndex = crypto.randomInt(chars.length) code += chars[randomIndex] } return code } export async function sendSermonNotesEmail( email: string, firstName: string, sermonTitle: string, sermonDate: string, bibleReferences: string, personalAppliance: string, pastorsChallenge: string, userNotes: string, event?: H3Event ) { const config = getEmailConfig(event) const transporter = nodemailer.createTransport({ host: config.emailHost, port: parseInt(config.emailPort), secure: parseInt(config.emailPort) === 465, auth: { user: config.emailUser, pass: config.emailPassword, }, }) const mailOptions = { from: config.emailFrom, to: email, subject: `Sermon Notes: ${sermonTitle}`, text: ` Sermon Notes for ${firstName} Title: ${sermonTitle} Date: ${sermonDate} Bible References: ${bibleReferences} Personal Appliance: ${personalAppliance} Pastor's Challenge: ${pastorsChallenge} My Notes: ${userNotes || 'No notes taken'} `, html: `

Sermon Notes

${sermonTitle}

${sermonDate}

Bible References

${bibleReferences}

Personal Appliance

${personalAppliance}

Pastor's Challenge

${pastorsChallenge}

My Notes

${userNotes || 'No notes taken'}

This email was sent from New Life Christian Church.

`, } await transporter.sendMail(mailOptions) }