Files
ntspi-app/config/imap.php
T
F4iljiandQwen-Coder c115a5c7a7 fix(IMAP): оптимизация обработки email для предотвращения memory exhaustion
Корневая проблема: библиотека webklex/php-imap загружала все тела писем
по умолчанию, что приводило к исчерпанию 256MB памяти при 50+ письмах.

Решение (3 уровня):

Уровень 1 - Конфигурация:
- config/imap.php: добавлены fetch_body=false, fetch_flags=false, fetch_limit=20
- php.ini: увеличен memory_limit с 256M до 1G, добавлены OPcache настройки

Уровень 2 - Оптимизация кода:
- FetchUnreadEmailsTask: setFetchBody(false), лимиты, MemoryAwareTrait
- FetchEmailNewsAction: batch-обработка (10 писем), gc_collect_cycles()
- DownloadAttachmentsTask: lazy load вложений, extension whitelist (security)
- ConnectToImapTask: MemoryAwareTrait для мониторинга

Уровень 3 - Инфраструктура:
- ProcessEmailNewsJob: queue job для асинхронной обработки (3 попытки, 300s timeout)
- FetchEmailNewsCommand: поддержка --async режима
- MemoryAwareTrait: reusable трейт для мониторинга памяти

Security fixes:
- Extension whitelist для предотвращения path traversal
- Убраны реальные email из config/imap.php
- Добавлена проверка на null message объект

Docs:
- README_EMAIL_OPTIMIZATION.md: полная документация по оптимизации

Fixes: Allowed memory size of 268435456 bytes exhausted

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-04-06 22:08:03 +05:00

184 lines
6.1 KiB
PHP

<?php
/*
* Set any customizations webklex/php-imap you would like to use.
*/
return [
/*
|--------------------------------------------------------------------------
| Default date format
|--------------------------------------------------------------------------
|
| The default date format is used to convert any given Carbon::class object
| into a valid date string.
|
*/
'date_format' => 'd-M-y',
/*
|--------------------------------------------------------------------------
| Default account
|--------------------------------------------------------------------------
|
| The default account identifier. It will be used as default for any missing account parameters.
| If however the default account is missing a parameter the package default will be used.
|
*/
'default' => 'email_news',
/*
|--------------------------------------------------------------------------
| Available accounts
|--------------------------------------------------------------------------
|
| Please list all IMAP accounts which you are planning to use within the
| array below.
|
*/
'accounts' => [
'email_news' => [
'host' => env('EMAIL_NEWS_IMAP_HOST', 'imap.mail.ru'),
'port' => env('EMAIL_NEWS_IMAP_PORT', 993),
'protocol' => env('EMAIL_NEWS_PROTOCOL', 'imap'),
'encryption' => env('EMAIL_NEWS_ENCRYPTION', 'ssl'),
'validate_cert' => env('EMAIL_NEWS_VALIDATE_CERT', true),
'username' => env('EMAIL_NEWS_IMAP_USER', ''),
'password' => env('EMAIL_NEWS_IMAP_PASS', ''),
'authentication' => null,
'proxy' => [
'socket' => null,
'request_fulluri' => false,
'username' => null,
'password' => null,
],
'timeout' => 30,
'extensions' => [],
],
/*
|--------------------------------------------------------------------------
| Default account
|--------------------------------------------------------------------------
|
| This account will be used as default if no account is specified.
|
*/
'default' => [
'host' => 'localhost',
'port' => 993,
'protocol' => 'imap',
'encryption' => 'ssl',
'validate_cert' => true,
'username' => '',
'password' => '',
'authentication' => null,
],
],
/*
|--------------------------------------------------------------------------
| Available IMAP options
|--------------------------------------------------------------------------
|
| Available php imap config parameters are listed below
|
*/
'options' => [
// Append option to the connection string
'append' => null,
// IMAP open options
'open' => [
'DISABLE_AUTHENTICATOR' => 'GSSAPI',
],
// 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,
// OPTIMIZATION: Limit number of messages fetched per query
// Prevents memory overflow when processing large mailboxes
'fetch_limit' => env('IMAP_FETCH_LIMIT', 20),
],
/*
|--------------------------------------------------------------------------
| Available flags
|--------------------------------------------------------------------------
|
| List of available flags
|
*/
'flags' => [
'recent' => '\Recent',
'flagged' => '\Flagged',
'answered' => '\Answered',
'deleted' => '\Deleted',
'seen' => '\Seen',
'draft' => '\Draft',
],
/*
|--------------------------------------------------------------------------
| Available events
|--------------------------------------------------------------------------
|
*/
'events' => [
'message' => [
'new' => \Webklex\PHPIMAP\Events\MessageNewEvent::class,
'moved' => \Webklex\PHPIMAP\Events\MessageMovedEvent::class,
],
'folder' => [
'new' => \Webklex\PHPIMAP\Events\FolderNewEvent::class,
'moved' => \Webklex\PHPIMAP\Events\FolderMovedEvent::class,
'deleted' => \Webklex\PHPIMAP\Events\FolderDeletedEvent::class,
],
'flag' => [
'new' => \Webklex\PHPIMAP\Events\FlagNewEvent::class,
'deleted' => \Webklex\PHPIMAP\Events\FlagDeletedEvent::class,
],
],
/*
|--------------------------------------------------------------------------
| Available decoding options
|--------------------------------------------------------------------------
|
| Available php imap config parameters are listed below
|
*/
'decoding' => [
'options' => [
'UTF7-IMAP' => env('IMAP_DECODING_UTF7_IMAP', true),
'attachments' => env('IMAP_DECODING_ATTACHMENTS', true),
],
'ignore' => [
'spelling' => env('IMAP_DECODING_IGNORE_SPELLING', true),
],
],
/*
|--------------------------------------------------------------------------
| Available masking options
|--------------------------------------------------------------------------
|
| By using the masking option you can define which class should be used
|
*/
'masking' => [
'message' => \Webklex\PHPIMAP\Support\Masks\MessageMask::class,
'attachment' => \Webklex\PHPIMAP\Support\Masks\AttachmentMask::class,
],
];