Una variable de automatización es lo que separa un genérico "Su ticket fue actualizado" de un "Ticket 12345 - Impresora sin tóner pasó a En atención, con la técnica Ana Paula". En GLPI estas variables son las etiquetas de notificación: marcadores ##...## que el motor reemplaza por el dato real en el momento del envío. Parecen triviales hasta el día en que el nombre del solicitante sale en blanco en el correo y nadie sabe por qué. Esta guía es el mapa que usamos al dar soporte a parques GLPI de clientes para acertar la plantilla a la primera.
Dónde viven las variables: plantilla no es notificación
Antes de elegir etiquetas, entiende la cadena que GLPI arma, porque la mayoría de los "la variable no funciona" son en realidad errores de configuración, no de sintaxis. Un mensaje solo sale cuando cuatro piezas están alineadas:
- Notificación (Configurar > Notificaciones): activa el evento - nuevo ticket, seguimiento, solución, encuesta de satisfacción.
- Plantilla (Plantillas de notificación): el cuerpo en texto y el cuerpo en HTML, donde escribes las etiquetas
##...##. - Destinatarios: quién lo recibe - solicitante, técnico asignado, grupo, observador.
- Cola y envío: GLPI no manda el correo al instante; lo encola y la tarea automática
queuednotificationlo despacha.
Poner la etiqueta correcta en una plantilla que no está vinculada a ninguna notificación activa no produce ningún correo - y no es culpa de la etiqueta.
Las etiquetas que realmente usas
Las etiquetas son contextuales: el conjunto disponible cambia según el elemento (Ticket, Change, Problem). Para tickets, estas cubren la mayoría de las plantillas - todas verificadas directamente en el motor de notificación de GLPI 11:
| Etiqueta | Qué devuelve |
|---|---|
##ticket.id## | Número del ticket |
##ticket.title## | Título |
##ticket.description## | Descripción (contenido de apertura) |
##ticket.url## | Enlace directo al ticket (requiere inicio de sesión) |
##ticket.status## | Estado actual |
##ticket.priority## | Prioridad |
##ticket.category## | Categoría |
##ticket.creationdate## | Fecha de apertura |
##ticket.solvedate## | Fecha de solución |
##ticket.duedate## | Plazo de resolución (SLA) |
##ticket.authors## | Solicitante(s) - lista separada por comas |
##ticket.assigntousers## | Técnico(s) asignado(s) - lista por comas |
##ticket.assigntogroups## | Grupo(s) asignado(s) |
##ticket.solution## | Texto de la solución |
##followup.author## / ##followup.description## | Dentro de ##FOREACHfollowups## |
##task.author## / ##task.description## | Dentro de ##FOREACHtasks## |
##author.name## / ##author.email## | Dentro de ##FOREACHauthors## |
Fíjate en que ##ticket.assigntousers## devuelve una lista ya lista, separada por comas - GLPI hace el implode internamente. No es un bucle, es texto plano: resuelve "tengo dos técnicos y quiero a ambos en el correo" sin ningún truco.
El error de campo más común: el solicitante no es ##user.name##
Este es, de lejos, el problema que más reabrimos en auditorías de plantilla: el nombre del solicitante llega en blanco. La causa casi siempre es la misma - alguien copió ##user.name## de un tutorial de recuperación de contraseña dentro de una notificación de ticket. En una notificación de Ticket, ##user.name## simplemente no existe: pertenece a las notificaciones del objeto Usuario (reset de contraseña, creación de cuenta). GLPI no da error - solo sustituye por vacío, y el técnico pasa la tarde persiguiendo un bug que en realidad es de origen de datos. El solicitante de un ticket es ##ticket.authors## (lista lista) o, si quieres nombre y correo de cada uno por separado, el bloque FOREACH de abajo.
FOREACH: la parte que casi nadie conoce
Un ticket tiene N seguimientos, N tareas, N solicitantes. No hay una etiqueta mágica que vuelque todo formateado: GLPI expone las colecciones mediante un bloque de repetición. Abres el bucle, escribes el interior una vez con las etiquetas del elemento y lo cierras - y hasta puedes limitar cuántos elementos con FIRST o LAST:
Hola ##ticket.authors##,
Su ticket ##ticket.id## - ##ticket.title##
cambio a: ##ticket.status##
Tecnico(s): ##ticket.assigntousers##
Ultimo seguimiento:
##FOREACH LAST 1 followups##
[##followup.date##] ##followup.author##:
##followup.description##
##ENDFOREACHfollowups##
Acceda: ##ticket.url##
El LAST 1 (también acepta FIRST y números mayores) es lo que evita el correo kilométrico repitiendo todo el historial en cada nuevo seguimiento - una petición recurrente de cliente que la mayoría "resuelve" recortando contenido a la fuerza, cuando bastaba el modificador. Las colecciones que aceptan FOREACH incluyen followups, tasks, authors, actors, costs y las enlazadas (linkedtickets, linkedchanges, linkedproblems).
Notificación multilingüe gratis: las etiquetas ##lang.*##
Detalle que solo aparece cuando abres la lista completa de etiquetas: cada etiqueta de valor tiene una compañera de rótulo. Para ##ticket.status## (el valor) existe ##lang.ticket.status##, que imprime el rótulo "Estado" traducido al idioma del destinatario. Montando la plantilla con pares rótulo + valor, el mismo mensaje sale en portugués para un usuario y en español para otro, sin duplicar la plantilla:
##lang.ticket.title##: ##ticket.title##
##lang.ticket.status##: ##ticket.status##
##lang.ticket.priority##: ##ticket.priority##
En un cliente con entidades en más de un país, esto reduce el mantenimiento de "una plantilla por idioma" a una sola. El valor no lo traduces - el dato es el dato; lo que cambia es solo el rótulo, y ##lang.*## lo resuelve solo.
Diagnóstico: la variable está bien, pero el correo no sale
Cuando la plantilla es impecable y aun así el correo desaparece, el problema no está en la etiqueta - está en la cola. GLPI graba cada mensaje en glpi_queuednotifications y la tarea automática queuednotification es quien envía de verdad. Si la tarea no corre (cron parado) o el SMTP rechaza, el mensaje se acumula con sent_time nulo. Es lo primero que ejecutamos en un ticket de "la notificación no llega":
-- Notificaciones en cola que ya deberian haber salido:
-- sent_time NULL = aun no enviada; send_time en el pasado = atrasada.
SELECT id, name AS asunto, recipient, send_time, sent_try
FROM glpi_queuednotifications
WHERE sent_time IS NULL
AND send_time <= NOW()
ORDER BY send_time ASC
LIMIT 30;
Filas acumulándose con sent_try subiendo significan SMTP rechazando; cola creciendo con sent_try en cero significa cron parado. En ambos casos la plantilla está bien - y acabas de ahorrarte la tarde que ibas a gastar reescribiendo etiquetas en vano.
Dónde funciona cada variable (matriz de decisión)
La confusión que heredamos de casi todo parque nuevo es creer que "plantilla de ticket" y "plantilla de notificación" son lo mismo. No lo son - y solo una hace sustitución de ##tag##:
| Dónde | ¿Sustituye ##tag##? | Para qué sirve |
|---|---|---|
| Plantilla de notificación (cuerpo y asunto) | Sí - etiquetas, FOREACH y ##lang.*## | Cuerpo de correo dinámico |
| Plantilla de ticket (TicketTemplate) | No | Predefinir, ocultar u obligar campos en la apertura |
| Plantilla de tarea / seguimiento | No | Texto base reutilizable, sin sustitución dinámica |
| Asunto de la notificación | Sí | Las mismas etiquetas del cuerpo, en una sola línea |
Consejo final que vale por todo lo demás: al editar una plantilla de notificación, GLPI muestra la pestaña de etiquetas disponibles para ese elemento específico. Es la fuente de la verdad - contextual y siempre alineada a la versión instalada. Antes de copiar una etiqueta de un blog (incluido este), confirma que aparece allí.
¿Necesitas notificaciones que informen de verdad - multilingües, con el solicitante correcto y sin correos atascados en la cola? Conoce el servicio de soporte GLPI de NexTool.
Revisado por el equipo de NexTool Solutions.