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.