De la bandeja de entrada al caos cero: cómo automatizar Gmail sin perder la cabeza

Bandeja de entrada organizada en un portátil, representando un sistema de automatización de Gmail para reducir el ruido del correo electrónico

Si estás leyendo esto es porque —como yo— alguna vez has abierto Gmail y has sentido esa pequeña ansiedad de ver una bandeja de entrada llena de cosas que no pediste.

Newsletters que parecían interesantes hace seis meses. Notificaciones de GitHub. Alertas del homelab. Facturas. Confirmaciones de pedidos. Correos de bancos. Ofertas que caducan hoy. Redes sociales. Foros. Promociones. Y en medio de todo eso, el correo importante que de verdad necesitas atender.

Llevo años probando métodos: Inbox Zero, carpetas, etiquetas de colores, filtros manuales, estrellas, marcadores, prioridades, bandejas múltiples… Y al final todo se reduce a una verdad incómoda:

Gestionar el correo manualmente no escala.

Da igual lo organizado que seas. Si cada correo que entra exige una decisión manual, estás condenado. La solución no es ser más disciplinado. La solución es diseñar un sistema.

Y si puedes automatizar una decisión repetitiva, deberías automatizarla.

En este artículo voy a compartir mi sistema para automatizar Gmail: filtros nativos, etiquetas bien pensadas, categorías, reglas de revisión y algunos scripts con Google Apps Script para los casos donde Gmail se queda corto.

El objetivo no es tener una bandeja bonita. El objetivo es más simple: que solo llegue a tu vista lo que requiere tu atención.


Ojo con automatizar demasiado rápido. El correo mezcla ruido con información importante: bancos, proveedores, trabajo, facturas, alertas y accesos. Antes de borrar o archivar de forma agresiva, probaría las reglas en modo etiqueta durante unos días.

El patrón que sigo es sencillo: etiquetar → observar → archivar. Primero hago visible lo que la regla haría; solo después le doy permiso para sacar correos de mi vista.

La regla base: la bandeja de entrada no es un almacén

Antes de hablar de filtros, etiquetas o scripts, hay una idea que hay que tener clara.

La bandeja de entrada no debería ser un almacén. Debería ser una cola de trabajo.

Si algo está en la bandeja de entrada, significa una de estas cosas:

  • Tengo que responder.
  • Tengo que decidir.
  • Tengo que hacer algo.
  • Tengo que revisarlo hoy o esta semana.

Todo lo demás debería salir de ahí automáticamente.

No borrado necesariamente. No perdido. Simplemente fuera de la vista principal, bien etiquetado y localizable cuando lo necesites.

Ese cambio mental es el que transforma Gmail de “un sitio donde se acumula ruido” a “un sistema de entrada controlado”.


Fase 1: filtros nativos de Gmail

Antes de meter scripts, APIs o herramientas externas, Gmail ya tiene un sistema de filtros bastante potente.

El problema es que mucha gente crea dos o tres filtros y se olvida. Yo aplico una regla más agresiva:

Cada vez que veo un correo que no merece estar en mi bandeja principal, creo un filtro.

Esto al principio lleva un poco de tiempo. Luego se convierte en una rutina de 20 segundos.

Cómo crear filtros en Gmail

  • Abre un correo que quieras automatizar.
  • Haz clic en los tres puntos.
  • Selecciona Filtrar mensajes similares.
  • Ajusta los criterios: remitente, asunto, palabras clave, destinatario, tamaño, adjuntos, etc.
  • Elige la acción: Saltar Recibidos, aplicar etiqueta, marcar como leído, destacar, reenviar o eliminar.

La opción clave es Saltar Recibidos. En la interfaz inglesa aparece como Skip the Inbox. Lo que hace realmente es archivar el correo: desaparece de Recibidos, pero sigue estando en Gmail y puedes encontrarlo por búsqueda o por etiqueta.

Mi combinación favorita es:

