DEV Community

Crea un asistente de correo con IA usando n8n y Telegram

¿Tu bandeja de entrada está llena de correos repetitivos? Consultas de soporte, preguntas frecuentes, solicitudes de información... todo requiere tiempo y respuestas manuales.

En este artículo vas a construir un asistente automatizado de correo electrónico que:

  1. Lee los correos entrantes vía IMAP
  2. Los analiza con DeepSeek usando una base de conocimiento personalizada
  3. Responde automáticamente si el modelo tiene suficiente contexto
  4. Te notifica por Telegram si necesita revisión manual

Architecture

Diagrama realizado con https://savnet.co


¿Qué necesitas?

  • 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.

1. Obtener credenciales

DeepSeek API

Regístrate en platform.deepseek.com, ve a la sección de API Keys y crea una nueva. Vas a necesitar:

  • DEEPSEEK_API_KEY
  • URL del endpoint: https://api.deepseek.com/v1/chat/completions
  • Modelo recomendado: deepseek-chat

Bot de Telegram

Crear un bot en Telegram es rápido y no requiere registro de empresa ni tarjetas. Para crear el bot abre Telegram, busca @BotFather, envía /newbot y sigue los pasos. Al finalizar te dará un token como 4839574812:AAFD39kkdpWt3ywyRZergyOLMaJhac60qc.

Para más detalle sobre la creación del bot: Telegram Bot Creation Handbook

Obtener el Chat ID

Necesitas saber el Chat ID (tu ID de usuario en Telegram) para que el bot sepa a quién enviarle los mensajes.

  1. Abre Telegram y busca @userinfobot
  2. Inicia la conversación con Start
  3. El bot te responde automáticamente con tu información. Busca la línea que dice Id:, ese número es tu Chat ID
Id: 1234567890   <<< Este es tu Chat ID
First: TuNombre
Lanf: es
....
Enter fullscreen mode Exit fullscreen mode

Guarda ambos valores (Bot Token y Chat ID) para usarlos en n8n.


2. Construir el flujo en n8n

Workflow

Si eres nuevo en n8n lo primero es crear un flujo. En cada paso te diré el nombre del nodo a agregar para que lo puedas buscar así:

Add node

Paso a paso:

Nodo 1 - Trigger IMAP

Agrega el nodo Email Trigger (IMAP), el cual será el activador de nuestro flujo y revisará los correos sin leer en nuestro buzón.

  1. 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)
  • Port: 993
  • Secure: true
  1. 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.

Imap config

Por defecto, cuando publiquemos el workflow el nodo hará polling cada cierto tiempo (por defecto cada 60 segundos) para detectar correos nuevos.

Nodo 2 - Code (Base de conocimiento)

Code Know

El "secreto" del asistente está aquí. En lugar de dejar que DeepSeek improvise, le defines un contexto claro con las respuestas que esperas.

Agrega un nodo Code (Code in Javascript), cambia el modo a "Run Once for All Items" (arriba a la derecha del editor) y conéctalo al Nodo 1 (IMAP).

El código debe preservar los datos del correo que nos interesan y agregar el campo 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
  }
}));
Enter fullscreen mode Exit fullscreen mode

Puedes hacer esto tan detallado como quieras. Mientras más contexto, mejor responderá. Al usar ...item.json los datos del correo original se conservan y el Nodo 3 (extraer contenido) los recibe sin problema.

Este nodo se llamará, por ejemplo, CodeKnow.

Nodo 3 - Code (extraer contenido)

