nakama/backend/utils/email.js

185 lines
6.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const AWS = require('aws-sdk');
const nodemailer = require('nodemailer');
const config = require('../config');
// Инициализация AWS SES
let sesClient = null;
let transporter = null;
const initializeEmailService = () => {
const emailProvider = process.env.EMAIL_PROVIDER || 'aws'; // aws, yandex, smtp
if (emailProvider === 'aws' && config.email?.aws) {
sesClient = new AWS.SES({
accessKeyId: config.email.aws.accessKeyId,
secretAccessKey: config.email.aws.secretAccessKey,
region: config.email.aws.region || 'us-east-1'
});
} else if (emailProvider === 'yandex' || emailProvider === 'smtp') {
const emailConfig = config.email?.[emailProvider] || config.email?.smtp || {};
transporter = nodemailer.createTransport({
host: emailConfig.host || process.env.SMTP_HOST,
port: emailConfig.port || parseInt(process.env.SMTP_PORT || '587', 10),
secure: emailConfig.secure === true || process.env.SMTP_SECURE === 'true',
auth: {
user: emailConfig.user || process.env.SMTP_USER,
pass: emailConfig.password || process.env.SMTP_PASSWORD
}
});
}
};
// Генерация HTML письма с кодом
const generateVerificationEmail = (code) => {
return `
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
.container { max-width: 600px; margin: 0 auto; padding: 20px; }
.code { font-size: 32px; font-weight: bold; color: #007bff;
text-align: center; padding: 20px; background: #f8f9fa;
border-radius: 8px; margin: 20px 0; letter-spacing: 8px; }
.footer { margin-top: 30px; font-size: 12px; color: #666; }
</style>
</head>
<body>
<div class="container">
<h1>Код подтверждения</h1>
<p>Ваш код для регистрации в Nakama:</p>
<div class="code">${code}</div>
<p>Код действителен в течение 15 минут.</p>
<div class="footer">
<p>Если вы не запрашивали этот код, просто проигнорируйте это письмо.</p>
</div>
</div>
</body>
</html>
`;
};
const sendEmail = async (to, subject, html, text) => {
try {
const emailProvider = process.env.EMAIL_PROVIDER || 'aws';
const fromEmail = process.env.EMAIL_FROM || config.email?.from || 'noreply@nakama.guru';
if (emailProvider === 'aws' && sesClient) {
// Отправка через AWS SES
const params = {
Source: fromEmail,
Destination: {
ToAddresses: [to]
},
Message: {
Subject: {
Data: subject,
Charset: 'UTF-8'
},
Body: {
Html: {
Data: html,
Charset: 'UTF-8'
},
Text: {
Data: text || html.replace(/<[^>]*>/g, ''),
Charset: 'UTF-8'
}
}
}
};
const result = await sesClient.sendEmail(params).promise();
return { success: true, messageId: result.MessageId };
} else if (transporter) {
// Отправка через SMTP (Yandex, Gmail и т.д.)
const info = await transporter.sendMail({
from: fromEmail,
to,
subject,
html,
text: text || html.replace(/<[^>]*>/g, '')
});
return { success: true, messageId: info.messageId };
} else {
throw new Error('Email service not configured');
}
} catch (error) {
console.error('Ошибка отправки email:', error);
throw error;
}
};
const sendVerificationCode = async (email, code) => {
const subject = 'Код подтверждения регистрации - Nakama';
const html = generateVerificationEmail(code);
const text = `Ваш код подтверждения: ${code}. Код действителен 15 минут.`;
return await sendEmail(email, subject, html, text);
};
// Генерация HTML письма с кодом для админа
const generateAdminConfirmationEmail = (code, action, userInfo) => {
const actionText = action === 'add' ? 'добавления админа' : 'удаления админа';
const userDetails = userInfo ? `
<p><strong>Пользователь:</strong> @${userInfo.username} (${userInfo.firstName})</p>
${userInfo.adminNumber ? `<p><strong>Номер админа:</strong> ${userInfo.adminNumber}</p>` : ''}
` : '';
return `
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
.container { max-width: 600px; margin: 0 auto; padding: 20px; }
.code { font-size: 32px; font-weight: bold; color: #007bff;
text-align: center; padding: 20px; background: #f8f9fa;
border-radius: 8px; margin: 20px 0; letter-spacing: 8px; }
.footer { margin-top: 30px; font-size: 12px; color: #666; }
.info { background: #e7f3ff; padding: 15px; border-radius: 8px; margin: 20px 0; }
</style>
</head>
<body>
<div class="container">
<h1>Подтверждение ${actionText}</h1>
${userDetails}
<div class="info">
<p><strong>Код подтверждения:</strong></p>
<div class="code">${code}</div>
<p>Код действителен в течение 5 минут.</p>
</div>
<div class="footer">
<p>Если вы не запрашивали это подтверждение, проигнорируйте это письмо.</p>
</div>
</div>
</body>
</html>
`;
};
const sendAdminConfirmationCode = async (code, action, userInfo) => {
const ownerEmail = config.ownerEmail || process.env.OWNER_EMAIL || 'aaem9848@gmail.com';
const actionText = action === 'add' ? 'добавления админа' : 'удаления админа';
const subject = `Код подтверждения ${actionText} - Nakama Moderation`;
const html = generateAdminConfirmationEmail(code, action, userInfo);
const text = `Код подтверждения ${actionText}: ${code}\n\nПользователь: @${userInfo?.username || 'не указан'}\nКод действителен 5 минут.`;
return await sendEmail(ownerEmail, subject, html, text);
};
// Инициализация при загрузке модуля
initializeEmailService();
module.exports = {
sendEmail,
sendVerificationCode,
sendAdminConfirmationCode,
initializeEmailService
};