Saltar Recibidos
Aplicar etiqueta
Marcar como leído, si no requiere acción

Eso convierte el correo en información consultable, no en ruido.

Buscar primero, filtrar después

Antes de convertir una regla en automática, la pruebo como búsqueda. Los criterios que utilizas para localizar correos son precisamente la parte delicada del filtro: si la búsqueda trae mensajes que no debería, el filtro hará lo mismo pero sin preguntarte.

Gmail permite combinar operadores muy útiles. No hace falta aprenderlos todos; con unos pocos puedes afinar muchísimo:

  • from: y to: para remitente y destinatario.
  • subject: para buscar en el asunto.
  • has:attachment para exigir adjuntos.
  • newer_than: y older_than: para acotar por antigüedad.
  • category: y label: para trabajar con categorías y etiquetas.
  • larger: para localizar mensajes grandes.
  • is:unread para limitar la búsqueda a no leídos.

Por ejemplo, antes de crear un filtro de facturas podría probar algo como from:[email protected] subject:(factura OR recibo) has:attachment newer_than:30d. Reviso los resultados, corrijo falsos positivos y solo entonces convierto esa búsqueda en filtro.

La documentación de búsqueda de Gmail tiene muchos más operadores. Yo prefiero empezar con los que resuelven un problema concreto y añadir complejidad solo cuando hace falta.

Antes de tocar muchos filtros, guarda una copia

Si voy a reorganizar una parte importante de mis reglas, primero exporto los filtros actuales. Gmail permite seleccionar filtros desde Filtros y direcciones bloqueadas, exportarlos a un archivo XML y volver a importarlos más adelante.

Es importante llamar a esto por su nombre: es una copia de la configuración de los filtros, no un backup de los mensajes de correo. Aun así, viene muy bien antes de una limpieza grande porque te permite volver atrás si una reorganización sale peor de lo esperado.

Google documenta la exportación e importación en la misma guía oficial de filtros de Gmail.


Mi taxonomía de etiquetas

Las etiquetas son útiles si no te vuelves loco creando cien. Yo las divido en tres bloques: acción, archivo y ruido.

📥 Acción
├── 📬 Pendiente        → Correos que requieren respuesta
├── 📋 Seguimiento      → Cosas que revisar esta semana
└── ⏳ Esperando        → Correos donde espero respuesta de otro

📦 Archivo
├── 🛒 Compras          → Facturas, pedidos, tracking
├── 🏦 Finanzas         → Bancos, inversiones, seguros
├── 🔐 Seguridad        → Alertas 2FA, cambios de contraseña
├── 🤖 DevOps           → GitHub, CI/CD, monitores, homelab
├── 📰 Newsletters      → Lectura semanal
└── 📆 Eventos          → Reservas, entradas, calendario

🧹 Ruido
├── 📢 Promociones      → Ofertas y descuentos
├── 🔔 Notificaciones   → Redes sociales, foros, plataformas
└── 🧪 Revisar filtro   → Correos que el sistema no tiene claro todavía

La etiqueta más importante de todas es 🧪 Revisar filtro.

No recomiendo automatizar de golpe correos ambiguos. Primero los mandas a una etiqueta de revisión. Si durante unas semanas ves que siempre son irrelevantes, ya puedes archivarlos automáticamente. Si alguno era importante, has evitado perderlo.

Automatizar bien no es automatizar a lo bruto. Es quitarte decisiones repetitivas sin perder control.

Para las reglas que pueden ocultar correo importante sigo tres fases:

  1. Etiquetar. La regla clasifica el mensaje, pero no lo saca todavía de mi vista.
  2. Observar. Durante unos días reviso qué cae ahí y busco falsos positivos.
  3. Archivar. Solo cuando el patrón es estable activo Saltar Recibidos o el archivado automático.

Si sigo teniendo dudas, la regla se queda en 🧪 Revisar filtro. No hay ningún premio por automatizar antes de tiempo.


Ejemplos prácticos de filtros

