Add hotel registration with email confirmation (nodemailer, confirm-email endpoint)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-17 17:30:07 +03:00
parent c06f4bf553
commit 152a8c0463
6 changed files with 259 additions and 5 deletions

56
backend/src/email.ts Normal file
View File

@@ -0,0 +1,56 @@
import nodemailer from 'nodemailer'
const transporter = nodemailer.createTransport({
host: process.env.SMTP_HOST ?? 'smtp.timeweb.ru',
port: parseInt(process.env.SMTP_PORT ?? '465', 10),
secure: true,
auth: {
user: process.env.SMTP_USER ?? 'noreply@hotelsync.ru',
pass: process.env.SMTP_PASS ?? '08K28150zBwii32c85',
},
})
export async function sendConfirmationEmail(to: string, name: string, token: string): Promise<void> {
const apiUrl = process.env.API_URL ?? 'https://api.hotelsync.ru'
const confirmUrl = `${apiUrl}/api/auth/confirm-email?token=${token}`
const fromAddr = process.env.SMTP_USER ?? 'noreply@hotelsync.ru'
await transporter.sendMail({
from: `"HotelSync" <${fromAddr}>`,
to,
subject: 'Подтвердите email — HotelSync',
html: `<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"></head>
<body style="font-family:Arial,sans-serif;background:#f1f5f9;margin:0;padding:40px 16px;">
<div style="max-width:520px;margin:0 auto;background:#fff;border-radius:16px;overflow:hidden;box-shadow:0 4px 24px rgba(0,0,0,0.08);">
<div style="background:linear-gradient(135deg,#4f46e5,#6366f1);padding:32px 40px;text-align:center;">
<div style="display:inline-block;width:48px;height:48px;background:rgba(255,255,255,0.2);border-radius:12px;line-height:48px;font-size:24px;margin-bottom:12px;">🏨</div>
<h1 style="color:#fff;margin:0;font-size:26px;font-weight:700;letter-spacing:-0.5px;">HotelSync</h1>
<p style="color:#c7d2fe;margin:6px 0 0;font-size:14px;">Современная PMS-система</p>
</div>
<div style="padding:40px;">
<h2 style="color:#1e293b;font-size:20px;margin:0 0 12px;font-weight:600;">Добро пожаловать, ${name}!</h2>
<p style="color:#475569;line-height:1.7;margin:0 0 28px;font-size:15px;">
Спасибо за регистрацию в HotelSync. Для активации аккаунта нажмите на кнопку ниже.
</p>
<div style="text-align:center;margin:0 0 28px;">
<a href="${confirmUrl}" style="display:inline-block;background:#4f46e5;color:#fff;text-decoration:none;padding:14px 36px;border-radius:10px;font-weight:600;font-size:16px;letter-spacing:0.2px;">
✓ Подтвердить email
</a>
</div>
<p style="color:#94a3b8;font-size:13px;margin:0 0 16px;line-height:1.6;background:#f8fafc;padding:12px 16px;border-radius:8px;border-left:3px solid #e2e8f0;">
⏱ Ссылка действительна <strong>24 часа</strong>.<br>
Если вы не регистрировались — просто проигнорируйте это письмо.
</p>
<hr style="border:none;border-top:1px solid #e2e8f0;margin:20px 0;">
<p style="color:#94a3b8;font-size:12px;margin:0;line-height:1.6;">
Кнопка не работает? Скопируйте ссылку в браузер:<br>
<a href="${confirmUrl}" style="color:#6366f1;word-break:break-all;font-size:11px;">${confirmUrl}</a>
</p>
</div>
</div>
</body>
</html>`,
})
}