Solución de problemas · Ubuntu

¿Cron no envía correos en Ubuntu? Por qué ocurre y qué hacer en su lugar

Por qué los correos de salida de cron nunca llegan en un VPS Ubuntu/Debian — sin MTA, MAILTO, filtros de spam — y una alternativa más fiable.

Por defecto, cron envía la salida de un job por correo al usuario local — pero en un VPS Ubuntu/Debian estándar ese correo normalmente no llega a ningún lado. Aquí está el motivo y qué hacer al respecto.

1. No hay ningún agente de transferencia de correo instalado

Un servidor mínimo no tiene MTA, así que cron no tiene a quién entregar el correo. Compruébalo:

which sendmail
systemctl status postfix

Si ninguno existe, la salida de cron simplemente se descarta. Puedes instalar un MTA ligero:

sudo apt update && sudo apt install -y postfix mailutils
# elige "Internet Site" (o "Satellite" para reenviar a través de un smarthost)

2. Define MAILTO

Cron envía la salida al propietario del crontab salvo que se le indique lo contrario. Define una dirección real al inicio del crontab:

MAILTO="ops@example.com"
0 2 * * * /opt/app/run.sh

Sin salida no hay correo — cron solo envía correo cuando un job escribe en stdout/stderr.

3. Tu correo se está clasificando como spam

Incluso con un MTA, el correo enviado directamente desde la IP de un VPS cualquiera es muy probable que sea rechazado o vaya a la carpeta de spam: sin SPF, sin DKIM, sin DNS inverso, y la IP puede estar en una lista negra. Reenviar a través de un proveedor real (un smarthost / relay SMTP) mejora la entregabilidad, pero requiere configuración y mantenimiento.

4. Prueba el recorrido completo

echo "test body" | mail -s "cron mail test" ops@example.com
tail -f /var/log/mail.log

Si el log muestra el mensaje diferido o rebotado, el problema es de entregabilidad, no de cron.

Un enfoque más fiable que el correo de cron

El correo de cron es frágil por diseño: solo se dispara cuando hay salida, depende de un MTA que tienes que gestionar, y acaba en spam. Lo peor de todo es que si el job deja de ejecutarse por completo, no hay salida — por lo tanto no hay correo, y no te enteras de nada.

Dale la vuelta: en lugar de que te envíen un correo cuando un job se ejecuta, recibe una alerta cuando no se ejecute. Haz ping a un heartbeat al terminar con éxito y deja que un servicio vigile el silencio:

0 2 * * * /opt/app/run.sh && curl -fsS https://ping.steadycron.com/<tu-ping-token>

Si el ping no llega o llega tarde, SteadyCron te avisa por correo (o por Slack, o por pager) — sin MTA local, sin complicaciones de SPF/DKIM, y detecta el caso que el correo de cron nunca podría detectar: el job que dejó de dispararse.