Estos ejemplos no son para copiarlos a ciegas. Son patrones. Lo correcto es ajustarlos a tus remitentes reales.

Y antes de pulsar Crear filtro, pegaría cada consulta en el buscador de Gmail. Si los resultados no son exactamente los que esperas, todavía no tienes un filtro: tienes una hipótesis que necesita afinarse.

Notificaciones de GitHub

from:([email protected])

Acciones:

Saltar Recibidos
Aplicar etiqueta: 🤖 DevOps
Marcar como leído

Si hay repositorios o menciones que sí quieres ver, crea una excepción o un filtro más específico.

Facturas y pedidos

from:(amazon.es OR paypal.es OR stripe.com) 
(subject:(factura OR recibo OR pedido OR enviado OR entregado))

Acciones:

Saltar Recibidos
Aplicar etiqueta: 🛒 Compras

Aquí no marcaría todo como leído de entrada. Las facturas y pedidos pueden requerir revisión, especialmente si hay importes altos o cargos inesperados.

Newsletters que sí quieres leer

from:(substack.com OR medium.com)
(subject:(newsletter OR weekly OR digest))

Acciones:

Saltar Recibidos
Aplicar etiqueta: 📰 Newsletters
Marcar como leído

Mi regla personal: una newsletter que no he leído en un mes se da de baja. Archivar ruido no es lo mismo que solucionar ruido.

Alertas de seguridad

subject:(security alert OR alerta de seguridad OR "new sign-in" OR "inicio de sesión")

Acciones:

Aplicar etiqueta: 🔐 Seguridad
No saltar Recibidos si requiere revisión

Con seguridad prefiero pecar de prudente. Las alertas críticas no deben desaparecer de la bandeja principal hasta que tengas claro cuáles son ruido y cuáles no.


Fase 2: usa bien las categorías de Gmail

Gmail ya clasifica automáticamente muchos correos en categorías como Principal, Social, Promociones, Actualizaciones y Foros cuando usas la bandeja predeterminada.

Estas categorías no son perfectas, pero ayudan bastante a reducir ruido.

Mi enfoque:

  • Principal: solo lo que puede requerir atención real.
  • Promociones: ofertas, descuentos, campañas y marketing.
  • Social: redes sociales y plataformas.
  • Actualizaciones: recibos, confirmaciones, extractos, avisos automáticos.
  • Foros: comunidades, grupos y listas.

Lo importante es no confiar ciegamente en las categorías. Gmail se equivoca. Por eso las uso como una primera capa, no como única capa.

Un flujo razonable sería:

  • Dejar que Gmail categorice.
  • Revisar durante unos días qué cae en cada pestaña.
  • Crear filtros para los patrones repetidos.
  • Aplicar etiquetas propias donde Gmail se queda corto.

En una tarde puedes eliminar gran parte del ruido, pero el sistema bueno se afina durante semanas.


Fase 3: Google Apps Script solo para lo que Gmail no puede hacer

Los filtros nativos cubren muchísimo. Pero tienen límites.

Un filtro de Gmail no puede hacer una llamada HTTP a Telegram. No puede aplicar lógica avanzada con importes. No puede generar un resumen semanal. No puede decidir en función de varios mensajes de un hilo de forma elaborada.

Para eso entra Google Apps Script.

Apps Script es una plataforma de automatización de Google que permite ejecutar código en la nube y trabajar con servicios como Gmail, Drive, Calendar o Sheets. Es muy potente, pero hay que usarlo con cabeza.

¿Filtro de Gmail o Apps Script?

La frontera que uso es sencilla: si Gmail puede resolverlo con una regla declarativa, lo dejo en Gmail. Si necesito lógica, tiempo, cálculos o salir de Gmail, entonces valoro Apps Script.

