fix(IMAP): исправить загрузку вложений — setFetchBody(true) необходим для структуры

Проблема: setFetchBody(false) не загружал структуру письма,
поэтому getAttachments() возвращал пустой список.

Исправления:
- FetchUnreadEmailsTask: setFetchBody(true) для загрузки структуры (вложения)
- FetchUnreadEmailsTask: конвертация Attribute в строку для subject
- config/imap.php: убраны fetch_body/fetch_flags (контроль на уровне Query)
- Обновлена документация

Fix: "В письме не найдено вложений" ошибка при обработке email

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
F4ilji
2026-04-06 22:17:21 +05:00
co-authored by Qwen-Coder
parent c115a5c7a7
commit cc20906062
3 changed files with 23 additions and 23 deletions
@@ -19,38 +19,40 @@ Allowed memory size of 268435456 bytes exhausted (tried to allocate 6291480 byte
### Уровень 1: Конфигурация (config/imap.php)
Добавлены настройки для предотвращения загрузки тел сообщений:
Добавлены настройки для предотвращения загрузки лишних данных:
```php
'options' => [
'fetch' => \Webklex\PHPIMAP\IMAP::FT_PEEK, // Не помечать как прочитанные
'message_key' => 'id', // Использовать UID
'fetch_body' => false, // НЕ загружать тела
'fetch_flags' => false, // НЕ загружать флаги
'fetch_limit' => env('IMAP_FETCH_LIMIT', 20), // Лимит сообщений
],
```
**Результат:** Загружаются только заголовки писем (subject, from, date), тела и вложения НЕ загружаются.
**Важно:** `fetch_body` и `fetch_flags` контролируются на уровне Query (`setFetchBody()`, `setFetchFlags()`), а не в конфиге, чтобы не ломать загрузку вложений.
**Результат:** Письма не помечаются как прочитанные автоматически, используется лимит на количество сообщений.
---
### Уровень 2: Оптимизация кода
#### 2A. FetchUnreadEmailsTask
- Добавлен `setFetchBody(false)`явное отключение загрузки тел
- Добавлен `setFetchFlags(false)` — отключение загрузки флагов
- Добавлен параметр `$limit` для контроля количества сообщений
- Добавлен параметр `$offset` для пагинации
- `setFetchBody(true)`загружаем структуру письма (необходимо для вложений)
- `setFetchFlags(false)` — отключаем загрузку флагов (экономия памяти)
- Параметр `$limit` для контроля количества сообщений
- Добавлен мониторинг памяти через `MemoryAwareTrait`
```php
$query = $folder->messages()
->unseen()
->setFetchBody(false) // ← КРИТИЧНО
->setFetchFlags(false)
->limit($limit);
->setFetchBody(true) // Загружаем структуру (нужна для вложений)
->setFetchFlags(false) // Флаги не нужны
->limit($limit); // Лимит сообщений
```
**Важно:** `setFetchBody(true)` необходим для загрузки структуры письма, которая содержит информацию о вложениях. Без этого `getAttachments()` возвращает пустой список.
#### 2B. FetchEmailNewsAction
- Реализована **batch-обработка** (по 10 писем за цикл)
- Добавлена **принудительная сборка мусора** после каждого batch
@@ -35,12 +35,12 @@ class FetchUnreadEmailsTask
]);
try {
// OPTIMIZATION: Загружаем только заголовки (без тел и вложений)
// setFetchBody(false) предотвращает загрузку raw_body и structure
// NOTE: setFetchBody(true) необходим для загрузки структуры письма (вложения)
// Контроль памяти осуществляется через limit() и batch-обработку в Action
$query = $folder->messages()
->unseen()
->setFetchBody(false)
->setFetchFlags(false);
->setFetchBody(true) // Загружаем структуру (нужна для вложений)
->setFetchFlags(false); // Флаги не нужны
// Применяем лимит для предотвращения переполнения памяти
if ($limit > 0) {
@@ -53,6 +53,7 @@ class FetchUnreadEmailsTask
foreach ($messages as $message) {
// OPTIMIZATION: Извлекаем только метаданные (не загружаем тело)
$from = $message->getFrom()[0] ?? null;
$subjectAttr = $message->getSubject();
$emails[] = [
'message' => $message,
@@ -60,8 +61,10 @@ class FetchUnreadEmailsTask
'uid' => $message->getUid(),
'from_email' => $from?->mail ?? null,
'from_name' => $from?->name ?? null,
'subject' => $message->getSubject(),
// FIX: Attribute объект нужно конвертировать в строку
'subject' => $subjectAttr instanceof \Webklex\PHPIMAP\Attribute ? (string) $subjectAttr : ($subjectAttr ?? 'Без темы'),
'date' => $message->getDate(),
// NOTE: hasAttachments() может быть неточным без загрузки структуры
'has_attachments' => $message->hasAttachments(),
'size' => $message->getSize(),
];
+2 -7
View File
@@ -93,18 +93,13 @@ return [
],
// OPTIMIZATION: Fetch method - FT_PEEK prevents marking messages as read automatically
// This also reduces memory usage by not loading full message bodies by default
'fetch' => \Webklex\PHPIMAP\IMAP::FT_PEEK,
// OPTIMIZATION: Use UID as message key for better reliability
'message_key' => 'id',
// OPTIMIZATION: Do not fetch message bodies by default
// Bodies will be loaded only when explicitly needed (lazy loading)
'fetch_body' => false,
// OPTIMIZATION: Do not fetch flags by default (reduces memory)
'fetch_flags' => false,
// NOTE: fetch_body и fetch_flags контролируются на уровне Query (setFetchBody/setFetchFlags)
// Глобальные настройки здесь не применяются, чтобы не ломать вложения
// OPTIMIZATION: Limit number of messages fetched per query
// Prevents memory overflow when processing large mailboxes