Как максимально расширить на все случаи жизни ? Для любых писем Только с PhpMimeMailParser и декодирование различных кодировок
<?
require_once '../vendor/autoload.php';
use PhpMimeMailParser\Parser;
$eml_file = __DIR__ . '/attachments\2025\07\08\12b30715c8ccae21e2b05c2fe7faee6e/1751972486.eml';
$eml_file = __DIR__ . '/attachments/2025/07/08/9df0df4d80701d9302f892956da27d6d/1751963059.eml';
function parse_eml_full($emlFile) {
$parser = new Parser();
$parser->setPath($emlFile);
// Заголовки
echo "<h2>Заголовки</h2><table border='1' cellpadding='5'>";
foreach ($parser->getHeaders() as $header => $value) {
if (is_array($value)) $value = implode(", ", $value);
echo "<tr><td><strong>" . htmlspecialchars($header) . "</strong></td><td>" . htmlspecialchars($value) . "</td></tr>";
}
echo "</table>";
// От кого / Кому / Тема
echo "<h3>Отправитель: " . htmlspecialchars($parser->getHeader('from')) . "</h3>";
echo "<h3>Получатель: " . htmlspecialchars($parser->getHeader('to')) . "</h3>";
echo "<h3>Тема: " . htmlspecialchars($parser->getHeader('subject')) . "</h3>";
// Тело письма
echo "<h2>Тело письма (plain text)</h2>";
echo "<pre>" . htmlspecialchars($parser->getMessageBody('text')) . "</pre>";
echo "<h2>Тело письма (HTML)</h2>";
echo "<div style='border:1px solid #ccc;padding:10px;margin:10px 0;'>" . $parser->getMessageBody('html') . "</div>";
// Вложения
$attachments = $parser->getAttachments();
echo "<h2>Вложения</h2>";
if (empty($attachments)) {
echo "<p>Нет вложений</p>";
} else {
foreach ($attachments as $attachment) {
$name = $attachment->getFilename();
$size = strlen($attachment->getContent());
$savedPath = "attachments/uploads/" . $name;
file_put_contents($savedPath, $attachment->getContent());
echo "<p>Файл: <strong>$name</strong> ($size байт) — <a href='$savedPath' target='_blank'>Скачать</a></p>";
}
}
}
parse_eml_full($eml_file);
Для создания максимально универсального решения для обработки EML-файлов с использованием PhpMimeMailParser, включая поддержку различных кодировок, необходимо добавить обработку всех возможных случаев: декодирование заголовков, тел писем, вложений, работа с разными MIME-структурами и кодировками (например, base64, quoted-printable, UTF-8, Windows-1251 и т.д.). Ниже приведен расширенный код, который учитывает эти аспекты.
Основные улучшения:
- Декодирование заголовков: Используем mb_decode_mimeheader для корректного декодирования заголовков в любых кодировках.
- Обработка кодировок текста: Автоматическое определение кодировки тела письма (с использованием mb_detect_encoding) и приведение к UTF-8.
- Поддержка различных MIME-структур: Работа с многослойными MIME-сообщениями (multipart).
- Обработка вложений: Корректная работа с именами файлов в разных кодировках и сохранение вложений.
- Логирование ошибок: Добавлена обработка исключений для устойчивости.
- Универсальность: Код обрабатывает письма с отсутствующими частями (например, без HTML или текста).
Код:
php
<?php
require_once '../vendor/autoload.php';
use PhpMimeMailParser\Parser;
use PhpMimeMailParser\Attachment;
$eml_file = __DIR__ . '/attachments/2025/07/08/9df0df4d80701d9302f892956da27d6d/1751963059.eml';
function parse_eml_full($emlFile) {
try {
// Инициализация парсера
$parser = new Parser();
$parser->setPath($emlFile);
// Установка выходной кодировки
$outputEncoding = 'UTF-8';
// Декодирование заголовков
echo "<h2>Заголовки</h2><table border='1' cellpadding='5'>";
foreach ($parser->getHeaders() as $header => $value) {
if (is_array($value)) {
$value = array_map('mb_decode_mimeheader', $value);
$value = implode(", ", $value);
} else {
$value = mb_decode_mimeheader($value);
}
// Приведение к UTF-8
$value = mb_convert_encoding($value, $outputEncoding, 'auto');
echo "<tr><td><strong>" . htmlspecialchars($header) . "</strong></td><td>" . htmlspecialchars($value) . "</td></tr>";
}
echo "</table>";
// Отправитель, получатель, тема
$from = mb_decode_mimeheader($parser->getHeader('from'));
$to = mb_decode_mimeheader($parser->getHeader('to'));
$subject = mb_decode_mimeheader($parser->getHeader('subject'));
echo "<h3>Отправитель: " . htmlspecialchars(mb_convert_encoding($from, $outputEncoding, 'auto')) . "</h3>";
echo "<h3>Получатель: " . htmlspecialchars(mb_convert_encoding($to, $outputEncoding, 'auto')) . "</h3>";
echo "<h3>Тема: " . htmlspecialchars(mb_convert_encoding($subject, $outputEncoding, 'auto')) . "</h3>";
// Получение тела письма (plain text)
$textBody = $parser->getMessageBody('text');
if ($textBody) {
$textCharset = $parser->getTextCharset() ?: 'UTF-8';
$textBody = mb_convert_encoding($textBody, $outputEncoding, $textCharset);
echo "<h2>Тело письма (plain text)</h2>";
echo "<pre>" . htmlspecialchars($textBody) . "</pre>";
} else {
echo "<h2>Тело письма (plain text)</h2><p>Отсутствует</p>";
}
// Получение тела письма (HTML)
$htmlBody = $parser->getMessageBody('html');
if ($htmlBody) {
$htmlCharset = $parser->getHtmlCharset() ?: 'UTF-8';
$htmlBody = mb_convert_encoding($htmlBody, $outputEncoding, $htmlCharset);
echo "<h2>Тело письма (HTML)</h2>";
echo "<div style='border:1px solid #ccc;padding:10px;margin:10px 0;'>" . $htmlBody . "</div>";
} else {
echo "<h2>Тело письма (HTML)</h2><p>Отсутствует</p>";
}
// Обработка вложений
$attachments = $parser->getAttachments();
echo "<h2>Вложения</h2>";
if (empty($attachments)) {
echo "<p>Нет вложений</p>";
} else {
$uploadDir = __DIR__ . '/attachments/uploads/';
if (!is_dir($uploadDir)) {
mkdir($uploadDir, 0777, true);
}
foreach ($attachments as $attachment) {
$filename = $attachment->getFilename();
// Декодирование имени файла
$filename = mb_decode_mimeheader($filename);
$filename = mb_convert_encoding($filename, $outputEncoding, 'auto');
// Очистка имени файла для безопасности
$filename = preg_replace('/[^A-Za-z0-9_\-\.]/', '_', $filename);
$content = $attachment->getContent();
$size = strlen($content);
$savedPath = $uploadDir . $filename;
// Сохранение файла
file_put_contents($savedPath, $content);
echo "<p>Файл: <strong>" . htmlspecialchars($filename) . "</strong> ($size байт) — <a href='attachments/uploads/" . htmlspecialchars($filename) . "' target='_blank'>Скачать</a></p>";
}
}
} catch (Exception $e) {
echo "<h2>Ошибка</h2><p>Произошла ошибка при обработке EML-файла: " . htmlspecialchars($e->getMessage()) . "</p>";
}
}
// Вызов функции
parse_eml_full($eml_file);Что добавлено и улучшено:
- Декодирование заголовков:
- Используется mb_decode_mimeheader для обработки закодированных заголовков (например, =?UTF-8?B?...?=) в любых кодировках.
- Конвертация в UTF-8 с помощью mb_convert_encoding.
- Обработка кодировок тела письма:
- Используется метод getTextCharset() и getHtmlCharset() для определения кодировки текста и HTML соответственно.
- Автоматическая конвертация в UTF-8 для единообразного вывода.
- Обработка вложений:
- Декодирование имен файлов с помощью mb_decode_mimeheader.
- Очистка имен файлов от недопустимых символов для безопасного сохранения.
- Проверка и создание директории для вложений.
- Обработка ошибок:
- Весь код обернут в блок try-catch для перехвата возможных ошибок (например, некорректный EML-файл).
- Вывод понятного сообщения об ошибке.
- Универсальность:
- Проверка наличия текстового и HTML-тела, вывод сообщения, если они отсутствуют.
- Корректная работа с письмами без вложений или с многослойными MIME-структурами.
- Безопасность:
- Использование htmlspecialchars для предотвращения XSS-атак при выводе текста.
- Очистка имен файлов для предотвращения проблем с файловой системой.
Дополнительные рекомендации:
- Логирование:
- Добавьте логирование ошибок в файл или базу данных для отладки:
phperror_log($e->getMessage(), 3, __DIR__ . '/error.log');
- Добавьте логирование ошибок в файл или базу данных для отладки:
- Оптимизация хранения вложений:
- Для уникальности имен файлов можно добавлять хэш или временную метку:
php$filename = time() . '_' . $filename;
- Для уникальности имен файлов можно добавлять хэш или временную метку:
- Поддержка больших файлов:
- Если ожида EML-файлы большого размера, используйте потоковую обработку:
php$parser->setStream(fopen($emlFile, 'r'));
- Если ожида EML-файлы большого размера, используйте потоковую обработку:
- Кэширование:
- Для повторной обработки EML-файлов сохраняйте результаты парсинга в базе данных или файле, чтобы не парсить заново.
- Поддержка других кодировок:
- Если mb_detect_encoding не определяет кодировку, можно использовать библиотеку iconv:
php$value = iconv($detectedEncoding, $outputEncoding . '//IGNORE', $value);
- Если mb_detect_encoding не определяет кодировку, можно использовать библиотеку iconv:
- Валидация EML-файлов:
- Перед парсингом проверяйте, существует ли файл и доступен ли он:
phpif (!file_exists($emlFile) || !is_readable($emlFile)) {throw new Exception("Файл $emlFile не найден или недоступен");}
- Перед парсингом проверяйте, существует ли файл и доступен ли он:
Требования:
- Установленный пакет php-mime-mail-parser через Composer:
bashcomposer require php-mime-mail-parser/php-mime-mail-parser
- PHP с модулями mbstring и iconv для работы с кодировками.
Этот код максимально универсален и готов к обработке EML-файлов с любыми кодировками и структурой. Если у вас есть дополнительные требования (например, обработка специфических заголовков или форматов), напишите, и я добавлю соответствующий функционал.
2,4s