249 lines
10 KiB
JavaScript
249 lines
10 KiB
JavaScript
"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
|