"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.EmailService = void 0; const nodemailer = __importStar(require("nodemailer")); const fs = __importStar(require("fs")); const path = __importStar(require("path")); const Logger_1 = require("./Logger"); const EmailTemplateHelper_1 = require("./EmailTemplateHelper"); class EmailService { constructor() { this.templatesPath = path.join(__dirname, '../../Templates'); this.config = { host: process.env.EMAIL_HOST || 'smtp.gmail.com', port: parseInt(process.env.EMAIL_PORT || '587'), secure: process.env.EMAIL_SECURE === 'true', auth: { user: process.env.EMAIL_USER || '', pass: process.env.EMAIL_PASS || '' }, from: process.env.EMAIL_FROM || 'noreply@serpentrace.com' }; this.initializeTransporter(); } initializeTransporter() { try { this.transporter = nodemailer.createTransport({ host: this.config.host, port: this.config.port, secure: this.config.secure, auth: { user: this.config.auth.user, pass: this.config.auth.pass } }); } catch (error) { (0, Logger_1.logError)('EmailService initialization failed', error instanceof Error ? error : new Error(String(error))); throw new Error('Failed to initialize email service'); } } /** * Send email with template * @param options - Email options including template and data */ async sendEmail(options) { try { let htmlContent = options.html; let textContent = options.text; if (options.template) { const templateResult = await this.loadTemplate(options.template, options.templateData || {}); htmlContent = templateResult.html; textContent = templateResult.text; } const mailOptions = { from: this.config.from, to: options.to, subject: options.subject, html: htmlContent, text: textContent }; const result = await this.transporter.sendMail(mailOptions); (0, Logger_1.logAuth)('Email sent successfully', undefined, { messageId: result.messageId, to: options.to, subject: options.subject }); return true; } catch (error) { (0, Logger_1.logError)('Email sending failed', error instanceof Error ? error : new Error(String(error))); return false; } } /** * Send verification email to user * @param userEmail - User's email address * @param userName - User's name * @param verificationToken - Verification token * @param verificationUrl - Complete verification URL * @param language - Language code ('en', 'hu', 'de') */ async sendVerificationEmail(userEmail, userName, verificationToken, verificationUrl, language = 'en') { try { const templateName = language === 'en' ? 'verification' : `verification-${language}`; const subject = this.getLocalizedVerificationSubject(language); return await this.sendEmail({ to: userEmail, subject, template: templateName, templateData: { userName, verificationToken, verificationUrl, companyName: 'SerpentRace', supportEmail: 'support@serpentrace.com' } }); } catch (error) { (0, Logger_1.logError)('Verification email sending failed', error instanceof Error ? error : new Error(String(error))); return false; } } /** * Send password reset email * @param userEmail - User's email address * @param userName - User's name * @param resetToken - Password reset token * @param resetUrl - Complete password reset URL * @param language - Language code ('en', 'hu', 'de') */ async sendPasswordResetEmail(userEmail, userName, resetToken, resetUrl, language = 'en') { try { const templateName = language === 'en' ? 'password-reset' : `password-reset-${language}`; const subject = this.getLocalizedPasswordResetSubject(language); return await this.sendEmail({ to: userEmail, subject, template: templateName, templateData: { userName, resetToken, resetUrl, companyName: 'SerpentRace', supportEmail: 'support@serpentrace.com' } }); } catch (error) { (0, Logger_1.logError)('Password reset email sending failed', error instanceof Error ? error : new Error(String(error))); return false; } } /** * Load and compile email template with language support * @param templateName - Name of the template file (with or without language suffix) * @param data - Data to replace placeholders in the template */ async loadTemplate(templateName, data) { try { // Try the specified template first let htmlTemplatePath = path.join(this.templatesPath, `${templateName}.html`); let textTemplatePath = path.join(this.templatesPath, `${templateName}.txt`); let htmlTemplate = ''; let textTemplate = ''; // Load HTML template if it exists if (fs.existsSync(htmlTemplatePath)) { htmlTemplate = fs.readFileSync(htmlTemplatePath, 'utf8'); } else { // If language-specific template doesn't exist, try fallback to English const baseName = templateName.replace(/-[a-z]{2}$/, ''); // Remove language suffix const fallbackHtmlPath = path.join(this.templatesPath, `${baseName}.html`); if (fs.existsSync(fallbackHtmlPath)) { htmlTemplate = fs.readFileSync(fallbackHtmlPath, 'utf8'); } } // Load text template if it exists if (fs.existsSync(textTemplatePath)) { textTemplate = fs.readFileSync(textTemplatePath, 'utf8'); } else { // If language-specific template doesn't exist, try fallback to English const baseName = templateName.replace(/-[a-z]{2}$/, ''); // Remove language suffix const fallbackTextPath = path.join(this.templatesPath, `${baseName}.txt`); if (fs.existsSync(fallbackTextPath)) { textTemplate = fs.readFileSync(fallbackTextPath, 'utf8'); } } // If no templates found, throw error if (!htmlTemplate && !textTemplate) { throw new Error(`Template '${templateName}' not found`); } // Replace placeholders in templates const processedTemplate = EmailTemplateHelper_1.EmailTemplateHelper.processTemplate({ html: htmlTemplate, text: textTemplate }, data); return { html: processedTemplate.html, text: processedTemplate.text }; } catch (error) { (0, Logger_1.logError)('Email template loading failed', error instanceof Error ? error : new Error(String(error))); throw new Error(`Failed to load email template: ${templateName}`); } } /** * Get localized verification email subject * @param language - Language code ('en', 'hu', 'de') */ getLocalizedVerificationSubject(language) { const subjects = { verification: { en: 'SerpentRace - Verify Your Account', hu: 'SerpentRace - Fiók megerősítése', de: 'SerpentRace - Konto verifizieren' } }; return EmailTemplateHelper_1.EmailTemplateHelper.getLocalizedSubject('verification', subjects, language); } /** * Get localized password reset email subject * @param language - Language code ('en', 'hu', 'de') */ getLocalizedPasswordResetSubject(language) { const subjects = { passwordReset: { en: 'SerpentRace - Password Reset Request', hu: 'SerpentRace - Jelszó visszaállítás kérése', de: 'SerpentRace - Passwort zurücksetzen' } }; return EmailTemplateHelper_1.EmailTemplateHelper.getLocalizedSubject('passwordReset', subjects, language); } } exports.EmailService = EmailService; //# sourceMappingURL=EmailService.js.map