Files
ntspi-app/app/Containers/Dashboard/README_EMAIL_NEWS.md
T
2026-03-23 10:50:31 +05:00

9.1 KiB
Raw Blame History

📧 Email News Fetching

Автоматическое получение новостей из Email и создание черновиков в системе.

📋 Описание

Функция позволяет автоматически:

  • Подключаться к IMAP-серверу
  • Получать непрочитанные письма от редактора
  • Скачивать вложения (DOC, DOCX, изображения)
  • Создавать новости через существующий ProcessMixedFilesAction
  • Помечать обработанные письма как прочитанные

🏗 Архитектура (Porto)

app/Containers/Dashboard/
├── Actions/
│   └── FetchEmailNewsAction.php          # Оркестрация процесса
├── Tasks/
│   ├── ConnectToImapTask.php             # IMAP подключение
│   ├── FetchUnreadEmailsTask.php         # Получение писем
│   ├── FilterBySenderTask.php            # Фильтрация по отправителю
│   ├── DownloadAttachmentsTask.php       # Загрузка вложений
│   └── MarkEmailAsReadTask.php           # Пометка как прочитанное
├── Data/
│   └── EmailAttachmentData.php           # DTO для вложений
├── Exceptions/
│   └── EmailFetchException.php           # Исключения
├── Commands/
│   └── FetchEmailNewsCommand.php         # Artisan команда
└── Configs/
    └── email-news.php                    # Конфигурация

🔧 Установка

1. Пересобрать PHP-контейнер (требуется расширение IMAP)

docker-compose down
docker-compose build --no-cache ntspi-php
docker-compose up -d

2. Настроить переменные окружения

Скопируйте .env.email-news.example в .env и заполните:

EMAIL_NEWS_ENABLED=true
EMAIL_NEWS_IMAP_HOST=imap.yandex.ru
EMAIL_NEWS_IMAP_PORT=993
EMAIL_NEWS_ENCRYPTION=ssl
EMAIL_NEWS_IMAP_USER=news@ntspi.ru
EMAIL_NEWS_IMAP_PASS=app_password
EMAIL_NEWS_SENDER_EMAIL=editor@example.com
EMAIL_NEWS_FOLDER=INBOX

3. Протестировать подключение

Запустите команду вручную:

docker exec -it ntspi-php php artisan email:fetch-news --log

📝 Использование

Ручной запуск

# Обычный запуск
docker exec -it ntspi-php php artisan email:fetch-news

# С подробным логом
docker exec -it ntspi-php php artisan email:fetch-news --log

# Принудительный запуск (если отключено в конфиге)
docker exec -it ntspi-php php artisan email:fetch-news --force

Автоматический запуск (Cron)

Команда автоматически добавлена в расписание Laravel Scheduler:

  • Частота: каждые 5 минут
  • Защита от перекрытий: withoutOverlapping()
  • Один сервер: onOneServer()

Scheduler уже настроен в app/Ship/Kernels/ConsoleKernel.php.

Убедитесь, что Cron запущен в контейнере:

# Проверьте crontab
docker exec -it ntspi-php crontab -l

# Должно быть:
# * * * * * php /var/www/artisan schedule:run >> /dev/null 2>&1

🔐 Безопасность

Фильтрация отправителей

Обрабатываются только письма от редактора, указанного в EMAIL_NEWS_SENDER_EMAIL.

Письма от других отправителей:

  • Не обрабатываются
  • Не скачиваются
  • Логируются (если EMAIL_NEWS_LOG_SKIPPED=true)
  • Остаются в папке (не помечаются прочитанными)

Whitelist нескольких отправителей

В конфиге app/Containers/Dashboard/Configs/email-news.php можно указать несколько email:

'allowed_senders' => [
    env('EMAIL_NEWS_SENDER_EMAIL'),
    env('EMAIL_NEWS_SENDER_EMAIL_2'),
    env('EMAIL_NEWS_SENDER_EMAIL_3'),
],

App-Specific Password

Рекомендуется использовать специальный пароль приложения вместо основного пароля:

📊 Логирование

Логи доступны в storage/logs/laravel.log:

[2024-01-15 10:30:00] local.INFO: [FetchEmailNewsAction] Начало получения новостей из Email
[2024-01-15 10:30:01] local.INFO: [ConnectToImapTask] Успешное подключение к IMAP
[2024-01-15 10:30:02] local.INFO: [FetchUnreadEmailsTask] Получены письма: count=3
[2024-01-15 10:30:02] local.INFO: [FilterBySenderTask] Фильтрация писем: total=3, filtered=2, skipped=1
[2024-01-15 10:30:05] local.INFO: [FetchEmailNewsAction:processEmail] Письмо успешно обработано: post_id=123

⚠️ Обработка ошибок

Типичные ошибки

Ошибка Причина Решение
Не удалось подключиться к IMAP-серверу Неправильный хост/порт/пароль Проверьте .env настройки
IMAP-папка не найдена Папка не существует Проверьте имя папки в EMAIL_NEWS_FOLDER
Письмо получено от неразрешённого отправителя Отправитель не в whitelist Добавьте email в allowed_senders
Нет DOC/DOCX файла для извлечения текста Во вложениях нет документа Редактор должен прикрепить DOC/DOCX

Отладка

# Запуск с подробным выводом
docker exec -it ntspi-php php artisan email:fetch-news --log

# Просмотр последних логов
docker exec -it ntspi-php tail -f storage/logs/laravel.log

# Проверка расширения IMAP
docker exec -it ntspi-php php -m | grep imap

🔄 Поток данных

┌─────────────────────────────────────────────────────────┐
│  Cron (каждые 5 мин) → php artisan email:fetch-news    │
│                    ↓                                    │
│  FetchEmailNewsCommand                                  │
│                    ↓                                    │
│  FetchEmailNewsAction                                   │
│  ├─ ConnectToImapTask (IMAP-соединение)                │
│  ├─ FetchUnreadEmailsTask (получение писем)            │
│  ├─ FilterBySenderTask (проверка отправителя)          │
│  ├─ DownloadAttachmentsTask (скачивание вложений)      │
│  └─ ProcessMixedFilesAction (создание поста) ←───┐    │
│                    ↓                              │    │
│  MarkEmailAsReadTask (пометка как прочитанное)    │    │
└───────────────────────────────────────────────────┼────┘
                                                    │
                    ┌───────────────────────────────┘
                    ↓
         Существующий процесс создания новости
         (AI-распознавание, сжатие изображений, и т.д.)

🧪 Тестирование

Отправка тестового письма

  1. Отправьте письмо с EMAIL_NEWS_SENDER_EMAIL на EMAIL_NEWS_IMAP_USER
  2. Прикрепите DOC/DOCX файл (текст новости)
  3. Прикрепите изображения (опционально)
  4. Запустите команду:
docker exec -it ntspi-php php artisan email:fetch-news --log
  1. Проверьте создание новости в Dashboard

Мок-тестирование (для разработчиков)

// В Unit-тестах можно моковать IMAP
$this->mock(ClientManager::class, function ($mock) {
    $mock->shouldReceive('account')
         ->with('email_news')
         ->andReturn($client);
});

📚 Ссылки