Usa otro nodo Code (Code in Javascript) para extraer la información necesaria de cada correo y generar el chatInput con el prompt que enviaremos a nuestra IA. Cambia el modo a "Run for Each Item" :

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)}`
};
Enter fullscreen mode Exit fullscreen mode

Process emails

Nodo 4 - DeepSeek Chat Model (configuración)

Agrega un nodo DeepSeek Chat Model. Es probable que esto te genere 3 nodos automáticamente: When chatmessage received, Basic LLM Chain y DeepSeek Chat Model. Quédate solo con el LLM y DeepSeek, el otro sobra. Conecta el bloque de código con el de Basic LLM, así:

Setup Deepseek

En los bloques que nos quedan debemos:

  1. En DeepSeek Chat Model, solo especificar las credenciales:
  • Credential: selecciona o crea una credencial DeepSeek account
    • API Key: tu clave de DeepSeek
  • Model: deepseek-v4-flash
  1. 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: SystemMessage: {{ $json.knowledgeBase }}
  • Require Specific Output Format: desactivado

Lo que hemos hecho es enviarle un prompt con nuestra intención y la data del correo que definimos en el bloque CodeProcessEmail junto con un mensaje de sistema con nuestra base de conocimiento, información que definimos en el bloque CodeKnow.

IA config

¿Y el costo? DeepSeek v4 cobra ~$0.14 por millón de tokens de entrada y ~$0.28 por salida. Un correo típico (~1,000 tokens) cuesta ~$0.0002. Con 1,000 correos al mes gastarías ~$0.20. En ajustes para producción te muestro cómo filtrar para evitar llamadas innecesarias.

El nodo toma el chatInput del Nodo 3 (base de conocimiento + correo) y devuelve la respuesta generada por DeepSeek.

Nodo 5 - Code (mapear respuesta del asistente)

Code Normalize

El bloque de DeepSeek solo nos retorna la respuesta de la IA con lo cual perdemos la información completa del correo que necesitamos más adelante. Por eso agregamos este nodo Code en modo "Run Once for All Items" que combina la respuesta de la IA con los datos del correo original y determina si puede responder o no:

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;
Enter fullscreen mode Exit fullscreen mode

Este bloque es clave porque:

  • 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

Nodo 6 - IF (¿Puede responder?)

Condition

Teniendo a la mano la respuesta de la IA y la información del correo, agregamos un bloque if. Este bloque evalúa el campo {{ $json.canReply }} con la condición:

  • (true) → va a envío SMTP
  • No (false) → va a notificación Telegram

Nodo 7.1 - Email (SMTP) - Responder

Smtp

Configura el nodo Send Email para enviar la respuesta automática:

  • 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 }}

Nodo 7.2 - Telegram - Enviar notificación

Para los correos que la IA no puede responder, no enviaremos una respuesta automática. En su lugar, recibirás una alerta por Telegram.

Sin embargo, antes debemos verificar que no vamos a enviar mensajes de más de 4.000 caracteres —el límite de Telegram—. Para ello:

  1. Agregamos un nodo Code (JavaScript) en modo Run Once for All Items con el código:
const escapeHtml = (value) => {
  return String(value || '')
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;');
};
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;
Enter fullscreen mode Exit fullscreen mode

Telegram code

  1. Agregamos un nodo de tipo HTTP Request para enviar cada uno de los mensajes que definimos
  2. Method: POST
  3. URL: https://api.telegram.org/bot{TuTokenTelegram,formato:0000:xxxxxx}/sendMessage
  4. Authentication: none
  5. SendBody: true
  6. Body Content Type: JSON
  7. Specify Body: Using Fields Below
    1. chat_id: tu ID de conversación en Telegram
    2. text: {{ $json.text }}
    3. parse_mode: HTML
    4. disable_web_page_preview: TRUE

Setup telegram1

Setup telegram2


Listo, con esto hemos terminado nuestro flujo :D

Workflow


3. Probar el flujo

⚠️ Antes de lanzarte a producción, haz pruebas controladas. No conectes este flujo directamente a tu buzón personal o corporativo. Usa una cuenta de correo de pruebas (IMAP + SMTP) que no contenga información sensible ni confidencial. Si algo sale mal — una mala interpretación de la IA, un dominio mal configurado — podrías terminar respondiendo automáticamente a clientes reales con información incorrecta. Mejor prevenir.

Con el flujo listo, haz lo siguiente:

  1. 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.
  2. Envíate un correo de prueba con una pregunta que esté en tu base de conocimiento.
  3. Revisa que recibas la respuesta automática en la bandeja del remitente de prueba.
  4. Envíate otro correo con algo fuera de tu base de conocimiento.
  5. Deberías recibir la notificación en Telegram con el contenido del correo.

Cuando todo funcione como esperas, solo da clic en Publish para activar el polling y dejarlo en producción.


4. Ajustes para producción

Filtrar por remitente

Agrega un nodo IF después del trigger para procesar solo correos de dominios o direcciones específicas:

const from = $input.item.json.from;
const allowedDomains = ['tudominio.com', 'cliente.com'];
const domain = from.split('@')[1];
return allowedDomains.includes(domain);
Enter fullscreen mode Exit fullscreen mode

Rate limiting

DeepSeek tiene límites de peticiones por minuto. Si esperas muchos correos, agrega un nodo Wait de 1-2 segundos entre procesamiento y procesamiento, o usa una cola.

Historial de conversación

Si quieres que DeepSeek recuerde conversaciones anteriores, puedes almacenar el historial en una base de datos (PostgreSQL, Redis) y pasarlo como contexto adicional en cada iteración.

Manejo de adjuntos

DeepSeek no procesa archivos directamente. Si recibes correos con adjuntos, puedes usar un nodo Code para extraer el texto de PDFs o imágenes (con OCR) y pasarlo como contexto.


Conclusión

Tienes un asistente de correo automatizado que:

  • 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

Esto no reemplaza un equipo de soporte, pero sí absorbe el volumen de preguntas repetitivas y libera tiempo para lo que realmente importa.

Si quieres documentar visualmente este flujo o diagramas de infraestructura más complejos, Savnet te ayuda a diseñarlos. Y si necesitas validar este tipo de automatizaciones de forma continua, SavFalconEye te permite mantener la confianza en cada cambio.


¿Te animas a probarlo? Cuéntame en los comentarios cómo te fue.

Top comments (0)