Update CorreoImapService.php

This commit is contained in:
Lizandro Guarnizo
2026-04-25 15:10:02 -05:00
parent 0e5ff957eb
commit 88a42ec629
+38 -27
View File
@@ -171,12 +171,15 @@ class CorreoImapService
/**
* Descarga cabeceras + cuerpo de un rango de secuencia (ej: "1:5").
*
* Usamos BODY.PEEK[1] en lugar de BODY.PEEK[TEXT]:
* - Para emails multipart/alternative (como Bancolombia), BODY[1] devuelve
* ÚNICAMENTE la parte text/plain, sin boundaries ni HTML.
* - Para emails simples (solo texto), BODY[1] también devuelve el cuerpo.
*/
private function fetchMessages(string $set): array
{
// Pedimos FLAGS, ENVELOPE y BODY para extraer remitente, asunto y cuerpo
$raw = $this->command("FETCH {$set} (FLAGS BODY.PEEK[HEADER.FIELDS (FROM SUBJECT DATE)] BODY.PEEK[TEXT])");
$raw = $this->command("FETCH {$set} (BODY.PEEK[HEADER.FIELDS (FROM SUBJECT DATE)] BODY.PEEK[1])");
return $this->parseMessages($raw);
}
@@ -215,19 +218,22 @@ class CorreoImapService
$email['date'] = trim($m[1]);
}
// BODY: tomamos el texto entre las dos secciones BODY
// La respuesta tiene dos literales {N}\r\n<contenido>
// BODY: la respuesta IMAP usa literales {N}\r\n<contenido>
// Con dos secciones pedidas habrá al menos 3 partes al dividir por "}\r\n".
// La tercera parte es BODY[1] (texto plano directo).
$parts = preg_split('/\}\r?\n/', $block);
$rawBody = '';
if (count($parts) >= 3) {
// La tercera sección suele ser el cuerpo de texto
$rawBody = $parts[2];
// Limpiar hasta el fin del literal (antes del siguiente *)
$rawBody = preg_replace('/\r?\n\)\s*\*.*$/s', '', $rawBody);
$rawBody = preg_replace('/\r?\n\)\s*[A-Z0-9]+ OK.*/s', '', $rawBody);
$email['body'] = $this->cleanBody(trim($rawBody));
// Quitar el cierre del literal IMAP (\r\n) y la línea "OK"
$rawBody = preg_replace('/\r?\n\s*\)\s*(\r?\n[A-Z0-9]+ OK.*)?$/s', '', $rawBody);
} elseif (count($parts) === 2) {
$rawBody = $parts[1];
$rawBody = preg_replace('/\r?\n\).*$/s', '', $rawBody);
$rawBody = $parts[1];
$rawBody = preg_replace('/\r?\n\s*\).*$/s', '', $rawBody);
}
if ($rawBody !== '') {
$email['body'] = $this->cleanBody(trim($rawBody));
}
@@ -298,33 +304,38 @@ class CorreoImapService
private function cleanBody(string $body): string
{
// ── 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 ──────────────────────────────
// ── 1. Decoded quoted-printable ──────────────────────────────────
// BODY.PEEK[1] retorna directamente el contenido de la parte (sin
// boundaries), pero puede estar codificado en quoted-printable.
if (preg_match('/=[0-9A-F]{2}/i', $body) || preg_match('/=\r?\n/m', $body)) {
$body = quoted_printable_decode($body);
}
// ── 3. Eliminar cabeceras MIME residuales ───────────────────────
// ── 2. Si aún hay boundaries MIME residuales, extraer text/plain
if (preg_match('/^--([^\r\n]+)/m', $body, $bm)) {
$plain = $this->extractMimePlainPart($body, $bm[1]);
if ($plain !== null) {
// Decodificar QP en la parte extraída también
if (preg_match('/=[0-9A-F]{2}/i', $plain) || preg_match('/=\r?\n/m', $plain)) {
$plain = quoted_printable_decode($plain);
}
$body = $plain;
}
}
// ── 3. Eliminar cabeceras MIME residuales de parte ───────────────
// (Content-Type:, Content-Transfer-Encoding:, etc.)
$body = preg_replace('/^(Content-[^\r\n]+\r?\n)+/mi', '', $body);
// ── 4. Limpiar URLs de imágenes entre corchetes: "Logo [http://...]"
// ── 4. Limpiar URLs entre corchetes: "Logo [http://...]" ─────────
$body = preg_replace('/\[https?:\/\/[^\]]*\]/i', '', $body);
// ── 5. Si aún contiene HTML (fallback) quitar etiquetas ──────────
// ── 5. Fallback HTML: si queda HTML, quitar etiquetas ────────────
if (preg_match('/<[a-z][\s>]/i', $body)) {
$body = self::stripHtmlFull($body);
}
// ── 6. Normalizar espacios y líneas ──────────────────────────────
// ── 6. Normalizar saltos de línea y espacios ─────────────────────
$body = str_replace(["\r\n", "\r"], "\n", $body);
$body = preg_replace('/\n{3,}/', "\n\n", $body);