Build an auto-reply email assistant with n8n and DeepSeek

A MacBook with lines of code on its screen on a busy desk

Repetitive support emails are a real time tax. FAQs, hours questions, password resets, refund policies: you know the answer before you finish reading the subject line. This guide shows you how to build a workflow in n8n that reads those emails automatically, checks them against a knowledge base you define, sends a reply when it has enough context, and fires a Telegram alert when a human needs to step in.

The total LLM cost for 1,000 emails a month runs about $0.20 using DeepSeek. The Telegram bot is free. If you already have n8n running on a server, the only recurring cost is a Claude-equivalent API subscription.

️ What You Need Before You Start

  • A server with n8n installed and running
  • An email account with IMAP and SMTP access (Gmail, Outlook, ZohoMail, or any compatible provider)
  • A DeepSeek API key from platform.deepseek.com
  • A Telegram bot token and your Chat ID (instructions below)

Get your DeepSeek API key

Sign up at platform.deepseek.com, go to the API Keys section, and create a new key. You’ll use:

  • API key: your DEEPSEEK_API_KEY
  • Endpoint: https://api.deepseek.com/v1/chat/completions
  • Model: deepseek-chat

Create your Telegram bot and get your Chat ID

Open Telegram, search for @BotFather, send /newbot, and follow the steps. You’ll receive a token in the format 4839574812:AAFD39kkdpWt3ywyRZergyOLMaJhac60qc. No company registration, no credit card required.

To find your Chat ID, search for @userinfobot in Telegram and send it Start. It replies immediately with your user info. The number next to Id: is your Chat ID. Save both values.

smartphone screen showing facebook application

Building the Workflow: 7 Nodes

Node 1: IMAP Trigger

Add the Email Trigger (IMAP) node. This is the workflow’s entry point. It polls for unread emails every 60 seconds once the workflow is published.

Configure the credential with your email provider’s values:

  • User: your email address
  • Password: your password or app password
  • Host: your IMAP server (e.g. imap.gmail.com)
  • Port: 993
  • Secure: true

Set Mailbox Name to INBOX and Action to Mark as Read so every processed email gets flagged and won’t trigger twice.

Node 2: Code — Knowledge Base

This is the core of the assistant. Add a Code node (JavaScript), set the mode to Run Once for All Items, and connect it to Node 1.

The code injects a knowledgeBase string into the email data. That string is your policy document: business hours, refund terms, common error codes, anything DeepSeek should use when composing a reply. It also instructs the model to return exactly NO_PUEDO_RESPONDER when it can’t answer confidently. The ...item.json spread preserves the original email fields so downstream nodes can still access them.

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
  }
}));

The more detailed your knowledge base, the better the auto-reply quality. Add pricing tiers, SLA commitments, escalation paths: anything your team handles on repeat.

Node 3: Code — Extract Content

Add a second Code node (JavaScript), this time in Run for Each Item mode. It pulls subject, body, sender, recipient, and UID from the email object, then assembles the chatInput string that gets passed to DeepSeek. Body text is capped at 5,000 characters.

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)}`
};

Node 4: DeepSeek Chat Model

Add a DeepSeek Chat Model node. n8n will likely auto-generate three nodes: When chatmessage received, Basic LLM Chain, and DeepSeek Chat Model. Delete the first one. Keep and connect the other two.

In DeepSeek Chat Model, configure your API key credential and set the model to deepseek-v4-flash.

In Basic LLM Chain, configure:

  • 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 }}
  • Require Specific Output Format: disabled

DeepSeek charges approximately $0.14 per million input tokens and $0.28 per million output tokens. A typical email at around 1,000 tokens costs roughly $0.0002. At 1,000 emails a month, the total is about $0.20.

Node 5: Code — Map Assistant Response

DeepSeek’s output node only returns the AI response text. It drops all the email metadata you’ll need to send the reply. This node merges the AI output back with the original email data and adds a canReply boolean.

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;

If DeepSeek’s response contains NO_PUEDO_RESPONDER, canReply is set to false and the email gets routed to Telegram instead of being auto-replied.

person using smartphone

Node 6: IF — Can it reply?

Add an IF node that evaluates {{ $json.canReply }}:

  • True: route to the SMTP send node
  • False: route to the Telegram notification node

Node 7a: Send Email (SMTP)

Configure the Send Email node with your SMTP credentials. Set:

  • From Email: {{ $json.to }} (replies from the address the email was sent to)
  • To: {{ $json.from }}
  • Subject: Re: {{ $('CodeProcessEmail').item.json.subject }}
  • Email Format: HTML
  • Text: {{ $json.aiResponse }}

Node 7b: Telegram Notification

Telegram enforces a 4,000-character message limit. Add a Code node first to chunk any batch of flagged emails into segments of 3,900 characters each, then send each chunk via an HTTP Request node.

The chunking code escapes HTML, builds a numbered summary of each flagged email, and splits the output into multiple items if needed:

const escapeHtml = (value) => {
  return String(value || '')
    .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`;
});

const chunkSize = 3900;
const header = `━━━━━━━━━━━━━━━━━━━━n<b>Recibiste los siguientes correos:</b>nn`;

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;

The HTTP Request node that follows sends each chunk to Telegram’s API:

  • Method: POST
  • URL: https://api.telegram.org/bot{YourToken}/sendMessage
  • Body: JSON with fields chat_id, text ({{ $json.text }}), parse_mode: HTML, disable_web_page_preview: true

Testing Before You Go Live

Don’t connect this workflow to your real inbox during testing. Use a dedicated test email account with no sensitive data. A bad AI interpretation or misconfigured domain could trigger auto-replies to real customers.

Click Execute Workflow to trigger it manually without waiting for the 60-second polling cycle. Send a test email that matches something in your knowledge base and confirm you receive the auto-reply. Then send something outside the knowledge base and confirm the Telegram alert arrives. Once both paths work, click Publish.

Production Tweaks Worth Adding

Filter by sender domain

Add an IF node after the IMAP trigger to skip emails from senders outside your expected domains. This prevents the workflow from processing spam and avoids unnecessary DeepSeek API calls:

const from = $input.item.json.from;
const allowedDomains = ['yourdomain.com', 'client.com'];
const domain = from.split('@')[1];
return allowedDomains.includes(domain);

Rate limiting

DeepSeek has rate limits per minute. If you expect high email volume, insert a Wait node of 1 to 2 seconds between processing batches, or route items through a queue.

Conversation history

If you want DeepSeek to remember prior context from a thread, store the conversation history in PostgreSQL or Redis and pass it as additional context on each iteration.

Handling attachments

DeepSeek doesn’t process files directly. If emails arrive with attachments, add a Code node to extract text from PDFs or images via OCR and pass the result as additional context in the prompt.

What You End Up With

A workflow that reads every inbound email via IMAP, checks the content against your custom knowledge base using DeepSeek, sends an automatic reply when it has a confident answer, and pushes a Telegram alert when it doesn’t. The total cost at 1,000 emails a month is approximately $0.20 in API usage. The manual reply queue shrinks to the edge cases only a human should handle.

Stay on top of AI & Automation with BizStack Newsletter
BizStack  —  Entrepreneur’s Business Stack
Logo