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:
@@ -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
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user