--- title: "Alertas por correo con mailx y Postfix en Ubuntu 24.04" description: "Configura Postfix como relay SMTP autenticado y mailx en Ubuntu 24.04 para recibir por correo alertas de disco lleno y de servicios systemd que fallan." category: "Monitoring Logging" language: es source: https://cubepath.com/es/docs/monitoring-logging/configuracion-de-alertas-por-correo-con-mailx updated: 2026-09-25 --- # Alertas por correo con mailx y Postfix en Ubuntu 24.04 `mailx` es un cliente de correo de línea de comandos que permite a scripts, tareas cron y unidades de systemd enviar mensajes sin intervención humana. Por sí solo no entrega nada: necesita un agente de transporte (MTA) que lleve el correo hasta el destinatario. En este tutorial configurarás Postfix en Ubuntu 24.04 como relay que envía todo a través de un proveedor SMTP autenticado, instalarás `mailx` y crearás dos alertas reales: una cuando un disco supera un umbral de uso y otra cuando falla un servicio de systemd. ## Requisitos previos Para seguir esta guía necesitas: - Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath. - Un usuario no root con privilegios `sudo`. - Una cuenta en un proveedor SMTP con credenciales para enviar correo por el puerto 587 (tu propio servidor de correo, Brevo, Amazon SES, SendGrid, Mailgun o Gmail con contraseña de aplicación). - Una dirección de remitente que tu proveedor permita usar, por ejemplo `alertas@your_domain`. - Una dirección donde quieras recibir las alertas. > Nota: Muchos proveedores cloud bloquean el tráfico saliente al puerto 25 para evitar spam. Por eso esta guía no entrega el correo directamente, sino que lo envía a un servidor SMTP autenticado en el puerto 587, que es la forma fiable de que tus alertas no acaben en la carpeta de spam. ## Paso 1: Instalar Postfix, mailx y el soporte SASL Instala los tres paquetes necesarios: `postfix` (el MTA), `bsd-mailx` (el comando `mail`/`mailx`) y `libsasl2-modules`, que Postfix necesita para autenticarse contra el servidor SMTP: ```bash sudo apt update sudo apt install postfix bsd-mailx libsasl2-modules ``` Durante la instalación aparece el asistente de Postfix: - **General mail configuration type**: elige `Satellite system`. - **System mail name**: el nombre completo del servidor, por ejemplo `server01.your_domain`. - **SMTP relay host**: el servidor de tu proveedor con corchetes y puerto, por ejemplo `[smtp.your_provider.com]:587`. - **Root and postmaster mail recipient**: puedes dejarlo vacío. Comprueba que `mail` apunta a `bsd-mailx`: ```bash readlink -f "$(command -v mail)" ``` ```output /usr/bin/bsd-mailx ``` ## Paso 2: Configurar Postfix como relay autenticado Postfix necesita las credenciales del proveedor en un mapa aparte. Crea el archivo: ```bash sudo nano /etc/postfix/sasl_passwd ``` Añade una línea con el mismo host y puerto que usaste como relay, seguido de usuario y contraseña. Sustituye los valores de ejemplo por los tuyos: ```text [smtp.your_provider.com]:587 your_smtp_user:your_smtp_password ``` Protege el archivo, ya que contiene una contraseña en claro, y genera la base de datos que Postfix lee: ```bash sudo chmod 600 /etc/postfix/sasl_passwd sudo postmap /etc/postfix/sasl_passwd ``` Esto crea `/etc/postfix/sasl_passwd.db`. Ahora aplica la configuración con `postconf -e`, que edita `/etc/postfix/main.cf` de forma segura: ```bash sudo postconf -e 'relayhost = [smtp.your_provider.com]:587' sudo postconf -e 'smtp_sasl_auth_enable = yes' sudo postconf -e 'smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd' sudo postconf -e 'smtp_sasl_security_options = noanonymous' sudo postconf -e 'smtp_tls_security_level = encrypt' sudo postconf -e 'inet_interfaces = loopback-only' ``` Qué hace cada ajuste: - `smtp_tls_security_level = encrypt` obliga a usar STARTTLS, de modo que la contraseña nunca viaja sin cifrar. - `inet_interfaces = loopback-only` hace que Postfix solo acepte correo desde el propio servidor. No necesitas exponer el puerto 25 a Internet. ### Reescribir el remitente Por defecto los mensajes salen como `root@server01.your_domain`, una dirección que tu proveedor rechazará o marcará como spam. Con un mapa genérico, Postfix reescribe cualquier remitente local por tu dirección verificada al enviarlo hacia fuera: ```bash sudo nano /etc/postfix/generic ``` ```text @server01.your_domain alertas@your_domain ``` Usa el mismo nombre que pusiste en **System mail name**. Genera el mapa, actívalo y recarga Postfix: ```bash sudo postmap /etc/postfix/generic sudo postconf -e 'smtp_generic_maps = hash:/etc/postfix/generic' sudo systemctl reload postfix ``` Revisa que no haya errores de configuración: ```bash sudo postfix check && postconf relayhost smtp_generic_maps ``` ```output relayhost = [smtp.your_provider.com]:587 smtp_generic_maps = hash:/etc/postfix/generic ``` > Nota: Si usas Gmail, el relay es `[smtp.gmail.com]:587` y la contraseña debe ser una contraseña de aplicación (requiere tener activada la verificación en dos pasos). Gmail reescribe el remitente a tu cuenta de Google en cualquier caso. ## Paso 3: Enviar un correo de prueba Envía un mensaje sencillo. El cuerpo se lee de la entrada estándar y el asunto va en `-s`: ```bash echo "Correo de prueba enviado desde $(hostname -f)" | mail -s "Prueba de mailx" tu@correo.com ``` Mira el registro de Postfix para confirmar la entrega: ```bash sudo tail -n 20 /var/log/mail.log ``` Una entrega correcta contiene `status=sent` y la respuesta `250` del servidor remoto: ```output 2026-09-25T10:12:04.381220+00:00 server01 postfix/smtp[4312]: 9C1E2A0431: to=, relay=smtp.your_provider.com[192.0.2.25]:587, delay=1.4, delays=0.02/0.01/0.62/0.75, dsn=2.0.0, status=sent (250 2.0.0 OK) ``` Algunas opciones de `bsd-mailx` que usarás en los scripts: ```bash # Varios destinatarios y copia mail -s "Asunto" -c equipo@your_domain uno@your_domain dos@your_domain < informe.txt # Añadir una cabecera, por ejemplo Reply-To echo "Cuerpo" | mail -s "Asunto" -a "Reply-To: soporte@your_domain" tu@correo.com ``` > Nota: `bsd-mailx` no adjunta archivos (su opción `-a` añade cabeceras). Para alertas basta con incluir el texto relevante en el cuerpo del mensaje, como harás en los pasos siguientes. ## Paso 4: Crear una alerta de espacio en disco Esta alerta revisa todos los sistemas de archivos reales y envía un correo si alguno supera el umbral. Crea el script: ```bash sudo nano /usr/local/bin/check-disk-alert ``` ```bash #!/usr/bin/env bash set -euo pipefail THRESHOLD="${THRESHOLD:-85}" RECIPIENT="${RECIPIENT:-tu@correo.com}" HOST="$(hostname -f)" full="$(df --output=pcent,target -x tmpfs -x devtmpfs -x squashfs -x overlay \ | awk -v t="$THRESHOLD" 'NR > 1 { p = $1; sub(/%/, "", p); if (p + 0 >= t) print $2 " al " p "%" }')" if [[ -n "$full" ]]; then { printf 'Sistemas de archivos por encima del %s%% en %s:\n\n%s\n\n' "$THRESHOLD" "$HOST" "$full" df -h -x tmpfs -x devtmpfs -x squashfs -x overlay } | mail -s "[ALERTA] Disco casi lleno en $HOST" "$RECIPIENT" fi ``` Cambia `tu@correo.com` por tu dirección. Haz el script ejecutable y pruébalo forzando un umbral del 1 % para que salte seguro: ```bash sudo chmod 755 /usr/local/bin/check-disk-alert sudo THRESHOLD=1 /usr/local/bin/check-disk-alert ``` Deberías recibir un correo con un cuerpo parecido a este: ```text Sistemas de archivos por encima del 1% en server01.your_domain: / al 23% /boot al 12% ``` Prográmalo con cron para que se ejecute cada 30 minutos: ```bash sudo nano /etc/cron.d/check-disk-alert ``` ```text MAILTO=tu@correo.com */30 * * * * root /usr/local/bin/check-disk-alert ``` La variable `MAILTO` hace que cron te envíe también cualquier salida o error del script, así sabrás si deja de funcionar. Mientras el disco siga por encima del umbral recibirás un aviso cada 30 minutos; si te resulta excesivo, cambia la frecuencia a `0 * * * *` (cada hora). ## Paso 5: Recibir un correo cuando falla un servicio systemd permite lanzar una unidad cuando otra falla mediante la directiva `OnFailure=`. Crearás una unidad plantilla que envía el estado del servicio que ha fallado. Primero, el script que compone el mensaje: ```bash sudo nano /usr/local/bin/systemd-failure-mail ``` ```bash #!/usr/bin/env bash set -euo pipefail UNIT="$1" RECIPIENT="tu@correo.com" HOST="$(hostname -f)" { systemctl status --full --no-pager --lines=30 "$UNIT" || true } | mail -s "[ALERTA] $UNIT ha fallado en $HOST" "$RECIPIENT" ``` `systemctl status` devuelve un código distinto de cero para una unidad fallida; el `|| true` evita que eso haga fallar el script. Hazlo ejecutable: ```bash sudo chmod 755 /usr/local/bin/systemd-failure-mail ``` Ahora la unidad plantilla. La `@` del nombre indica que recibe un parámetro (`%i`), que será el nombre del servicio que falló: ```bash sudo nano /etc/systemd/system/failure-mail@.service ``` ```ini [Unit] Description=Aviso por correo del fallo de %i [Service] Type=oneshot ExecStart=/usr/local/bin/systemd-failure-mail %i ``` ### Probar con un servicio que falla Crea un servicio de prueba que siempre falla y que usa la plantilla: ```bash sudo nano /etc/systemd/system/test-fallo.service ``` ```ini [Unit] Description=Servicio de prueba que falla OnFailure=failure-mail@%n.service [Service] Type=oneshot ExecStart=/bin/false ``` `%n` se sustituye por el nombre completo de la unidad (`test-fallo.service`). Recarga systemd y arráncalo: ```bash sudo systemctl daemon-reload sudo systemctl start test-fallo.service ``` El comando termina con un error, que es lo esperado. Comprueba que la plantilla se ha ejecutado: ```bash journalctl -u 'failure-mail@*' -n 5 --no-pager ``` ```output Sep 25 10:31:07 server01 systemd[1]: Starting failure-mail@test-fallo.service.service - Aviso por correo del fallo de test-fallo.service... Sep 25 10:31:07 server01 systemd[1]: failure-mail@test-fallo.service.service: Deactivated successfully. Sep 25 10:31:07 server01 systemd[1]: Finished failure-mail@test-fallo.service.service - Aviso por correo del fallo de test-fallo.service. ``` Recibirás un correo con la salida de `systemctl status test-fallo.service`. Elimina el servicio de prueba: ```bash sudo rm /etc/systemd/system/test-fallo.service sudo systemctl daemon-reload sudo systemctl reset-failed ``` ### Aplicarlo a un servicio real Para vigilar un servicio existente, como `nginx`, añade la directiva con un archivo drop-in en lugar de editar la unidad del paquete: ```bash sudo systemctl edit nginx.service ``` En el editor, escribe entre los comentarios indicados: ```ini [Unit] OnFailure=failure-mail@%n.service ``` Guarda y comprueba que se ha aplicado: ```bash systemctl show nginx.service -p OnFailure ``` ```output OnFailure=failure-mail@nginx.service.service ``` Si el servicio tiene `Restart=on-failure`, systemd solo lo considera fallido cuando agota los reintentos, así que no recibirás un correo por cada reinicio automático. ## Solución de problemas **`SASL authentication failed` en `/var/log/mail.log`.** Usuario o contraseña incorrectos, o falta `libsasl2-modules`. Corrige `/etc/postfix/sasl_passwd`, vuelve a ejecutar `sudo postmap /etc/postfix/sasl_passwd` y recarga Postfix. El host del archivo debe coincidir exactamente con `relayhost`, corchetes incluidos. **`Connection timed out` hacia el relay.** El puerto 587 saliente está bloqueado. Compruébalo con `nc -vz smtp.your_provider.com 587`. Si falla, revisa el firewall de salida del servidor o usa el puerto alternativo que ofrezca tu proveedor. **`Sender address rejected` o `550` relacionado con el remitente.** El proveedor no acepta la dirección de origen. Revisa `/etc/postfix/generic`, que el dominio coincida con **System mail name** (`cat /etc/mailname`) y que la dirección esté verificada en el proveedor. **Mensajes retenidos en la cola.** Lista la cola con `mailq`. Tras corregir el problema, fuerza el reintento con `sudo postqueue -f`. Para descartar todo lo pendiente usa `sudo postsuper -d ALL`. **El correo llega a spam.** Configura SPF, DKIM y DMARC del dominio remitente según las instrucciones de tu proveedor SMTP. ## Conclusión Tu servidor ya envía correo a través de un relay autenticado y cifrado, y te avisa cuando un disco se llena o un servicio de systemd falla. El mismo patrón sirve para cualquier otra comprobación: un script que solo escribe en `mail` cuando hay algo que contar, programado con cron o con un temporizador de systemd. Como siguientes pasos puedes aplicar `OnFailure=` a tus servicios críticos (base de datos, servidor web, copias de seguridad), añadir un informe diario con la salida de `df -h` y `systemctl --failed`, o pasar a un sistema de monitorización como Prometheus con Alertmanager cuando gestiones varios servidores.