Necesidad Filtro de Gmail Apps Script
Clasificar por remitente, asunto o palabras Sí No hace falta
Etiquetar, archivar o marcar como leído Sí No hace falta
Evaluar un importe y tomar decisiones Se queda corto Sí
Generar un resumen semanal No Sí
Enviar una alerta a Telegram No Sí

Mis reglas:

  • No uso Apps Script si un filtro normal basta.
  • No proceso todo Gmail cada hora sin necesidad.
  • No borro correos automáticamente salvo casos muy claros.
  • No archivo correos críticos sin una fase previa de revisión.
  • No guardo tokens en el código.

Los triggers no son tiempo real

Apps Script no ofrece un trigger instalable genérico de «ha llegado un correo nuevo» para Gmail. Para estos ejemplos uso disparadores temporales: cada cierto tiempo se ejecuta una función, hace una búsqueda acotada y procesa lo que siga pendiente.

Eso es polling, no tiempo real. Para un resumen semanal es obvio; para una alerta de facturas también suele ser suficiente si eliges una frecuencia razonable. Si necesitas reacción inmediata y garantías más fuertes, ya estarías entrando en otro tipo de arquitectura.

También prefiero trabajar por lotes. En los ejemplos uso GmailApp.search(query, 0, 50): cada ejecución toma como máximo 50 hilos pendientes. Lo que termina queda marcado y la siguiente ejecución vuelve a empezar por el primer conjunto todavía pendiente. Así no recorro todo el buzón ni mantengo offsets sobre una lista que va cambiando.

Los triggers instalables y la variante paginada de GmailApp.search() están documentados por Google.

Apps Script tiene cuotas y límites. No me interesa llenar aquí una tabla de cifras que puede quedar vieja: dependen del servicio y del tipo de cuenta, y Google puede modificarlas. La idea importante es diseñar scripts acotados, revisar la documentación oficial de cuotas si aumentas el volumen y no tratar Apps Script como si fuera un backend infinito.


Ejemplo: archivado prudente de facturas

Este ejemplo busca correos recientes relacionados con facturas, intenta detectar importes y actúa con prudencia. Además, utiliza una etiqueta técnica para no volver a procesar normalmente el mismo hilo en ejecuciones posteriores.

Si no puede interpretar un importe, manda el hilo a 🧪 Revisar filtro. Si el importe supera el umbral del ejemplo, lo manda a seguimiento y envía una alerta por Telegram. Si el importe es normal, lo etiqueta como compra y lo archiva.

function archiveInvoices() {
  const lock = LockService.getScriptLock();

  // Si otra ejecución está en curso, finalizar limpiamente:
  // los pendientes quedan para la siguiente ejecución del trigger.
  if (!lock.tryLock(10000)) {
    console.log('archiveInvoices: ya hay otra ejecución en curso; se omite este ciclo');
    return;
  }

  try {
    const query = 'in:inbox newer_than:7d -label:auto_factura_procesada (factura OR recibo OR "confirmación de pago" OR invoice OR receipt)';
    const threads = GmailApp.search(query, 0, 50);

    const purchasesLabel = getOrCreateLabel_('🛒 Compras');
    const followUpLabel = getOrCreateLabel_('📋 Seguimiento');
    const processedLabel = getOrCreateLabel_('auto_factura_procesada');

    console.log('archiveInvoices: ' + threads.length + ' facturas pendientes');

    threads.forEach(thread => {
      const messages = thread.getMessages();
      const lastMessage = messages[messages.length - 1];
      const subject = lastMessage.getSubject();
      const body = lastMessage.getPlainBody();

      const amount = extractEuroAmount_(body);

      if (amount === null) {
        thread.addLabel(getOrCreateLabel_('🧪 Revisar filtro'));
        thread.addLabel(processedLabel);
        return;
      }

      if (amount > 500) {
        thread.addLabel(followUpLabel);
        sendTelegramAlert_(
          'Factura de importe elevado\nSe ha detectado una factura de ' +
          amount.toFixed(2) + ' €. Revisa el hilo: ' + subject
        );
        thread.addLabel(processedLabel);
        return;
      }

      thread.addLabel(purchasesLabel);
      thread.moveToArchive();
      thread.addLabel(processedLabel);
    });
  } finally {
    lock.releaseLock();
  }
}

