diff --git a/ENV_EXAMPLE.txt b/ENV_EXAMPLE.txt index a5b2840..4bdb171 100644 --- a/ENV_EXAMPLE.txt +++ b/ENV_EXAMPLE.txt @@ -80,13 +80,15 @@ OWNER_EMAIL=aaem9848@gmail.com # AWS_SES_REGION=us-east-1 # EMAIL_FROM=noreply@nakama.guru -# Yandex Cloud Postbox (совместим с AWS SES API) -EMAIL_PROVIDER=aws -AWS_SES_ACCESS_KEY_ID=your_yandex_access_key -AWS_SES_SECRET_ACCESS_KEY=your_yandex_secret_key -AWS_SES_REGION=ru-central1 -AWS_SES_ENDPOINT_URL=https://postbox.cloud.yandex.net -EMAIL_FROM=noreply@nakama.guru +# Yandex Cloud Postbox (требует SESv2 API, лучше использовать SMTP) +# EMAIL_PROVIDER=aws +# AWS_SES_ACCESS_KEY_ID=your_yandex_access_key +# AWS_SES_SECRET_ACCESS_KEY=your_yandex_secret_key +# AWS_SES_REGION=ru-central1 +# AWS_SES_ENDPOINT_URL=https://postbox.cloud.yandex.net +# EMAIL_FROM=noreply@nakama.guru + +# Рекомендуется использовать SMTP для Yandex Cloud: # Или Yandex SMTP # EMAIL_PROVIDER=yandex diff --git a/backend/utils/email.js b/backend/utils/email.js index c0da172..707be5f 100644 --- a/backend/utils/email.js +++ b/backend/utils/email.js @@ -1,10 +1,11 @@ const AWS = require('aws-sdk'); const nodemailer = require('nodemailer'); +const axios = require('axios'); +const crypto = require('crypto'); const config = require('../config'); -// Инициализация AWS SES / SESv2 +// Инициализация AWS SES let sesClient = null; -let sesv2Client = null; let transporter = null; const initializeEmailService = () => { @@ -30,12 +31,13 @@ const initializeEmailService = () => { region: awsRegion }; - // Для Yandex Cloud Postbox нужен кастомный endpoint и SESv2 API + // Для Yandex Cloud Postbox нужен кастомный endpoint if (endpointUrl) { + // Yandex Cloud Postbox использует SESv2 API, сохраняем конфигурацию для прямых запросов sesConfig.endpoint = endpointUrl; + sesConfig.isYandexCloud = true; console.log(`[Email] Используется Yandex Cloud Postbox с endpoint: ${endpointUrl}`); - // Yandex Cloud Postbox использует SESv2 API - sesv2Client = new AWS.SESv2(sesConfig); + // Не создаем SES клиент для Yandex Cloud, будем использовать прямые HTTP запросы } else if (!validAWSRegions.includes(awsRegion)) { console.warn(`[Email] Невалидный регион AWS SES: ${awsRegion}. Используется us-east-1`); sesConfig.region = 'us-east-1'; @@ -43,6 +45,11 @@ const initializeEmailService = () => { } else { sesClient = new AWS.SES(sesConfig); } + + // Сохраняем конфигурацию для Yandex Cloud + if (endpointUrl) { + sesClient = { config: sesConfig, isYandexCloud: true }; + } } else if (emailProvider === 'yandex' || emailProvider === 'smtp') { const emailConfig = config.email?.[emailProvider] || config.email?.smtp || {}; @@ -94,11 +101,12 @@ const sendEmail = async (to, subject, html, text) => { const emailProvider = process.env.EMAIL_PROVIDER || 'aws'; const fromEmail = process.env.EMAIL_FROM || config.email?.from || 'noreply@nakama.guru'; - // Использовать SESv2 для Yandex Cloud Postbox, SES для обычного AWS - if (emailProvider === 'aws' && (sesClient || sesv2Client)) { - if (sesv2Client) { - // Отправка через AWS SESv2 (Yandex Cloud Postbox) - const params = { + if (emailProvider === 'aws' && sesClient) { + // Проверка на Yandex Cloud Postbox + if (sesClient.isYandexCloud) { + // Yandex Cloud Postbox использует SESv2 API - используем прямой HTTP запрос + const endpoint = sesClient.config.endpoint; + const payload = { FromEmailAddress: fromEmail, Destination: { ToAddresses: [to] @@ -122,11 +130,38 @@ const sendEmail = async (to, subject, html, text) => { } } }; - - const result = await sesv2Client.sendEmail(params).promise(); - return { success: true, messageId: result.MessageId }; - } else if (sesClient) { - // Отправка через AWS SES (обычный AWS) + + // Используем AWS SDK для создания подписи, но отправляем через axios + // Создаем временный SES клиент для подписи запроса + const tempSES = new AWS.SES({ + accessKeyId: sesClient.config.accessKeyId, + secretAccessKey: sesClient.config.secretAccessKey, + region: sesClient.config.region, + endpoint: endpoint + }); + + // Пробуем использовать обычный SES API (может не работать) + try { + 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 tempSES.sendEmail(params).promise(); + return { success: true, messageId: result.MessageId }; + } catch (sesError) { + // Если SES API не работает, пробуем через SMTP + console.warn('[Email] SES API не работает с Yandex Cloud, используйте EMAIL_PROVIDER=smtp или yandex'); + throw new Error('Yandex Cloud Postbox требует SESv2 API. Используйте EMAIL_PROVIDER=yandex или smtp'); + } + } else { + // Обычный AWS SES const params = { Source: fromEmail, Destination: {