# Email-рассылки клиентам

## Назначение
Транзакционные и маркетинговые email-рассылки клиентам клуба. Автоматические триггерные письма + ручные кампании из панели админа клуба.

## Технические параметры
- **Провайдер**: SMTP или API (SendGrid, Mailgun, Unisender — настраивается per-club)
- **Шаблоны**: HTML (Handlebars/MJML), адаптивная вёрстка, предпросмотр
- **Очередь**: BullMQ (throttling, retry при ошибках, batch-отправка)
- **Трекинг**: доставка (bounce/reject), открытия (tracking pixel), клики (redirect), отписки
- **Отписка**: обязательная ссылка Unsubscribe в каждом письме (CAN-SPAM / GDPR)
- **Rate limiting**: per-club лимит писем/мин для защиты от спам-блокировок

## Типы писем (5 автоматических)

| Тип | Триггер | Описание |
|-----|---------|----------|
| Приветственное | `client.created` | Приветствие, информация о клубе, первый визит |
| Напоминание о тренировке | За 24ч до тренировки | Дата, время, тренер, адрес |
| Истечение абонемента | За 7 дней до истечения | Уведомление + предложение продления |
| Акции и спецпредложения | Ручная рассылка | Маркетинговые кампании |
| День рождения | В день рождения клиента | Поздравление + персональная скидка |

## Ручные кампании (UI в панели админа клуба)
- Создание кампании: выбор шаблона, тема, контент (WYSIWYG-редактор)
- Сегментация аудитории: по абонементу, активности, дате последнего визита, тегам
- Расписание: отправить сейчас / запланировать на дату+время
- A/B тестирование: тема письма (2 варианта)
- Аналитика кампании: отправлено, доставлено, открыто, кликов, отписок, bounce

## NestJS-модуль `email/`

```typescript
email/
├── email.module.ts           // NestJS модуль, @RequireModule('email')
├── email.controller.ts       // REST API: /v1/email/*
├── email.service.ts          // Бизнес-логика: отправка, очереди, трекинг
├── email-template.service.ts // Рендеринг Handlebars/MJML шаблонов
├── email-provider.service.ts // Strategy: SMTP / SendGrid / Mailgun / Unisender
├── email-tracking.service.ts // Обработка webhook-ов от провайдера (bounce, open, click)
├── email-campaign.service.ts // Управление кампаниями, сегментация, расписание
├── processors/
│   └── email-send.processor.ts // BullMQ processor: batch-отправка
├── dto/
│   ├── create-template.dto.ts
│   ├── create-campaign.dto.ts
│   └── send-email.dto.ts
└── entities/
    ├── email-template.entity.ts
    ├── email-campaign.entity.ts
    └── email-log.entity.ts
```

## Prisma-модели (ключевые)

```prisma
model EmailTemplate {
  id        String   @id @default(uuid())
  clubId    String   @map("club_id")
  name      String
  subject   String
  bodyHtml  String   @map("body_html")
  type      EmailTemplateType  // welcome, reminder, expiring, promo, birthday
  isActive  Boolean  @default(true)
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
  club      Club     @relation(fields: [clubId], references: [id])
}

model EmailCampaign {
  id            String              @id @default(uuid())
  clubId        String              @map("club_id")
  templateId    String              @map("template_id")
  name          String
  subject       String
  status        EmailCampaignStatus // draft, scheduled, sending, sent, cancelled
  segmentFilter Json?
  scheduledAt   DateTime?
  sentAt        DateTime?
  totalSent     Int    @default(0)
  totalOpened   Int    @default(0)
  totalClicked  Int    @default(0)
  totalBounced  Int    @default(0)
  totalUnsub    Int    @default(0)
  createdAt     DateTime @default(now())
  club          Club     @relation(fields: [clubId], references: [id])
  template      EmailTemplate @relation(fields: [templateId], references: [id])
}

model EmailLog {
  id         String      @id @default(uuid())
  clubId     String      @map("club_id")
  campaignId String?     @map("campaign_id")
  clientId   String      @map("client_id")
  email      String
  subject    String
  status     EmailStatus // queued, sent, delivered, opened, clicked, bounced, rejected, unsubscribed
  sentAt     DateTime?
  openedAt   DateTime?
  clickedAt  DateTime?
  errorMsg   String?
}
```

## Provider Strategy (переключаемый per-club)

```typescript
interface EmailProvider {
  send(options: SendEmailOptions): Promise<EmailSendResult>;
  validateConfig(config: EmailProviderConfig): Promise<boolean>;
}

class SmtpProvider implements EmailProvider { ... }
class SendGridProvider implements EmailProvider { ... }
class MailgunProvider implements EmailProvider { ... }
class UnisenderProvider implements EmailProvider { ... }
```

## Env-переменные

```
EMAIL_PROVIDER=smtp|sendgrid|mailgun|unisender
EMAIL_SMTP_HOST=smtp.example.com
EMAIL_SMTP_PORT=587
EMAIL_SMTP_USER=
EMAIL_SMTP_PASS=
EMAIL_SENDGRID_API_KEY=
EMAIL_MAILGUN_API_KEY=
EMAIL_MAILGUN_DOMAIN=
EMAIL_DEFAULT_FROM=noreply@myfitcrm.ru
EMAIL_DEFAULT_FROM_NAME=MyFitCRM
EMAIL_TRACKING_DOMAIN=track.myfitcrm.ru
EMAIL_BATCH_SIZE=50
EMAIL_RATE_LIMIT=100
```

## Ограничения v1
- Без drag-and-drop визуального редактора шаблонов (только WYSIWYG + код)
- Без A/B тестирования контента (только тема)
- Без цепочек писем (drip campaigns) — только одиночные рассылки
