From 08be3f254dae42c93ad6a617f4ba40af289c8cb1 Mon Sep 17 00:00:00 2001 From: Lizandro Guarnizo <77708265+lizandrogd@users.noreply.github.com> Date: Sat, 25 Apr 2026 15:02:07 -0500 Subject: [PATCH] up --- app/Services/BancolombiaParser.php | 3 ++ app/Services/CorreoImapService.php | 59 +++++++++++++++++++++++++----- 2 files changed, 52 insertions(+), 10 deletions(-) diff --git a/app/Services/BancolombiaParser.php b/app/Services/BancolombiaParser.php index 8c3827c..f8f46ed 100644 --- a/app/Services/BancolombiaParser.php +++ b/app/Services/BancolombiaParser.php @@ -26,6 +26,9 @@ class BancolombiaParser // Limpiar HTML si llega con etiquetas $text = self::stripHtml($text); + // Limpiar referencias URL entre corchetes: "Logo Bancolombia [http://...]" + $text = preg_replace('/\[https?:\/\/[^\]]*\]/i', '', $text); + // Normalizar espacios y saltos de línea $text = preg_replace('/\s+/', ' ', $text); $text = trim($text); diff --git a/app/Services/CorreoImapService.php b/app/Services/CorreoImapService.php index 1fd13a8..606a54b 100644 --- a/app/Services/CorreoImapService.php +++ b/app/Services/CorreoImapService.php @@ -291,31 +291,70 @@ class CorreoImapService private function cleanBody(string $body): string { - // Quitar quoted-printable si aplica (antes de tocar HTML) - if (str_contains($body, '=\r\n') || preg_match('/=[0-9A-F]{2}/i', $body)) { + // ── 1. MIME multipart: extraer SOLO la parte text/plain ────────── + // Los emails de Bancolombia son multipart/alternative. + // Detectamos el boundary en la primera línea --boundary + if (preg_match('/^--([^\r\n]+)/m', $body, $bm)) { + $plainPart = $this->extractMimePlainPart($body, $bm[1]); + if ($plainPart !== null) { + $body = $plainPart; + } + } + + // ── 2. Decodificar quoted-printable ────────────────────────────── + if (preg_match('/=[0-9A-F]{2}/i', $body) || preg_match('/=\r?\n/m', $body)) { $body = quoted_printable_decode($body); } - // Quitar líneas de separadores de partes MIME - $body = preg_replace('/--[^\r\n]+\r?\n/m', '', $body); - - // Eliminar líneas de cabecera de parte MIME (Content-Type, etc.) + // ── 3. Eliminar cabeceras MIME residuales ──────────────────────── $body = preg_replace('/^(Content-[^\r\n]+\r?\n)+/mi', '', $body); - // Si el cuerpo contiene HTML, procesarlo adecuadamente + // ── 4. Limpiar URLs de imágenes entre corchetes: "Logo [http://...]" + $body = preg_replace('/\[https?:\/\/[^\]]*\]/i', '', $body); + + // ── 5. Si aún contiene HTML (fallback) quitar etiquetas ────────── if (preg_match('/<[a-z][\s>]/i', $body)) { $body = self::stripHtmlFull($body); } - // Normalizar saltos de línea + // ── 6. Normalizar espacios y líneas ────────────────────────────── $body = str_replace(["\r\n", "\r"], "\n", $body); - - // Recortar líneas en blanco excesivas $body = preg_replace('/\n{3,}/', "\n\n", $body); return trim($body); } + /** + * Extrae el contenido de la parte text/plain de un cuerpo MIME multipart. + * Devuelve null si no se encuentra o el email no es multipart. + */ + private function extractMimePlainPart(string $body, string $boundary): ?string + { + $escaped = preg_quote(rtrim($boundary), '/'); + + // Separar por --boundary (con o sin espacios/CRLF alrededor) + $parts = preg_split('/--' . $escaped . '(?:--)?[ \t]*\r?\n/', $body, -1, PREG_SPLIT_NO_EMPTY); + + foreach ($parts as $part) { + // Ignorar partes sin cabeceras MIME + if (stripos($part, 'Content-Type:') === false) { + continue; + } + + // ¿Es text/plain? + if (!preg_match('/Content-Type:\s*text\/plain/i', $part)) { + continue; + } + + // Separar cabeceras del cuerpo (doble CRLF o LF) + if (preg_match('/\r?\n\r?\n(.+)$/s', $part, $m)) { + return $m[1]; + } + } + + return null; + } + /** * Elimina completamente bloques