# Уведомления в приложении и почта через очередь

Используйте сервис уведомлений для закрытого списка входящих сообщений и необязательной фоновой почты. Вставка входящего сообщения в SQL и добавление задания в очередь используют одну транзакцию базы данных. Доставка писем выполняется в отдельном процессе под управлением диспетчера. Это отличается от существующего синхронного транспорта подтверждения учётной записи и восстановления пароля.

## Подготовка и регистрация

```bash
php elang platform:setup
```

Зарегистрируйте провайдер в начальной загрузке, которую используют и HTTP-запросы, и обработчики очереди:

```php
$app->provider(new Elang\Notification\Provider());
```

Провайдер регистрирует фиксированный обработчик `notification.mail`. Данные JSON не могут выбирать произвольные классы PHP или код. Почтовые данные шифруются под `APP_KEY` перед попаданием в очередь. Сохраняйте этот ключ постоянным и создавайте его резервную копию. Текст входящих сообщений закрыт через авторизацию, но автоматически не шифруется при хранении; применяйте шифрование базы данных и диска, подходящее вашим данным.

## Отправка и чтение

```php
$notifications = $app->container->get(Elang\Notification\Notifications::class);
$id = $notifications->send(
    $user,
    'Export ready',
    'Your requested report is ready to review.',
    '/reports/42',
    mail: true,
);
$inbox = $notifications->inbox($user);
$notifications->markRead($user, $id);
```

Темы ограничены 160 символами, тела — 16 000 байтами. Необязательные ссылки должны быть локальными путями не длиннее 500 байт; ссылки без указания протокола, обратные косые черты, управляющие символы и пробелы отклоняются. Отображайте текст с экранированием шаблона. Запросы входящих сообщений и обновления отметки о прочтении всегда ограничиваются `user_id`; другой пользователь не может отметить ваше сообщение прочитанным. Сервис возвращает последние 100 входящих записей.

Ссылка уведомления — средство перехода, а не авторизация. Назначение всё равно должно проверять принадлежность записи или членство в команде. Для данных арендатора помещайте в текст входящего сообщения или письма только минимальную полезную информацию: удаление участника не может стереть уже доставленное ему письмо.

## Настройка реальной почты

```dotenv
MAILER_DSN=smtp://username:encoded-password@smtp.example.com:587
MAIL_FROM=notifications@example.com
```

Храните реальные значения вне Git и кодируйте учётные данные в DSN в формате URL. Предпочитайте менеджер секретов или защищённый файл окружения. Используйте документированные настройки TLS провайдера транспорта. Настройте SPF, DKIM и DMARC для домена отправителя, подтвердите разрешённого отправителя и проверьте обработку возвратов и жалоб. Один настроенный DSN не доказывает доставку или репутацию домена.

```bash
php elang queue:work
php elang queue:failed
```

`null://null` намеренно отклоняется доставкой уведомлений через очередь, чтобы обработчик не отбрасывал письма незаметно. Сервер перехвата SMTP для разработки, например Mailpit, принимает сообщения без отправки реальным получателям. Подтверждение учётной записи и восстановление уже предоставляют зашифрованный локальный почтовый ящик при `APP_ENV=local`, когда транспорт пустой; этот ящик — удобство разработки, а не почтовый сервис рабочей среды.

## Повторные попытки и семантика доставки

Обработчик резервирует задание с ограниченным сроком и защитой от устаревшего владельца, повторяет попытки с ограниченной задержкой и записывает класс исключения без тел сообщений или учётных данных. Изучите метаданные неудачного задания, устраните причину, затем повторите проверенное задание:

```bash
php elang queue:retry JOB_ID_FROM_FAILED_LIST
```

Доставка выполняется как минимум один раз. Если SMTP-сервер принял письмо, но обработчик потерял подтверждение или завершился до окончания задания, повторная попытка может отправить его снова. Для провайдеров, поддерживающих идемпотентность, добавьте постоянный ключ доставки и адаптер конкретного провайдера. Никогда не обещайте отправку почты ровно один раз.

Длительность заданий должна быть меньше настроенного срока резервирования, либо реализуйте проверенную политику продления. Не помещайте исходные ссылки подтверждения, токены, пароли или персональные данные в незашифрованные данные заданий. Отслеживайте задержку очереди, сбои, сигналы активности обработчиков и накопление outbox. См. [эксплуатацию](/docs/v0.1/observability), [почту](/docs/v0.1/mail) и [очереди](/docs/v0.1/queues).
