NAiOSOmni Email
omnichat-emailv0.6.0Añade un canal de email (IMAP/SMTP) a NAiOSOmni. Tu bandeja aparece como un canal más dentro del Inbox unificado, con auto-reply IA, agentes verticales y todas las capacidades de NAiOSOmni.
Descripción
Plugin acoplado a NAiOSOmni: registra un nuevo driver 'email-imap' en el ChannelRegistry de NAiOSOmni para que cualquier cuenta IMAP/SMTP (Gmail con app-password, IONOS, Outlook personal, corporativo) pueda enchufarse como canal. Los emails entrantes aparecen en el Inbox unificado, agrupados por remitente (peer = email address). Los específicos del email (subject, message-id, threading, cc/bcc, html body, attachments) se serializan en media_meta JSON sin modificar el esquema de NAiOSOmni. Los responses se envían por SMTP con threading correcto (In-Reply-To + Subject: Re:). HTML body se sirve por 'ver original' desde el publicRouter del propio plugin (auth-checked).
Funcionalidades (3)
Tu bandeja IMAP aparece junto a WhatsApp y Telegram en el Inbox unificado.
Compatible con Gmail (app-password), IONOS, Outlook personal, corporativo. OAuth Google/Microsoft en fase 2.
Las respuestas mantienen In-Reply-To + Subject: Re: para que el cliente del destinatario las hile bien.
Changelog
- PHASE 10 · HUMAN-IN-THE-LOOP + tool integration RAG
- DRAFT MODE — toggle per-canal en tab General (solo email-imap). Cuando ON, las auto-respuestas IA NO se envían: se guardan con status='draft' para revisión. Bubble especial con borde dashed amber + 3 acciones: Enviar (SMTP real ahora) / Editar (carga texto en composer + descarta) / Descartar (limpia BD + ficheros). PATCH /channels/:id/draft-mode para activar/desactivar
- Endpoints draft: GET /api/drafts/:msgId (fetch para composer), POST /api/drafts/:msgId/send (promociona a envío real), DELETE /api/drafts/:msgId (limpia con borrado de adjuntos en disco)
- Renderer del inbox: detecta status='draft', muestra header 🤖 Borrador IA pendiente + bubble styled distinto + action row con 3 botones. Cero cambios en chat drivers (WA/TG no emiten status='draft')
- TOOL search_inbox para agentes — registrada en TOOLS de OmniChat mediante mutación del objeto exportado (cero cambios en core). Schema OpenAI tool con params {query, top_k}. ctx.invokePlugin delega al plugin's searchInbox() que llama al EmbeddingsStore. Los agentes pueden ahora preguntar al inbox semánticamente cuando un cliente lo pide
- Método público searchInbox(args) en el plugin: genera embedding del query, ejecuta cosine search, devuelve top-K formateado para LLM (sin buffers, scores con 2 decimales, snippet truncado)
- PHASE 9 · EMAIL-AI FEATURES — 4 features de IA específicas para email
- F-1 · TRIAJE AUTOMÁTICO — cada email entrante clasificado por LLM en {urgent, action, fyi, newsletter, spam} con reason en ≤12 palabras. Badge colored en el bubble del inbox (rojo/naranja/gris/azul/negro). Persistido en media_meta.triage
- F-4 · ANTI-PHISHING IA — score 0-1 calculado en la misma llamada LLM que el triage (token-eficiente). Banner severity-coded sobre el mensaje cuando score ≥ 0.5 (medio/alto/crítico con pulse animation). Risk factors en español. Persistido en media_meta.phishing
- F-5 · RAG SOBRE LA BANDEJA — SQLite propia con vectores Float32 packed (1536-dim, ~6KB/email). Auto-indexa cada email entrante no-spam tras el análisis. Endpoint POST /api/search con embedding del query + cosine in JS. Top-K resultados con peer/subject/snippet/score. Cleanup integrado: borra embeddings de canales eliminados
- F-6 · TRES BORRADORES AUTOCOMPOSE — al abrir un thread email, fila de 3 chips encima del composer con drafts en tonos formal/cercano/breve. Click → carga el texto en el textarea. Cache 5min por (canal+peer+last_inbound_id) para no re-gastar tokens al navegar tabs. Botón refresh para regenerar manual
- ENDPOINTS — POST /plugins/omnichat-email/api/search, POST /plugins/omnichat-email/api/drafts. Ambos auth-checked, scoped al usuario
- UI/CSS — badges de triage (5 colores), banner de phishing (3 severities con pulse), draft chips con hover lift effect. Todo driver-conditional (solo email-imap, WA/TG intactos)
- Combinación LLM — triage + phishing en una sola llamada con prompt unificado → ~50% ahorro de tokens vs llamadas separadas. Modelo: gpt-4o-mini para clasificación/borradores, text-embedding-3-small para vectores
- PHASE 8 · POLISH & ROBUSTEZ — los 7 ítems completos
- B-7 · Sanitize HTML email body — allowedTags ampliados (style, font, center, table-layout, etc.) para preservar formato real de emails. CSS inline no se filtra (parseStyleAttributes=false). meta charset utf-8 garantizado vía HTTP header + meta inline
- B-2 · IMAP \Seen flag — driver.markAsRead(peerId) ahora hace IMAP search by-From + STORE +FLAGS \Seen para todos los UIDs unseen del peer. Endpoint /api/channels/:id/messages dispara markAsRead fire-and-forget al servir el thread (driver-agnóstico, WA/TG son no-op)
- B-6 · Healthcheck enriquecido — tracking de latencia NOOP (rolling window 10 muestras), detección de degradación (3 NOOPs >5s consecutivos → reconnect preventivo), hint de inactividad (>6h sin inbound en horario laboral → log info)
- B-1 · UI de cuotas en tab Anti-spam — nueva card SOLO para canales email-imap con 3 inputs (per_minute/hour/day), pre-filled desde driver_config.quotas, PATCH /plugins/omnichat-email/channels/:cid/quotas con bounds razonables
- B-5 · Cool-down outbound dedup — refuse re-envío del mismo (peerId + body) dentro de 60s. Hash SHA-1 en mapa in-memory podado a la ventana. err.code DEDUP con tiempo desde el send anterior
- B-3 · Cleanup jobs orphans — cron diario (delay inicial 60s) que escanea data/bodies/<uid>/<cid>/ y uploads/users/<uid>/email-<cid>/ y elimina dirs cuyo canal email-imap ya no existe en BD. Scope channel-level (per-message orphans deferred)
- B-4 · Métricas dedicadas — endpoint /plugins/omnichat-email/api/metrics (admin/superadmin only) con channels totales/conectados, volumen 24h/7d in/out, filter savings, smtp errors, quota hits, avg attachment size, top senders 7d, NOOP latency p50/p95 + slow streak + last inbound por canal vivo
- PHASE 7 · HARDENING — endurecimiento del driver para producción real
- CUOTAS OUTBOUND — defaults 30/min · 200/hora · 1000/día por canal, contadores in-memory con timestamps podados a 24h. Excede → throw con err.code QUOTA_MINUTE/HOUR/DAY. Override per-canal via driver_config.quotas. _recordSend() solo cuenta tras éxito SMTP (fallos no penalizan)
- HEALTHCHECK IMAP NOOP cada 5min — detecta IDLE muerto silenciosamente (NAT timeout, LB reset, server-side drop). NOOP falla → close → reconnect via backoff existente. Iniciado tras connect, parado en disconnect
- LOG STRUCTURED BRIDGE — driver emite 'omnichat-email.log' en el event bus, el plugin lo forwarda a OmniChat.logService.log(). Categorías: email-rx, email-tx, email-filter, email-quota, email-health. Eventos detallados (subject, peer, uid, attachments, smtp_code) visibles en tiempo real en la pestaña Log del canal
- SANITIZACIÓN from_name — helper sanitizeFromName() strip CR/LF/angle-brackets + cap 80 chars. Aplicado en pairing inicial y edit-connection page. Bloquea inyección de headers SMTP
- CAP ATTACHMENT SIZE — total raw bytes ≤ 24MB (env. SMTP máx típico 25MB con overhead base64 +33%). fs.statSync sum antes de enviar, falla limpio con err.code=ATTACHMENT_TOO_LARGE
- LOG ESTRUCTURADO en todos los fail-paths — SMTP rechaza (con smtp_code si lo da), cuota excedida (code), adjuntos demasiado grandes (bytes), filtro auto-mail (reason), recepción/envío exitoso (full metadata)
- Rename — 'OmniChat Email' → 'NAiOSOmni Email' en manifest (id sigue siendo omnichat-email por compatibilidad)
- PAIRING (Phase 2) — validación real IMAP+SMTP con imapflow + nodemailer.verify(), cifrado AES-256-GCM de credenciales con secret-vault, sanitización (passwords stripped de driver_config)
- RECEPCIÓN (Phase 3) — IMAP IDLE persistente, backfill inicial de 30 emails, tracking UIDVALIDITY + UIDNEXT, mailparser + sanitize-html, attachments a disco, sanitización HTML body. Reconnect con backoff 5/10/30/60/120/300s
- ENVÍO (Phase 4) — SMTP con pool, threading correcto (In-Reply-To + References), 3 modos de subject (Asunto: explícito / Re: automático / sintético 60 chars), header Auto-Submitted: auto-replied (anti-loop activo)
- VER ORIGINAL (Phase 5) — Ruta /plugins/omnichat-email/body/:cid/:mid sirve HTML sanitizado con CSP estricto + iframe-friendly headers, ownership check. Attachments reusan /uploads/users/ existente de NAiOSOmni (cero código nuevo de auth)
- ADJUNTOS SALIENTES (Phase 6) — 1 email = N attachments en un único envelope SMTP (en lugar de N emails como hacen WA/TG). Driver acepta content.attachments[] del composer y los mapea a nodemailer
- EMAIL TACTICAL MODE — Filtro inbound de correo automático (Auto-Submitted, Precedence bulk/list/junk, List-* headers, X-Autoresponse, machine senders); supresión de progress notifies de tools (isProgress flag, no más '📚 Consultando KB…' por email); suffix al system_prompt cuando driver=email-imap para tono email-aware (una respuesta, formal, sin emojis decorativos)
- EDIT CONNECTION — Página /plugins/omnichat-email/channels/:cid/edit propia con form pre-rellenado (passwords blank por seguridad), validación antes de guardar, unload+load+connect en vivo. 'Re-vincular' del menú ⋮ redirige automático para canales email-imap
- INBOX UI — Renderer ahora dibuja media_meta.attachments[] como tarjetas (thumbnails para imágenes, players inline para video/audio, icono+nombre+size para PDF/Word/Excel/ZIP). Driver-agnóstico, cualquier driver futuro con el mismo shape lo aprovecha
- Modal 'Añadir contacto' driver-aware — copy + validación cambian según driver (email vs phone vs telegram chat_id)
- Tab 'Simulación' oculta para email-imap (incompatible por diseño: state machine síncrona chat-only)
- BUGS — BigInt coercion para uidValidity/uidNext/uid (imapflow >=1.3 los devuelve BigInt → rompía JSON.stringify); _restoreOwnChannels para evitar 'driver not registered' en boot race; polling de pluginLoader (no solo setImmediate, hay awaits entre loadAll y app.set); CSS padding del modal 'Añadir canal' (bug preexistente)
- TLS — Flag tls_insecure per-canal opcional para servers con cert intercept (Norton AV / corporate proxies / certs caducados). Strict TLS por defecto
- Dependencies — imapflow ^1.3.3, mailparser ^3.9.8, sanitize-html ^2.17.3 (nodemailer ya estaba)
- Scaffold inicial — registro de driver 'email-imap' en OmniChat ChannelRegistry
- Form-based pairing con campos IMAP/SMTP (placeholder — Phase 2 implementa la validación real)
- Driver stub: connect/startPairing/sendMessage lanzan 'not yet implemented' con la fase pendiente