function getOrCreateLabel_(name) {
  return GmailApp.getUserLabelByName(name) || GmailApp.createLabel(name);
}

function extractEuroAmount_(text) {
  const matches = text.match(/(\d{1,3}(?:\.\d{3})*|\d+),(\d{2})\s*€/g);

  if (!matches || matches.length === 0) {
    return null;
  }

  const values = matches.map(match => {
    const clean = match
      .replace('€', '')
      .trim()
      .replace(/\./g, '')
      .replace(',', '.');

    return parseFloat(clean);
  }).filter(value => !isNaN(value));

  if (values.length === 0) {
    return null;
  }

  return Math.max.apply(null, values);
}

Hay varias decisiones deliberadas aquí.

  • auto_factura_procesada es una marca técnica de esta automatización. Significa que el script ya evaluó ese hilo por una de sus ramas; no significa que la factura esté pagada, validada o gestionada por una persona.
  • La búsqueda excluye -label:auto_factura_procesada, de modo que una ejecución normal no vuelve a seleccionar lo que ya terminó.
  • Si la alerta de Telegram falla, la excepción impide aplicar la marca técnica. El hilo queda pendiente para que una ejecución posterior pueda volver a intentarlo.
  • LockService evita que dos ejecuciones del mismo proyecto entren a la vez en esta sección crítica. Si el lock no está disponible, el ciclo termina limpiamente y deja el trabajo pendiente.

El extractor de importes también es intencionadamente conservador. El ejemplo reconoce formatos como 500,00 € o 1.234,56 €; un texto como 500 € no coincide y termina en 🧪 Revisar filtro. Prefiero un falso «necesito revisar esto» a inventarme un parser universal de facturas.

El umbral de 500 € y la ventana de 7 días son ejemplos. Cámbialos por valores que tengan sentido para ti.

La etiqueta y el lock reducen mucho los duplicados normales, pero no prometen exactly-once. Hay una ventana pequeña que no intento esconder: Telegram puede aceptar el mensaje y el script podría interrumpirse justo antes de añadir auto_factura_procesada. En ese caso, una ejecución posterior podría volver a alertar. Resolver eso de forma absoluta exigiría bastante más infraestructura y dejaría de ser un ejemplo sencillo.

La función archiveInvoices() llama a sendTelegramAlert_(), que definimos en la Fase 4. Si vas implementando el artículo paso a paso, añade también ese bloque antes de activar el trigger.

Para instalarlo:

  • Ve a script.google.com.
  • Crea un nuevo proyecto.
  • Pega el código.
  • Ejecuta una vez manualmente para autorizar permisos.
  • Crea un disparador horario si todo funciona.

Importante: antes de dejarlo en automático, cambia temporalmente thread.moveToArchive() por una etiqueta de revisión. Durante unos días comprueba que clasifica bien. Luego ya automatizas.


Resumen semanal de newsletters

Este patrón me gusta mucho porque elimina la interrupción diaria sin perder lectura interesante.

La idea:

  • Las newsletters se etiquetan automáticamente como 📰 Newsletters.
  • No aparecen en Recibidos.
  • Una vez por semana recibes un resumen con enlaces a los hilos.

Antes de automatizarlo, probaría en la búsqueda de Gmail la consulta label:"📰 Newsletters" -label:auto_newsletter_resumida y comprobaría que devuelve exactamente lo que esperas en tu cuenta. El ejemplo usa ese nombre de etiqueta; si tú utilizas otro, adapta la consulta y el código.

