const brevo = require('@getbrevo/brevo'); const fs = require('fs'); const path = require('path'); const { logger } = require('../middleware/logger'); class MailService { constructor() { this.brevo = new brevo.TransactionalEmailsApi(); this.brevo.setApiKey( brevo.TransactionalEmailsApiApiKeys.apiKey, process.env.BREVO_API_KEY ); this.sender = { email: process.env.BREVO_SENDER_EMAIL, name: process.env.BREVO_SENDER_NAME, }; this.loginUrl = process.env.LOGIN_URL; this.templatesDir = path.join(__dirname, '../mailTemplates'); } // Helper to load and render a template renderTemplate(templateName, variables, lang = 'en') { logger.info('MailService.renderTemplate:start', { templateName, lang }); // Supported languages const supportedLangs = ['en', 'de']; // Fallback to 'en' if unsupported or missing const chosenLang = supportedLangs.includes(lang) ? lang : 'en'; const templatePath = path.join(this.templatesDir, chosenLang, templateName); let template; try { template = fs.readFileSync(templatePath, 'utf8'); logger.info('MailService.renderTemplate:template_loaded', { templatePath, lang: chosenLang }); } catch (err) { // Fallback to English if template not found if (chosenLang !== 'en') { const fallbackPath = path.join(this.templatesDir, 'en', templateName); template = fs.readFileSync(fallbackPath, 'utf8'); logger.warn('MailService.renderTemplate:fallback_to_en', { fallbackPath, lang }); } else { logger.error('MailService.renderTemplate:error', { templatePath, error: err.message }); throw err; } } template = template.replace(/{{(\w+)}}/g, (_, key) => variables[key] || ''); logger.info('MailService.renderTemplate:success', { templateName, lang: chosenLang }); return template; } async sendRegistrationEmail({ email, firstName, lastName, userType, companyName, lang }) { logger.info('MailService.sendRegistrationEmail:start', { email, userType, lang }); let subject, text; const chosenLang = lang || 'en'; if (userType === 'personal') { subject = chosenLang === 'de' ? `Willkommen bei ProfitPlanet, ${firstName}!` : `Welcome to ProfitPlanet, ${firstName}!`; text = this.renderTemplate('registrationPersonal.txt', { firstName, lastName, loginUrl: this.loginUrl }, chosenLang); } else if (userType === 'company') { subject = chosenLang === 'de' ? `Willkommen bei ProfitPlanet, ${companyName}!` : `Welcome to ProfitPlanet, ${companyName}!`; text = this.renderTemplate('registrationCompany.txt', { companyName, loginUrl: this.loginUrl }, chosenLang); } else { subject = chosenLang === 'de' ? 'Willkommen bei ProfitPlanet!' : 'Welcome to ProfitPlanet!'; text = chosenLang === 'de' ? `Danke für Ihre Registrierung bei ProfitPlanet!\nSie können sich jetzt hier anmelden: ${this.loginUrl}\n\nMit freundlichen Grüßen,\nProfitPlanet Team` : `Thank you for registering at ProfitPlanet!\nYou can now log in here: ${this.loginUrl}\n\nBest regards,\nProfitPlanet Team`; } try { const payload = new brevo.SendSmtpEmail(); payload.sender = this.sender; payload.to = [{ email }]; payload.subject = subject; payload.textContent = text; const data = await this.brevo.sendTransacEmail(payload); logger.info('MailService.sendRegistrationEmail:email_sent', { email, userType, lang: chosenLang }); return data; } catch (error) { logger.error('MailService.sendRegistrationEmail:error', { email, error: error.message }); throw error; } } async sendVerificationCodeEmail({ email, code, expiresAt, lang }) { logger.info('MailService.sendVerificationCodeEmail:start', { email, code, expiresAt, lang }); const chosenLang = lang || 'en'; const subject = chosenLang === 'de' ? 'Ihr ProfitPlanet E-Mail-Verifizierungscode' : 'Your ProfitPlanet Email Verification Code'; const text = this.renderTemplate('verificationCode.txt', { code, expiresAt: expiresAt.toLocaleTimeString() }, chosenLang); try { const payload = new brevo.SendSmtpEmail(); payload.sender = this.sender; payload.to = [{ email }]; payload.subject = subject; payload.textContent = text; const data = await this.brevo.sendTransacEmail(payload); logger.info('MailService.sendVerificationCodeEmail:email_sent', { email, code, lang: chosenLang }); return data; } catch (error) { logger.error('MailService.sendVerificationCodeEmail:error', { email, error: error.message }); throw error; } } async sendLoginNotificationEmail({ email, ip, loginTime, userAgent, lang }) { logger.info('MailService.sendLoginNotificationEmail:start', { email, ip, loginTime, userAgent, lang }); const chosenLang = lang || 'en'; const subject = chosenLang === 'de' ? 'ProfitPlanet: Neue Login-Benachrichtigung' : 'ProfitPlanet: New Login Notification'; const text = this.renderTemplate('loginNotification.txt', { email, ip, loginTime: loginTime.toLocaleString(), userAgent }, chosenLang); try { const payload = new brevo.SendSmtpEmail(); payload.sender = this.sender; payload.to = [{ email }]; payload.subject = subject; payload.textContent = text; const data = await this.brevo.sendTransacEmail(payload); logger.info('MailService.sendLoginNotificationEmail:email_sent', { email, ip, lang: chosenLang }); return data; } catch (error) { logger.error('MailService.sendLoginNotificationEmail:error', { email, error: error.message }); throw error; } } async sendPasswordResetEmail({ email, firstName, companyName, token, lang }) { logger.info('MailService.sendPasswordResetEmail:start', { email, token, lang }); const chosenLang = lang || 'en'; const subject = chosenLang === 'de' ? 'ProfitPlanet: Passwort zurücksetzen' : 'ProfitPlanet: Password Reset'; const resetUrl = `${process.env.PASSWORD_RESET_URL || 'https://profit-planet.partners/password-reset-set'}?token=${token}`; const text = this.renderTemplate('passwordReset.txt', { firstName: firstName || '', companyName: companyName || '', resetUrl }, chosenLang); try { const payload = new brevo.SendSmtpEmail(); payload.sender = this.sender; payload.to = [{ email }]; payload.subject = subject; payload.textContent = text; const data = await this.brevo.sendTransacEmail(payload); logger.info('MailService.sendPasswordResetEmail:email_sent', { email, token, lang: chosenLang }); return data; } catch (error) { logger.error('MailService.sendPasswordResetEmail:error', { email, error: error.message }); throw error; } } } module.exports = new MailService();