9.1 KiB
9.1 KiB
📧 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
Рекомендуется использовать специальный пароль приложения вместо основного пароля:
- Yandex: https://passport.yandex.ru/profile/passwords
- Google: https://myaccount.google.com/apppasswords
- Mail.ru: https://account.mail.ru/security
📊 Логирование
Логи доступны в 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-распознавание, сжатие изображений, и т.д.)
🧪 Тестирование
Отправка тестового письма
- Отправьте письмо с
EMAIL_NEWS_SENDER_EMAILнаEMAIL_NEWS_IMAP_USER - Прикрепите DOC/DOCX файл (текст новости)
- Прикрепите изображения (опционально)
- Запустите команду:
docker exec -it ntspi-php php artisan email:fetch-news --log
- Проверьте создание новости в Dashboard
Мок-тестирование (для разработчиков)
// В Unit-тестах можно моковать IMAP
$this->mock(ClientManager::class, function ($mock) {
$mock->shouldReceive('account')
->with('email_news')
->andReturn($client);
});