106 lines
4.2 KiB
JavaScript
106 lines
4.2 KiB
JavaScript
const nodemailer = require('nodemailer');
|
||
|
||
let transporter = null;
|
||
let emailEnabled = true; // по умолчанию включено, при ошибке станет false
|
||
let verificationDone = false; // проверка выполнена хотя бы раз
|
||
|
||
function createTransporter() {
|
||
if (!process.env.SMTP_HOST || !process.env.SMTP_USER || !process.env.SMTP_PASS) {
|
||
console.warn('[MAILER] SMTP не настроен (отсутствуют переменные окружения). Почтовые уведомления отключены.');
|
||
return null;
|
||
}
|
||
return nodemailer.createTransport({
|
||
host: process.env.SMTP_HOST,
|
||
port: parseInt(process.env.SMTP_PORT) || 587,
|
||
secure: false,
|
||
auth: {
|
||
user: process.env.SMTP_USER,
|
||
pass: process.env.SMTP_PASS
|
||
}
|
||
});
|
||
}
|
||
|
||
// Функция проверки соединения с почтовым сервером
|
||
async function verifyEmailConnection() {
|
||
if (verificationDone) return emailEnabled;
|
||
|
||
transporter = createTransporter();
|
||
if (!transporter) {
|
||
emailEnabled = false;
|
||
verificationDone = true;
|
||
return false;
|
||
}
|
||
|
||
try {
|
||
await transporter.verify();
|
||
console.log('[MAILER] SMTP подключение успешно, уведомления активны.');
|
||
emailEnabled = true;
|
||
} catch (err) {
|
||
console.error('[MAILER] Ошибка подключения к SMTP:', err.message);
|
||
console.warn('[MAILER] Почтовые уведомления будут отключены до следующего перезапуска.');
|
||
emailEnabled = false;
|
||
transporter = null; // сбросим, чтобы не использовать нерабочий
|
||
} finally {
|
||
verificationDone = true;
|
||
}
|
||
return emailEnabled;
|
||
}
|
||
|
||
async function sendNotification(emails, subject, text) {
|
||
if (!emailEnabled) {
|
||
// Молча пропускаем, т.к. проверка уже показала неработоспособность
|
||
return;
|
||
}
|
||
if (!emails) return;
|
||
const recipients = emails.split(',').map(e => e.trim()).filter(Boolean);
|
||
if (recipients.length === 0) return;
|
||
|
||
// Если транспортер ещё не создан (не было вызова verify), создадим его
|
||
if (!transporter) {
|
||
transporter = createTransporter();
|
||
if (!transporter) {
|
||
emailEnabled = false;
|
||
return;
|
||
}
|
||
}
|
||
|
||
try {
|
||
await transporter.sendMail({
|
||
from: process.env.SMTP_USER,
|
||
to: recipients.join(','),
|
||
subject,
|
||
text
|
||
});
|
||
console.log(`Уведомление отправлено на ${recipients.join(', ')}`);
|
||
} catch (err) {
|
||
console.error('Ошибка отправки письма:', err);
|
||
// Если при отправке возникла ошибка, считаем почту нерабочей до перезапуска
|
||
if (emailEnabled) {
|
||
console.warn('[MAILER] Отключение почтовых уведомлений из-за ошибки отправки.');
|
||
emailEnabled = false;
|
||
}
|
||
}
|
||
}
|
||
|
||
async function notifyNewBooking(booking) {
|
||
const subject = `Новая заявка №${booking.external_id} (${process.env.SERVICE_NAME})`;
|
||
const text = `Поступила новая заявка на заселение.\n
|
||
Имя: ${booking.name}
|
||
Телефон: ${booking.phone_raw}
|
||
Даты: с ${booking.checkin_date} по ${booking.checkout_date}
|
||
Взрослых: ${booking.adults}, детей: ${booking.children}
|
||
Ссылка: ${process.env.SERVICE_URL}/admin/bookings`;
|
||
await sendNotification(process.env.EMAIL_NOTIFY_NEW, subject, text);
|
||
}
|
||
|
||
async function notifyBookingUpdate(booking, changes) {
|
||
const subject = `Изменение заявки №${booking.external_id} (${process.env.SERVICE_NAME})`;
|
||
const text = `Заявка №${booking.external_id} была изменена.\n
|
||
Новый статус: ${booking.status}
|
||
Комментарий: ${booking.comments || 'нет'}
|
||
Изменения: ${JSON.stringify(changes, null, 2)}
|
||
Ссылка: ${process.env.SERVICE_URL}/admin/bookings`;
|
||
await sendNotification(process.env.EMAIL_NOTIFY_UPDATE, subject, text);
|
||
}
|
||
|
||
module.exports = { verifyEmailConnection, notifyNewBooking, notifyBookingUpdate }; |