function weeklyNewsletterDigest() {
  const lock = LockService.getScriptLock();

  // Si otra ejecución está en curso, finalizar limpiamente:
  // el resumen se construye una sola vez por ciclo.
  if (!lock.tryLock(10000)) {
    console.log('weeklyNewsletterDigest: ya hay otra ejecución en curso; se omite este ciclo');
    return;
  }

  try {
    const label = GmailApp.getUserLabelByName('📰 Newsletters');

    if (!label) {
      return;
    }

    const summarizedLabel = getOrCreateLabel_('auto_newsletter_resumida');

    // Siempre desde el primer conjunto pendiente (start=0); sin offsets
    // acumulativos sobre un conjunto que va cambiando.
    const query = 'label:"📰 Newsletters" -label:auto_newsletter_resumida';
    const threads = GmailApp.search(query, 0, 50);

    if (threads.length === 0) {
      return;
    }

    let digest = 'Tu resumen semanal de newsletters:\n\n';

    threads.forEach(thread => {
      digest += '- ' + thread.getFirstMessageSubject() + '\n';
      digest += '  ' + thread.getPermalink() + '\n\n';
    });

    // La llamada de envío termina sin excepción; no confirma entrega
    // al destinatario final (MailApp no ofrece recibo de entrega).
    MailApp.sendEmail(
      Session.getEffectiveUser().getEmail(),
      '📰 Resumen semanal de newsletters',
      digest
    );

    // Etiquetado por lote tras el envío correcto (GmailLabel.addToThreads,
    // hasta 100 hilos por llamada; nuestro lote es 50). No es una operación
    // transaccional/atómica: reduce llamadas a la API y simplifica el ejemplo.
    summarizedLabel.addToThreads(threads);

    threads.forEach(thread => {
      thread.markRead();
      thread.moveToArchive();
    });

    console.log('weeklyNewsletterDigest: llamada de envío terminada sin excepción (' + threads.length + ' newsletters)');
  } finally {
    lock.releaseLock();
  }
}

auto_newsletter_resumida es otra marca técnica independiente. No sustituye a 📰 Newsletters: la primera dice «este hilo ya entró en un resumen» y la segunda sigue siendo mi clasificación visible para conservar el histórico.

El script toma como máximo 50 hilos por ejecución. Si hay más, los restantes siguen sin la marca y quedan para el siguiente ciclo. Después de que MailApp.sendEmail() termine sin lanzar una excepción, la etiqueta técnica se aplica al lote de una sola vez y luego los hilos se marcan como leídos y se archivan.

Como este ejemplo está pensado para un trigger instalable, envío el resumen a Session.getEffectiveUser().getEmail(): la cuenta bajo cuya autoridad se está ejecutando el script. En un trigger instalable corresponde a la cuenta que creó ese trigger; Google lo documenta en la referencia de Session.

Eso tampoco es una confirmación de entrega al destinatario. Solo sabemos que la llamada de envío terminó sin excepción. Y existe la misma ventana residual que en el ejemplo anterior: si el envío termina y el proceso se interrumpe antes de marcar los hilos, ese lote podría reaparecer en un resumen posterior.

Los dos ejemplos usan getScriptLock(). Si viven en el mismo proyecto y sus triggers coinciden, uno puede adquirir el lock y el otro saltarse ese ciclo. Lo acepto como un trade-off de simplicidad: no pierdo el trabajo, porque lo que no se procesa sigue pendiente para la siguiente ejecución.

No elimino la etiqueta automáticamente en este ejemplo. Prefiero conservarla para tener histórico. Si quieres limpiar la etiqueta después de enviar el resumen, puedes hacerlo, pero yo no lo haría al principio.


Fase 4: notificaciones inteligentes por Telegram

Gmail te puede notificar, pero suele ser demasiado binario: o te avisa de demasiado, o te pierdes cosas.

Con Apps Script puedes crear notificaciones más inteligentes.

Mi flujo sería este:

  • Gmail recibe el correo.
  • Filtros nativos etiquetan y limpian lo evidente.
  • Apps Script revisa solo correos recientes y relevantes.
  • Si algo cumple una condición crítica, envía una alerta por Telegram.
  • El resto se queda archivado o etiquetado para revisión posterior.

