Id: 1234567890 <<< Este es tu Chat ID
First: TuNombre
Lanf: es
....
Id: 1234567890 <<< Este es tu Chat ID
First: TuNombre
Lanf: es
....
Id: 1234567890 <<< Este es tu Chat ID
First: TuNombre
Lanf: es
....
const knowledgeBase = `
Eres un asistente de soporte técnico de [Tu Empresa].
Responde solo si encuentras una coincidencia clara en las políticas siguientes.
Si no estás seguro, responde exactamente: NO_PUEDO_RESPONDER
POLÍTICAS:
1. Horario de atención: Lunes a viernes de 9:00 a 18:00 (GMT-5).
2. Tiempo de respuesta estimado: 24 horas hábiles.
3. Contraseñas: Nunca solicites ni compartas contraseñas por correo.
4. Reembolsos: Se procesan dentro de los primeros 30 días. El usuario debe enviar un comprobante.
5. Problemas técnicos comunes: - Error 403: El usuario debe limpiar caché y cookies. - Error 500: Reportar al equipo interno, pedir al usuario que espere 1 hora. - Olvido de contraseña: Enviar enlace de restablecimiento a su correo registrado.
6. Facturación: Para cambios de plan o facturación, responder que el usuario ingrese al panel de pago.
INSTRUCCIONES:
- Responde de forma amable y profesional.
- Usa el mismo idioma del correo recibido.
- Si el correo contiene más de una pregunta, responde cada punto.
- Si el correo es grosero o agresivo, responde: NO_PUEDO_RESPONDER
`; const items = $input.all();
return items.map(item => ({ json: { ...item.json, knowledgeBase }
}));
const knowledgeBase = `
Eres un asistente de soporte técnico de [Tu Empresa].
Responde solo si encuentras una coincidencia clara en las políticas siguientes.
Si no estás seguro, responde exactamente: NO_PUEDO_RESPONDER
POLÍTICAS:
1. Horario de atención: Lunes a viernes de 9:00 a 18:00 (GMT-5).
2. Tiempo de respuesta estimado: 24 horas hábiles.
3. Contraseñas: Nunca solicites ni compartas contraseñas por correo.
4. Reembolsos: Se procesan dentro de los primeros 30 días. El usuario debe enviar un comprobante.
5. Problemas técnicos comunes: - Error 403: El usuario debe limpiar caché y cookies. - Error 500: Reportar al equipo interno, pedir al usuario que espere 1 hora. - Olvido de contraseña: Enviar enlace de restablecimiento a su correo registrado.
6. Facturación: Para cambios de plan o facturación, responder que el usuario ingrese al panel de pago.
INSTRUCCIONES:
- Responde de forma amable y profesional.
- Usa el mismo idioma del correo recibido.
- Si el correo contiene más de una pregunta, responde cada punto.
- Si el correo es grosero o agresivo, responde: NO_PUEDO_RESPONDER
`; const items = $input.all();
return items.map(item => ({ json: { ...item.json, knowledgeBase }
}));
const knowledgeBase = `
Eres un asistente de soporte técnico de [Tu Empresa].
Responde solo si encuentras una coincidencia clara en las políticas siguientes.
Si no estás seguro, responde exactamente: NO_PUEDO_RESPONDER
POLÍTICAS:
1. Horario de atención: Lunes a viernes de 9:00 a 18:00 (GMT-5).
2. Tiempo de respuesta estimado: 24 horas hábiles.
3. Contraseñas: Nunca solicites ni compartas contraseñas por correo.
4. Reembolsos: Se procesan dentro de los primeros 30 días. El usuario debe enviar un comprobante.
5. Problemas técnicos comunes: - Error 403: El usuario debe limpiar caché y cookies. - Error 500: Reportar al equipo interno, pedir al usuario que espere 1 hora. - Olvido de contraseña: Enviar enlace de restablecimiento a su correo registrado.
6. Facturación: Para cambios de plan o facturación, responder que el usuario ingrese al panel de pago.
INSTRUCCIONES:
- Responde de forma amable y profesional.
- Usa el mismo idioma del correo recibido.
- Si el correo contiene más de una pregunta, responde cada punto.
- Si el correo es grosero o agresivo, responde: NO_PUEDO_RESPONDER
`; const items = $input.all();
return items.map(item => ({ json: { ...item.json, knowledgeBase }
}));
const email = $input.item.json;
const subject = email.subject || '';
const body = (email.textPlain && email.textPlain.trim()) || (email.textHtml && email.textHtml.trim()) || ''; return { subject, body: body.substring(0, 5000), from: email.from, to: email.to, uid: email.uid || email.id, chatInput: `From: ${email.from}\nAsunto: ${subject}\nCuerpo: ${body.substring(0, 5000)}`
};
const email = $input.item.json;
const subject = email.subject || '';
const body = (email.textPlain && email.textPlain.trim()) || (email.textHtml && email.textHtml.trim()) || ''; return { subject, body: body.substring(0, 5000), from: email.from, to: email.to, uid: email.uid || email.id, chatInput: `From: ${email.from}\nAsunto: ${subject}\nCuerpo: ${body.substring(0, 5000)}`
};
const email = $input.item.json;
const subject = email.subject || '';
const body = (email.textPlain && email.textPlain.trim()) || (email.textHtml && email.textHtml.trim()) || ''; return { subject, body: body.substring(0, 5000), from: email.from, to: email.to, uid: email.uid || email.id, chatInput: `From: ${email.from}\nAsunto: ${subject}\nCuerpo: ${body.substring(0, 5000)}`
};
const aiItems = $input.all();
const emailItems = $('CodeProcessEmail').all(); const output = aiItems.map((item, index) => { const originalEmail = emailItems[index]?.json || {}; const aiText = item.json.text || ''; return { json: { ...originalEmail, aiResponse: aiText.trim(), canReply: !aiText.includes('NO_PUEDO_RESPONDER') } };
}); return output;
const aiItems = $input.all();
const emailItems = $('CodeProcessEmail').all(); const output = aiItems.map((item, index) => { const originalEmail = emailItems[index]?.json || {}; const aiText = item.json.text || ''; return { json: { ...originalEmail, aiResponse: aiText.trim(), canReply: !aiText.includes('NO_PUEDO_RESPONDER') } };
}); return output;
const aiItems = $input.all();
const emailItems = $('CodeProcessEmail').all(); const output = aiItems.map((item, index) => { const originalEmail = emailItems[index]?.json || {}; const aiText = item.json.text || ''; return { json: { ...originalEmail, aiResponse: aiText.trim(), canReply: !aiText.includes('NO_PUEDO_RESPONDER') } };
}); return output;
const escapeHtml = (value) => { return String(value || '') .replace(/&/g, '&') .replace(/</g, '<') .replace(/>/g, '>');
};
const items = $input.all(); let text = '';
items.forEach((item, index) => { const subject = escapeHtml(item.json.subject || 'Sin asunto'); const aiResponse = escapeHtml(item.json.aiResponse || ''); text += `${index + 1}) ${subject}: ${aiResponse}\n━━━━━━━━━━━━━━━━━━━━\n`;
}); // ---- dividir en partes ----
const chunkSize = 3900;
const header = `━━━━━━━━━━━━━━━━━━━━\n<b>Recibiste los siguientes correos:</b>\n\n`; const fullText = header + text;
const totalParts = Math.ceil(fullText.length / chunkSize) || 1; const output = [];
for (let i = 0; i < fullText.length; i += chunkSize) { const part = Math.floor(i / chunkSize) + 1; output.push({ json: { text: `[${part}/${totalParts}]\n${fullText.slice(i, i + chunkSize)}` } });
} return output;
const escapeHtml = (value) => { return String(value || '') .replace(/&/g, '&') .replace(/</g, '<') .replace(/>/g, '>');
};
const items = $input.all(); let text = '';
items.forEach((item, index) => { const subject = escapeHtml(item.json.subject || 'Sin asunto'); const aiResponse = escapeHtml(item.json.aiResponse || ''); text += `${index + 1}) ${subject}: ${aiResponse}\n━━━━━━━━━━━━━━━━━━━━\n`;
}); // ---- dividir en partes ----
const chunkSize = 3900;
const header = `━━━━━━━━━━━━━━━━━━━━\n<b>Recibiste los siguientes correos:</b>\n\n`; const fullText = header + text;
const totalParts = Math.ceil(fullText.length / chunkSize) || 1; const output = [];
for (let i = 0; i < fullText.length; i += chunkSize) { const part = Math.floor(i / chunkSize) + 1; output.push({ json: { text: `[${part}/${totalParts}]\n${fullText.slice(i, i + chunkSize)}` } });
} return output;
const escapeHtml = (value) => { return String(value || '') .replace(/&/g, '&') .replace(/</g, '<') .replace(/>/g, '>');
};
const items = $input.all(); let text = '';
items.forEach((item, index) => { const subject = escapeHtml(item.json.subject || 'Sin asunto'); const aiResponse = escapeHtml(item.json.aiResponse || ''); text += `${index + 1}) ${subject}: ${aiResponse}\n━━━━━━━━━━━━━━━━━━━━\n`;
}); // ---- dividir en partes ----
const chunkSize = 3900;
const header = `━━━━━━━━━━━━━━━━━━━━\n<b>Recibiste los siguientes correos:</b>\n\n`; const fullText = header + text;
const totalParts = Math.ceil(fullText.length / chunkSize) || 1; const output = [];
for (let i = 0; i < fullText.length; i += chunkSize) { const part = Math.floor(i / chunkSize) + 1; output.push({ json: { text: `[${part}/${totalParts}]\n${fullText.slice(i, i + chunkSize)}` } });
} return output;
const from = $input.item.json.from;
const allowedDomains = ['tudominio.com', 'cliente.com'];
const domain = from.split('@')[1];
return allowedDomains.includes(domain);
const from = $input.item.json.from;
const allowedDomains = ['tudominio.com', 'cliente.com'];
const domain = from.split('@')[1];
return allowedDomains.includes(domain);
const from = $input.item.json.from;
const allowedDomains = ['tudominio.com', 'cliente.com'];
const domain = from.split('@')[1];
return allowedDomains.includes(domain); - Lee los correos entrantes vía IMAP
- Los analiza con DeepSeek usando una base de conocimiento personalizada
- Responde automáticamente si el modelo tiene suficiente contexto
- Te notifica por Telegram si necesita revisión manual - Un servidor con n8n funcionando (si no lo tienes, sigue esta guía de instalación)
- Una cuenta de correo con acceso IMAP (ZohoMail, Gmail, Outlook, o cualquier proveedor que lo soporte)
- Una clave API de DeepSeek (platform.deepseek.com)
- Un bot de Telegram creado con https://t.me/BotFather
> Nota: Telegram no tiene costos asociados por uso de bots, ideal para automatizaciones sin límites de mensajes. - DEEPSEEK_API_KEY
- URL del endpoint: https://api.deepseek.com/v1/chat/completions
- Modelo recomendado: deepseek-chat - Abre Telegram y busca @userinfobot
- Inicia la conversación con Start
- El bot te responde automáticamente con tu información. Busca la línea que dice Id:, ese número es tu Chat ID - En el campo Credential debes configurar (los valores y la forma de activación varían según el proveedor de correo): - User: tu correo
- Password: tu contraseña o contraseña de aplicación
- Host: tu servidor IMAP (ej: imap.gmail.com)
- Secure: true - En el resto de formulario ingresa: - Mailbox Name: nombre del buzón donde se deben extraer los correos, por defecto INBOX (Bandeja de entrada)
- Action: Mark as Read, con esto cada mensaje que procesemos será marcado como leído. - En DeepSeek Chat Model, solo especificar las credenciales: - Credential: selecciona o crea una credencial DeepSeek account API Key: tu clave de DeepSeek
- API Key: tu clave de DeepSeek
- Model: deepseek-v4-flash - API Key: tu clave de DeepSeek - En Basic LLM Chain (procesador): - Source for Prompt: Define below
- Prompt (User Message): Analyze this email and provide a short, clear response to send via Telegram.
{{ $json.chatInput }}
- Chat Messages: Type: System → Message: {{ $json.knowledgeBase }}
- Type: System → Message: {{ $json.knowledgeBase }}
- Require Specific Output Format: desactivado - Type: System → Message: {{ $json.knowledgeBase }} - Toma los datos originales del correo (subject, from, body, etc.)
- Agrega aiResponse con la respuesta limpia de DeepSeek
- Agrega canReply (true/false) para decidir si se responde automáticamente - Sí (true) → va a envío SMTP
- No (false) → va a notificación Telegram - Credential: te abrirá una ventana para registrar tus credenciales SMTP: User
Password
Host
Port
SSL
- From Email: le diremos que responda desde el mismo correo al que escribieron: {{ $json.to}}
- To: la persona que escribió {{ $json.from }}
- Subject: Re: {{ $('CodeProcessEmail').item.json.subject }}
- Email Format: HTML
- Text: {{ $json.aiResponse }} - Agregamos un nodo Code (JavaScript) en modo Run Once for All Items con el código: - Agregamos un nodo de tipo HTTP Request para enviar cada uno de los mensajes que definimos
- Method: POST
- URL: https://api.telegram.org/bot{TuTokenTelegram,formato:0000:xxxxxx}/sendMessage
- Authentication: none
- SendBody: true
- Body Content Type: JSON
- Specify Body: Using Fields Below chat_id: tu ID de conversación en Telegram text: {{ $json.text }} parse_mode: HTML disable_web_page_preview: TRUE
- chat_id: tu ID de conversación en Telegram
- text: {{ $json.text }}
- parse_mode: HTML
- disable_web_page_preview: TRUE - chat_id: tu ID de conversación en Telegram
- text: {{ $json.text }}
- parse_mode: HTML
- disable_web_page_preview: TRUE - Ejecuta manualmente haciendo clic en el botón Execute Workflow (arriba a la derecha). Esto dispara el flujo de inmediato sin esperar el polling automático.
- Envíate un correo de prueba con una pregunta que esté en tu base de conocimiento.
- Revisa que recibas la respuesta automática en la bandeja del remitente de prueba.
- Envíate otro correo con algo fuera de tu base de conocimiento.
- Deberías recibir la notificación en Telegram con el contenido del correo. - Lee correos vía IMAP sin perder ninguno
- Los analiza con DeepSeek contra tu propia base de conocimiento
- Responde automáticamente cuando puede
- Te notifica por Telegram cuando necesita tu intervención