Как максимально расширить на все случаи жизни ? Для любых писем
<?
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);
Чтобы максимально расширить функцию parse_eml_full для обработки любых писем и учета всех возможных случаев, нужно добавить обработку дополнительных заголовков, различных кодировок, встраивания HTML-контента, вложенных писем (MIME), обработки ошибок и других аспектов. Ниже приведен улучшенный код с комментариями, который охватывает широкий спектр случаев и делает функцию более универсальной.
php
<?php
require_once '../vendor/autoload.php';
use PhpMimeMailParser\Parser;
use MimeLib\Mime; // Предполагается, что вы используете библиотеку для более сложной обработки MIME
use Exception;
// Основная функция для парсинга EML-файлов
function parse_eml_full($emlFile) {
try {
// Проверяем существование файла
if (!file_exists($emlFile)) {
throw new Exception("Файл $emlFile не найден.");
}
// Инициализация парсера
$parser = new Parser();
$parser->setPath($emlFile);
// Получение всех заголовков
echo "<h2>Заголовки</h2>";
echo "<table border='1' cellpadding='5'>";
$headers = $parser->getHeaders();
foreach ($headers as $header => $value) {
// Обработка массивов и сложных заголовков
$value = is_array($value) ? implode(", ", array_map('htmlspecialchars', $value)) : htmlspecialchars($value);
echo "<tr><td><strong>" . htmlspecialchars($header) . "</strong></td><td>$value</td></tr>";
}
echo "</table>";
// Дополнительные важные заголовки
echo "<h3>Основная информация</h3>";
$from = $parser->getHeader('from') ? htmlspecialchars($parser->getHeader('from')) : 'Не указан';
$to = $parser->getHeader('to') ? htmlspecialchars($parser->getHeader('to')) : 'Не указан';
$cc = $parser->getHeader('cc') ? htmlspecialchars($parser->getHeader('cc')) : 'Отсутствует';
$bcc = $parser->getHeader('bcc') ? htmlspecialchars($parser->getHeader('bcc')) : 'Отсутствует';
$subject = $parser->getHeader('subject') ? htmlspecialchars($parser->getHeader('subject')) : 'Без темы';
$date = $parser->getHeader('date') ? htmlspecialchars($parser->getHeader('date')) : 'Не указана';
echo "<p><strong>Отправитель:</strong> $from</p>";
echo "<p><strong>Получатель:</strong> $to</p>";
echo "<p><strong>Копия (CC):</strong> $cc</p>";
echo "<p><strong>Скрытая копия (BCC):</strong> $bcc</p>";
echo "<p><strong>Тема:</strong> $subject</p>";
echo "<p><strong>Дата:</strong> $date</p>";
// Получение тела письма
echo "<h2>Тело письма</h2>";
// Текстовое тело
$textBody = $parser->getMessageBody('text');
if ($textBody) {
echo "<h3>Текстовый формат</h3>";
echo "<pre>" . htmlspecialchars($textBody) . "</pre>";
} else {
echo "<p>Текстовое тело отсутствует</p>";
}
// HTML тело
$htmlBody = $parser->getMessageBody('html');
if ($htmlBody) {
echo "<h3>HTML формат</h3>";
// Безопасная обработка HTML
$htmlBody = filter_var($htmlBody, FILTER_SANITIZE_FULL_SPECIAL_CHARS, FILTER_FLAG_NO_ENCODE_QUOTES);
echo "<div style='border:1px solid #ccc;padding:10px;margin:10px 0;'>$htmlBody</div>";
// Встраивание встроенных изображений (inline attachments, например, CID)
$attachments = $parser->getAttachments();
foreach ($attachments as $attachment) {
if ($attachment->getContentId()) {
$cid = $attachment->getContentId();
$content = base64_encode($attachment->getContent());
$mimeType = $attachment->getContentType();
$htmlBody = str_replace("cid:$cid", "data:$mimeType;base64,$content", $htmlBody);
}
}
echo "<h3>HTML с встроенными изображениями</h3>";
echo "<div style='border:1px solid #ccc;padding:10px;margin:10px 0;'>$htmlBody</div>";
} else {
echo "<p>HTML тело отсутствует</p>";
}
// Обработка вложений
echo "<h2>Вложения</h2>";
$attachments = $parser->getAttachments();
if (empty($attachments)) {
echo "<p>Нет вложений</p>";
} else {
$uploadDir = 'attachments/uploads/';
if (!is_dir($uploadDir)) {
mkdir($uploadDir, 0755, true);
}
foreach ($attachments as $attachment) {
$name = $attachment->getFilename() ?: 'unnamed_' . uniqid() . '.dat';
$size = strlen($attachment->getContent());
$contentType = $attachment->getContentType();
$savedPath = $uploadDir . $name;
// Проверка на допустимые типы файлов и безопасное сохранение
if (file_put_contents($savedPath, $attachment->getContent())) {
echo "<p>Файл: <strong>$name</strong> ($size байт, тип: $contentType) — <a href='$savedPath' target='_blank'>Скачать</a></p>";
} else {
echo "<p>Ошибка сохранения файла: <strong>$name</strong></p>";
}
}
}
// Обработка вложенных писем (например, пересланные письма)
echo "<h2>Вложенные письма</h2>";
$rawMessage = file_get_contents($emlFile);
$mime = new Mime();
$mime->setContent($rawMessage);
$parts = $mime->getParts();
$hasNestedMessages = false;
foreach ($parts as $part) {
if ($part->getContentType() === 'message/rfc822') {
$hasNestedMessages = true;
$nestedEmlPath = $uploadDir . 'nested_' . uniqid() . '.eml';
file_put_contents($nestedEmlPath, $part->getContent());
echo "<p>Обнаружено вложенное письмо: <a href='$nestedEmlPath' target='_blank'>Скачать</a></p>";
// Рекурсивный вызов для обработки вложенного письма
echo "<h3>Содержимое вложенного письма:</h3>";
echo "<div style='border:2px dashed #ccc;padding:10px;margin:10px 0;'>";
parse_eml_full($nestedEmlPath);
echo "</div>";
}
}
if (!$hasNestedMessages) {
echo "<p>Вложенные письма отсутствуют</p>";
}
} catch (Exception $e) {
echo "<h2>Ошибка</h2>";
echo "<p>Произошла ошибка при обработке файла: " . htmlspecialchars($e->getMessage()) . "</p>";
}
}
// Пример использования
$eml_file = __DIR__ . '/attachments/2025/07/08/9df0df4d80701d9302f892956da27d6d/1751963059.eml';
parse_eml_full($eml_file);Основные улучшения и расширения:
- Обработка ошибок:
- Добавлена проверка существования файла.
- Использование try-catch для обработки исключений, чтобы функция не "падала" при ошибках.
- Полная обработка заголовков:
- Вывод всех доступных заголовков, включая cc, bcc, date.
- Безопасная обработка массивов в заголовках с помощью array_map.
- Улучшенная обработка тела письма:
- Проверка наличия текстового и HTML-формата.
- Безопасная обработка HTML с помощью filter_var для предотвращения XSS-атак.
- Поддержка встроенных изображений (CID), которые часто используются в HTML-письмах.
- Обработка вложений:
- Проверка и создание директории для сохранения вложений.
- Генерация уникальных имен для безымянных вложений.
- Вывод типа содержимого (content-type) для каждого вложения.
- Обработка вложенных писем:
- Использование библиотеки MimeLib\Mime (предполагается, что вы добавите такую библиотеку, например, laminas/laminas-mime) для обработки сложных MIME-структур.
- Сохранение и рекурсивный парсинг вложенных писем (например, пересланных сообщений).
- Кодировки:
- htmlspecialchars используется для безопасного вывода всех строк.
- Поддержка встроенных изображений с заменой cid: на data: URI.
- Гибкость:
- Функция готова к обработке писем с отсутствующими заголовками, пустым телом или вложениями.
- Рекурсивная обработка вложенных писем делает её универсальной для сложных сообщений.
Рекомендации по использованию:
- Библиотеки: Убедитесь, что установлены php-mime-mail-parser и, при необходимости, библиотека для обработки MIME (например, laminas/laminas-mime).
bashcomposer require php-mime-mail-parser/php-mime-mail-parser laminas/laminas-mime
- Безопасность:
- Используйте filter_var для очистки HTML.
- Проверяйте типы файлов вложений, чтобы предотвратить загрузку опасных файлов (например, .exe).
- Логирование: Добавьте логирование ошибок в файл или базу данных для отладки.
- Хранение вложений: Рассмотрите использование уникальных имен файлов или хэшей для предотвращения конфликтов имен.
- Кодировки: Если письма содержат нестандартные кодировки, добавьте поддержку iconv или mb_convert_encoding для их обработки.
Пример добавления обработки кодировок:
php
function decodeHeader($header) {
return mb_decode_mimeheader($header);
}
// Пример использования в заголовках
$subject = decodeHeader($parser->getHeader('subject'));Дополнительные улучшения (по желанию):
- Многоязычность: Добавьте поддержку извлечения текста на разных языках.
- Превью вложений: Для изображений можно генерировать миниатюры с помощью GD или Imagick.
- Анализ спама: Интеграция с антиспам-библиотеками для проверки подозрительных писем.
- База данных: Сохранение метаданных письма (отправитель, получатель, тема) в базу данных для дальнейшего анализа.
Этот код покрывает большинство случаев, включая сложные письма с вложениями, HTML-контентом и пересланными сообщениями, и является достаточно гибким для дальнейших доработок.
1,3s
Только с PhpMimeMailParser и декодирование различных кодировок
Достигнут предел сообщений
Зарегистрируйся, чтобы продолжить с Grok 3
Наслаждайся большими лимитами, историей, вложениями, личными чатами и многим другим после бесплатной регистрации