Update CorreoImapService.php
This commit is contained in:
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user