From cc209060627991fefbad2165db04dfa8f4d89ded Mon Sep 17 00:00:00 2001 From: F4ilji Date: Mon, 6 Apr 2026 22:17:21 +0500 Subject: [PATCH] =?UTF-8?q?fix(IMAP):=20=D0=B8=D1=81=D0=BF=D1=80=D0=B0?= =?UTF-8?q?=D0=B2=D0=B8=D1=82=D1=8C=20=D0=B7=D0=B0=D0=B3=D1=80=D1=83=D0=B7?= =?UTF-8?q?=D0=BA=D1=83=20=D0=B2=D0=BB=D0=BE=D0=B6=D0=B5=D0=BD=D0=B8=D0=B9?= =?UTF-8?q?=20=E2=80=94=20setFetchBody(true)=20=D0=BD=D0=B5=D0=BE=D0=B1?= =?UTF-8?q?=D1=85=D0=BE=D0=B4=D0=B8=D0=BC=20=D0=B4=D0=BB=D1=8F=20=D1=81?= =?UTF-8?q?=D1=82=D1=80=D1=83=D0=BA=D1=82=D1=83=D1=80=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Проблема: setFetchBody(false) не загружал структуру письма, поэтому getAttachments() возвращал пустой список. Исправления: - FetchUnreadEmailsTask: setFetchBody(true) для загрузки структуры (вложения) - FetchUnreadEmailsTask: конвертация Attribute в строку для subject - config/imap.php: убраны fetch_body/fetch_flags (контроль на уровне Query) - Обновлена документация Fix: "В письме не найдено вложений" ошибка при обработке email Co-authored-by: Qwen-Coder --- .../Dashboard/README_EMAIL_OPTIMIZATION.md | 24 ++++++++++--------- .../Tasks/Email/FetchUnreadEmailsTask.php | 13 ++++++---- config/imap.php | 9 ++----- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/app/Containers/Dashboard/README_EMAIL_OPTIMIZATION.md b/app/Containers/Dashboard/README_EMAIL_OPTIMIZATION.md index 9fce243..af7fdf7 100644 --- a/app/Containers/Dashboard/README_EMAIL_OPTIMIZATION.md +++ b/app/Containers/Dashboard/README_EMAIL_OPTIMIZATION.md @@ -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 diff --git a/app/Containers/Dashboard/Tasks/Email/FetchUnreadEmailsTask.php b/app/Containers/Dashboard/Tasks/Email/FetchUnreadEmailsTask.php index fc56e32..016522d 100644 --- a/app/Containers/Dashboard/Tasks/Email/FetchUnreadEmailsTask.php +++ b/app/Containers/Dashboard/Tasks/Email/FetchUnreadEmailsTask.php @@ -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(), ]; diff --git a/config/imap.php b/config/imap.php index e45714e..321ca53 100644 --- a/config/imap.php +++ b/config/imap.php @@ -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