En el ejemplo de facturas, archiveInvoices() llama a esta función cuando detecta un importe superior al umbral. La diferencia respecto al bloque original es que aquí no doy por hecho que un fetch() haya funcionado: compruebo el código HTTP, intento interpretar la respuesta JSON y verifico el campo ok que devuelve la API de Telegram.

Ejemplo de función para Telegram usando propiedades del script en lugar de tokens hardcodeados:

function sendTelegramAlert_(message) {
  const properties = PropertiesService.getScriptProperties();
  const token = properties.getProperty('TELEGRAM_BOT_TOKEN');
  const chatId = properties.getProperty('TELEGRAM_CHAT_ID');

  if (!token || !chatId) {
    throw new Error('Faltan TELEGRAM_BOT_TOKEN o TELEGRAM_CHAT_ID en Script Properties');
  }

  const url = 'https://api.telegram.org/bot' + token + '/sendMessage';

  let response;
  try {
    response = UrlFetchApp.fetch(url, {
      method: 'post',
      payload: {
        chat_id: chatId,
        text: message
      },
      muteHttpExceptions: true
    });
  } catch (error) {
    // No loguear la excepción original: podría contener la URL (con token).
    console.error('sendTelegramAlert_: no se pudo contactar con Telegram');
    throw new Error('No se pudo contactar con Telegram');
  }

  const httpCode = response.getResponseCode();

  if (httpCode !== 200) {
    console.error('sendTelegramAlert_: Telegram respondió con HTTP ' + httpCode);
    throw new Error('Telegram respondió con HTTP ' + httpCode + ' al enviar el mensaje');
  }

  let json;
  try {
    json = JSON.parse(response.getContentText());
  } catch (error) {
    console.error('sendTelegramAlert_: respuesta de Telegram no es JSON');
    throw new Error('Telegram devolvió una respuesta inesperada (no JSON)');
  }

  if (json.ok !== true) {
    const description = json.description || 'sin descripción';
    console.error('sendTelegramAlert_: Telegram rechazó el mensaje (error_code ' + (json.error_code || '?') + ')');
    throw new Error('Telegram rechazó el mensaje: ' + description);
  }

  console.log('sendTelegramAlert_: mensaje enviado correctamente');
}

Para guardar las propiedades:

  • En Apps Script, ve a Project Settings.
  • Busca Script Properties.
  • Añade TELEGRAM_BOT_TOKEN.
  • Añade TELEGRAM_CHAT_ID.

No pongas el token del bot escrito directamente en el código. Es cómodo, pero es mala práctica. Y si algún día compartes el script o haces una captura, ya la has liado.

PropertiesService ayuda a sacar configuración del código, pero no es un gestor de secretos ni un vault. Si compartes el proyecto, revisa quién tiene acceso al script y a sus propiedades. Para un script personal es una solución práctica para no dejar el token incrustado en un bloque que acabarás copiando, versionando o enseñando.

También evito registrar la URL completa de Telegram, la petición o el token. En un error de red, el ejemplo escribe un mensaje sanitizado; en un error de API conserva información útil como el código HTTP o la descripción que devuelve Telegram sin imprimir la credencial.

Ten en cuenta además qué información mandas fuera de Gmail. Este ejemplo envía a Telegram el importe detectado y el asunto del hilo, no el cuerpo completo del correo. Si incluso ese dato es sensible en tu contexto, reduce el mensaje o no uses ese canal para esa alerta.

Cómo saber si la automatización ha dejado de funcionar

Una automatización que falla en silencio puede ser peor que una tarea manual, porque deja de hacer su trabajo mientras tú sigues confiando en ella.

Por eso no doy por terminado un script cuando «funciona una vez». Después de crear los triggers reviso también:

  • el historial de Executions / My Executions para ver estado, duración y errores;
  • console.log() para contadores y eventos no sensibles, nunca para volcar cuerpos de correo o tokens;
  • console.error() para fallos que merecen diagnóstico;
  • los avisos de error que Apps Script envía cuando falla un trigger instalable.

