import Mailgun from 'mailgun.js' import FormData from 'form-data' import { prisma } from './db' interface EmailOptions { to: string | string[] subject: string text?: string html?: string from?: string replyTo?: string } interface SendEmailResult { success: boolean messageId?: string error?: string } class MailgunService { private mailgun: any private settings: any = null constructor() { this.mailgun = new Mailgun(FormData) } private async getSettings() { if (!this.settings) { this.settings = await prisma.mailgunSettings.findFirst({ where: { isEnabled: true }, orderBy: { updatedAt: 'desc' } }) } return this.settings } private getMg() { const settings = this.settings if (!settings) { throw new Error('No Mailgun settings found') } return this.mailgun.client({ username: 'api', key: settings.apiKey, url: settings.region === 'EU' ? 'https://api.eu.mailgun.net' : 'https://api.mailgun.net' }) } async sendEmail(options: EmailOptions): Promise { try { const settings = await this.getSettings() if (!settings) { return { success: false, error: 'Mailgun not configured' } } if (!settings.isEnabled) { return { success: false, error: 'Mailgun is disabled' } } const mg = this.getMg() const emailData = { from: options.from || `${settings.fromName} <${settings.fromEmail}>`, to: Array.isArray(options.to) ? options.to.join(', ') : options.to, subject: options.subject, text: options.text, html: options.html, 'h:Reply-To': options.replyTo || settings.replyToEmail } // Remove undefined values Object.keys(emailData).forEach(key => { if (emailData[key as keyof typeof emailData] === undefined) { delete emailData[key as keyof typeof emailData] } }) // In test mode, use Mailgun's test domain if (settings.testMode) { console.log('Mailgun test mode - email would be sent:', emailData) return { success: true, messageId: `test-${Date.now()}` } } const response = await mg.messages.create(settings.domain, emailData) return { success: true, messageId: response.id } } catch (error) { console.error('Mailgun send error:', error) return { success: false, error: error instanceof Error ? error.message : 'Unknown error' } } } async sendContactForm(data: { name: string email: string subject: string message: string }): Promise { const settings = await this.getSettings() if (!settings) { return { success: false, error: 'Mailgun not configured' } } const html = `

New Contact Form Submission

Name: ${data.name}

Email: ${data.email}

Subject: ${data.subject}

Message:

${data.message.replace(/\n/g, '
')}
` const text = ` New Contact Form Submission Name: ${data.name} Email: ${data.email} Subject: ${data.subject} Message: ${data.message} ` return this.sendEmail({ to: settings.fromEmail, // Send to site admin subject: `Contact Form: ${data.subject}`, html, text, replyTo: data.email }) } async sendPasswordReset(email: string, resetToken: string): Promise { const settings = await this.getSettings() if (!settings) { return { success: false, error: 'Mailgun not configured' } } // This would need to be updated with your actual domain const resetUrl = `${process.env.NEXT_PUBLIC_BASE_URL}/reset-password?token=${resetToken}` const html = `

Password Reset Request

You requested to reset your password for your Biblical Guide account.

Click the link below to reset your password:

Reset Password

This link will expire in 1 hour.

If you didn't request this, please ignore this email.

` const text = ` Password Reset Request You requested to reset your password for your Biblical Guide account. Click the link below to reset your password: ${resetUrl} This link will expire in 1 hour. If you didn't request this, please ignore this email. ` return this.sendEmail({ to: email, subject: 'Reset Your Password - Biblical Guide', html, text }) } async testConnection(): Promise<{ success: boolean; error?: string }> { try { const settings = await this.getSettings() if (!settings) { return { success: false, error: 'No settings found' } } const mg = this.getMg() // Test by getting domain info await mg.domains.get(settings.domain) return { success: true } } catch (error) { return { success: false, error: error instanceof Error ? error.message : 'Connection failed' } } } // Clear cached settings when they are updated clearCache() { this.settings = null } } export const mailgunService = new MailgunService()