From 4d464d40ef23e58a6ac9c8a194e730b488222fd8 Mon Sep 17 00:00:00 2001 From: Carlos Narro Date: Thu, 4 Jun 2026 14:41:59 +0200 Subject: [PATCH] Incrusta el logo del reformista en los emails (CID) + tema de marca MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - prepararLogo: el logo (data URI base64, URL http o ruta /public con APP_URL) se adjunta como imagen inline con Content-ID y se referencia con cid:, que es la forma fiable de mostrarlo en Gmail/Apple Mail/Outlook (el data URI directo lo bloquea Gmail). Fallback al nombre de la empresa si no hay logo. - El acento (barra, botón) ya usa el color de marca del tenant (resolveTheme). Probado: envío real con el logo de Reformas Ejemplo embebido y tema pizarra. Co-Authored-By: Claude Opus 4.8 --- mvp/b2c/src/lib/email/mailer.ts | 50 +++++++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/mvp/b2c/src/lib/email/mailer.ts b/mvp/b2c/src/lib/email/mailer.ts index 19cf5dc..3857f36 100644 --- a/mvp/b2c/src/lib/email/mailer.ts +++ b/mvp/b2c/src/lib/email/mailer.ts @@ -43,18 +43,42 @@ type EmailParts = { parrafosHtml: string[]; // HTML seguro: las variables ya vienen escapadas cta?: { url: string; label: string } | null; footer: string; + logoCid?: string | null; // si hay logo, se incrusta como adjunto inline (cid:) }; +type LogoAdjunto = { filename: string; content?: Buffer; path?: string; cid: string; contentType?: string }; + +const LOGO_CID = 'logoempresa'; + +// Prepara el logo como adjunto inline (CID) para que se vea en todos los clientes (Gmail bloquea +// las imágenes en data URI directas). Acepta data URI (base64), URL http(s), o ruta /public +// (se vuelve absoluta con APP_URL). Devuelve null si no hay logo usable. +function prepararLogo(logoUrl: string | null | undefined): LogoAdjunto | null { + if (!logoUrl) return null; + if (logoUrl.startsWith('data:')) { + const coma = logoUrl.indexOf(','); + if (coma === -1) return null; + const mime = logoUrl.slice(5, coma).split(';')[0] || 'image/png'; + const ext = mime.split('/')[1]?.replace('+xml', '') || 'png'; + const content = Buffer.from(logoUrl.slice(coma + 1), 'base64'); + return { filename: `logo.${ext}`, content, cid: LOGO_CID, contentType: mime }; + } + if (/^https?:\/\//.test(logoUrl)) return { filename: 'logo', path: logoUrl, cid: LOGO_CID }; + if (logoUrl.startsWith('/') && env.APP_URL) { + return { filename: 'logo', path: `${env.APP_URL}${logoUrl}`, cid: LOGO_CID }; + } + return null; +} + const FONT = "-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif"; // Email transaccional: una columna (máx 600px), mobile-first, dark mode, botón bulletproof (tabla), // estilos inline como base +