feat(umind): el canal correo puede acotarse a ciertos remitentes
"Responder a: todos los que escriban / solo a estos remitentes" — direcciones completas o dominios, separados por coma. Un dominio (@miempresa.com) habilita a toda esa empresa; lo que no pasa el filtro se marca leído y no se contesta: decisión tomada, no correo pendiente que se relee en cada revisión. El match de dominio es contra el dominio entero, nunca por sufijo: "empresa.com" no habilita a alguien de "malaempresa.com" ni de un subdominio. Ese es el clásico filtro que parece cerrado y no lo está, y acá decide a quién le habla el agente en nombre del negocio — hay un test por cada agujero. El filtro y el intervalo también se pueden cambiar por el update del canal sin recrearlo, porque recrearlo pide la contraseña de la casilla de nuevo. De paso quedó verificado que el módulo de soporte sigue intacto tras la unificación del SMTP: los catorce tests de soporte (auto-respuesta, parseo IMAP, clasificador, resúmenes) pasan en verde. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
eddec45857
commit
9da2a057f2
@@ -38,7 +38,7 @@ function canalVacio() {
|
||||
return {
|
||||
tipo: 'telegram', bot_token: '', phone_number_id: '', access_token: '', app_secret: '', verify_token: '',
|
||||
usuario: '', password: '', imap_host: '', smtp_host: '', imap_encriptado: 'ssl', smtp_encriptado: 'starttls',
|
||||
intervalo_minutos: 5,
|
||||
intervalo_minutos: 5, responder_a: 'todos', filtro_remitentes: '',
|
||||
usar_whisper_audio: false, usar_ocr_imagenes: false, usar_archivos_docs: false,
|
||||
}
|
||||
}
|
||||
@@ -76,6 +76,7 @@ async function guardarCanal() {
|
||||
await api.post(apiUmind('/umind/canales'), {
|
||||
agente_id: props.agenteId, tipo: canalForm.value.tipo, credenciales, activo: true,
|
||||
intervalo_minutos: Number(canalForm.value.intervalo_minutos) || 5,
|
||||
filtro_remitentes: canalForm.value.responder_a === 'algunos' ? canalForm.value.filtro_remitentes : '',
|
||||
usar_whisper_audio: canalForm.value.usar_whisper_audio, usar_ocr_imagenes: canalForm.value.usar_ocr_imagenes,
|
||||
usar_archivos_docs: canalForm.value.usar_archivos_docs,
|
||||
})
|
||||
@@ -180,6 +181,7 @@ async function eliminarCanal(c) {
|
||||
<!-- Un canal de correo no tiene webhook: se revisa por intervalo. -->
|
||||
<p v-if="c.tipo === 'correo'" class="label mt-1">
|
||||
Revisa la casilla cada {{ c.intervalo_minutos >= 60 ? '1 hora' : `${c.intervalo_minutos} minutos` }}
|
||||
· {{ c.filtro_remitentes ? `responde solo a: ${c.filtro_remitentes}` : 'responde a todos' }}
|
||||
</p>
|
||||
<p v-else class="label mt-1 break-all">
|
||||
Webhook: <code class="bg-elevado px-1 rounded">{{ c.webhook_url }}</code>
|
||||
@@ -235,6 +237,32 @@ async function eliminarCanal(c) {
|
||||
</select>
|
||||
<p class="text-xs text-tenue mt-1">Un correo no es un chat: para la mayoría, 5 o 15 minutos sobra.</p>
|
||||
</div>
|
||||
<div>
|
||||
<label class="label">Responder a</label>
|
||||
<div class="flex flex-col gap-1.5 mt-1">
|
||||
<label class="flex items-center gap-2 text-sm text-texto cursor-pointer">
|
||||
<input v-model="canalForm.responder_a" type="radio" value="todos" class="text-brand focus:ring-brand" />
|
||||
Todos los que escriban
|
||||
</label>
|
||||
<label class="flex items-center gap-2 text-sm text-texto cursor-pointer">
|
||||
<input v-model="canalForm.responder_a" type="radio" value="algunos" class="text-brand focus:ring-brand" />
|
||||
Solo a estos remitentes
|
||||
</label>
|
||||
</div>
|
||||
<template v-if="canalForm.responder_a === 'algunos'">
|
||||
<textarea
|
||||
v-model="canalForm.filtro_remitentes"
|
||||
rows="3"
|
||||
required
|
||||
placeholder="juan@cliente.com, @miempresa.com Direcciones completas o dominios, separados por coma."
|
||||
class="input font-mono mt-2"
|
||||
></textarea>
|
||||
<p class="text-xs text-tenue mt-1">
|
||||
Un dominio (ej. <span class="font-mono">@miempresa.com</span>) habilita a todos los de esa empresa.
|
||||
El resto de los correos se ignoran sin responder.
|
||||
</p>
|
||||
</template>
|
||||
</div>
|
||||
<details class="text-xs text-tenue">
|
||||
<summary class="cursor-pointer">Servidores (solo si la detección automática falla)</summary>
|
||||
<div class="grid sm:grid-cols-2 gap-3 mt-2">
|
||||
|
||||
Reference in New Issue
Block a user