Si necesitas ir más lejos, Apps Script también se integra con Cloud Logging y Error Reporting. Para estos ejemplos no hace falta montar un sistema de observabilidad enorme; sí hace falta poder responder a una pregunta básica: ¿sé si mi automatización dejó de funcionar ayer?

Google mantiene la documentación de logging y ejecuciones, y la Bot API de Telegram documenta la respuesta de sendMessage.


El resultado después de un mes

Bandeja de entrada de Gmail organizada con etiquetas y pocos correos pendientes tras aplicar filtros y automatizaciones

Implementar este sistema me llevó una tarde. El primer mes fue de ajuste: filtros que se quedaban cortos, remitentes que cambiaban, newsletters que ya no me interesaban, facturas que necesitaban una excepción, alertas que eran ruido.

Pero al cabo de unas semanas el cambio se nota muchísimo.

  • Muchos menos correos en Recibidos.
  • Menos interrupciones durante el día.
  • Más facilidad para encontrar facturas, pedidos y alertas.
  • Menos miedo a perder algo importante.
  • Una revisión diaria mucho más rápida.

No he medido el ahorro con suficiente rigor como para convertirlo en porcentajes o minutos recuperados. Prefiero quedarme con algo más sencillo: en mi caso, la bandeja de entrada terminó siendo mucho más manejable.

Y eso ya cambia mucho.

Si te ha interesado la automatización del correo, los mismos principios se aplican a otras áreas. Los agentes de IA llevan esta idea un paso más allá: sistemas que no solo clasifican información, sino que pueden proponer acciones. Y en Ciberseguridad Hoy hablo de cómo proteger tu infraestructura digital, incluyendo muchas de esas alertas que acaban llegando por correo.


Para llevar

  • Empieza por filtros nativos. Cubren la mayoría de casos y no requieren código.
  • Usa etiquetas claras. Los emojis ayudan visualmente, pero lo importante es que la estructura sea simple.
  • No automatices a ciegas. Primero etiqueta para revisar; luego archiva si estás seguro.
  • Usa Apps Script solo para lo complejo. Si un filtro basta, no escribas código.
  • No incrustes tokens en el código. En un script personal, PropertiesService permite sacar esa configuración del código, pero no es un vault: controla quién tiene acceso al proyecto.
  • Ten en cuenta las cuotas. Apps Script no es un backend infinito.
  • Revisa el sistema cada mes. Remitentes, necesidades y filtros cambian.
  • Da de baja newsletters que no lees. Archivar basura no deja de ser gestionar basura.

La bandeja de entrada ordenada no es un lujo. Es una decisión técnica.

Y como casi todo en tecnología, si puedes convertir una decisión repetitiva en una regla fiable, ganas tiempo, foco y tranquilidad.


¿Tienes tu propio sistema de automatización de correo? ¿Usas filtros, etiquetas, Betterbird, Thunderbird, Spike, scripts caseros o algo más avanzado? Cuéntalo en los comentarios — siempre se aprende de cómo otros resuelven el mismo problema.

Continúa leyendo

Lo que mi homelab me enseña como CIO técnico

¿Quieres seguir explorando?

Puedes descubrir más artículos, seguir mis publicaciones en LinkedIn o escribirme.

Deja un comentario

Julio Rodas

Tecnología sin humo. Cómo pienso, pruebo y tomo decisiones tecnológicas.

Cómo trabajo  ·  Sobre mí  ·  Artículos  ·  Contacto

Invítame a un café

Aviso Legal  ·  Política de Privacidad  ·  Política de Cookies

Las opiniones expresadas en esta web son personales y no representan necesariamente la posición de mi empleador ni de ninguna organización con la que mantenga una relación profesional.

© 2026 Julio Rodas