const nodemailer = require('nodemailer') const debug = require('debug')('48hr-email:smtp-service') /** * SMTP Service for forwarding emails * Uses nodemailer to send forwarded emails via configured SMTP server */ class SmtpService { constructor(config) { this.config = config this.transporter = null // Only initialize transporter if SMTP is configured if (this._isConfigured()) { this._initializeTransporter() } else { debug('SMTP not configured - forwarding functionality will be unavailable') } } /** * Check if SMTP is properly configured * @returns {boolean} */ _isConfigured() { return !!( this.config.smtp.enabled && this.config.smtp.host && this.config.smtp.user && this.config.smtp.password ) } /** * Initialize the nodemailer transporter * @private */ _initializeTransporter() { try { this.transporter = nodemailer.createTransport({ host: this.config.smtp.host, port: this.config.smtp.port, secure: this.config.smtp.secure, auth: { user: this.config.smtp.user, pass: this.config.smtp.password }, tls: { // Allow self-signed certificates and skip verification // This is useful for development or internal SMTP servers rejectUnauthorized: false } }) debug(`SMTP transporter initialized: ${this.config.smtp.host}:${this.config.smtp.port}`) } catch (error) { debug('Failed to initialize SMTP transporter:', error.message) throw new Error(`SMTP initialization failed: ${error.message}`) } } /** * Forward an email to a destination address * @param {Object} mail - Parsed email object from mailparser * @param {string} destinationEmail - Email address to forward to * @returns {Promise<{success: boolean, error?: string, messageId?: string}>} */ async forwardMail(mail, destinationEmail) { if (!this.transporter) { return { success: false, error: 'SMTP is not configured. Please configure SMTP settings to enable forwarding.' } } if (!mail) { return { success: false, error: 'Email not found' } } try { debug(`Forwarding email (Subject: "${mail.subject}") to ${destinationEmail}`) const forwardMessage = this._buildForwardMessage(mail, destinationEmail) const info = await this.transporter.sendMail(forwardMessage) debug(`Email forwarded successfully. MessageId: ${info.messageId}`) return { success: true, messageId: info.messageId } } catch (error) { debug('Failed to forward email:', error.message) return { success: false, error: `Failed to send email: ${error.message}` } } } /** * Build the forward message structure * @param {Object} mail - Parsed email object * @param {string} destinationEmail - Destination address * @returns {Object} - Nodemailer message object * @private */ _buildForwardMessage(mail, destinationEmail) { // Extract original sender info const originalFrom = (mail.from && mail.from.text) || 'Unknown Sender' const originalTo = (mail.to && mail.to.text) || 'Unknown Recipient' const originalDate = mail.date ? new Date(mail.date).toLocaleString() : 'Unknown Date' const originalSubject = mail.subject || '(no subject)' // Build forwarded message body let forwardedBody = ` ---------- Forwarded message ---------- From: ${originalFrom} Date: ${originalDate} Subject: ${originalSubject} To: ${originalTo} ` // Add original text body if available if (mail.text) { forwardedBody += mail.text } else if (mail.html) { // If only HTML is available, mention it forwardedBody += '[This email contains HTML content. See attachment or HTML version below.]\n\n' } // Build the message object const message = { from: { name: this.config.smtp.fromName, address: this.config.smtp.user }, to: destinationEmail, subject: `Fwd: ${originalSubject}`, text: forwardedBody, replyTo: originalFrom } // Add HTML body if available if (mail.html) { const htmlForwardedBody = `
---------- Forwarded message ----------
From: ${this._escapeHtml(originalFrom)}
Date: ${this._escapeHtml(originalDate)}
Subject: ${this._escapeHtml(originalSubject)}
To: ${this._escapeHtml(originalTo)}