Troubleshooting · Ubuntu
Ubuntu cron not sending email? Why, and what to do instead
Why cron output emails never arrive on Ubuntu/Debian VPS — no MTA, MAILTO, spam filtering — and a more reliable alternative.
By default, cron emails a job’s output to the local user — but on a stock Ubuntu/Debian VPS that mail usually goes nowhere. Here’s why, and what to do.
1. There’s no mail transfer agent installed
A minimal server has no MTA, so cron has nothing to hand mail to. Check:
which sendmail
systemctl status postfix
If neither exists, cron output is simply discarded. You can install a lightweight MTA:
sudo apt update && sudo apt install -y postfix mailutils
# choose "Internet Site" (or "Satellite" to relay via a smarthost)
2. Set MAILTO
Cron sends output to the crontab owner unless told otherwise. Set a real address at the top of the crontab:
MAILTO="ops@example.com"
0 2 * * * /opt/app/run.sh
No output means no email — cron only mails when a job writes to stdout/stderr.
3. Your mail is being dropped as spam
Even with an MTA, mail sent directly from a random VPS IP is very likely to be rejected or junked: no SPF, no DKIM, no reverse DNS, and the IP may be on a block list. Relaying through a real provider (a smarthost / SMTP relay) fixes deliverability but is real work to set up and maintain.
4. Test the path end to end
echo "test body" | mail -s "cron mail test" ops@example.com
tail -f /var/log/mail.log
If the log shows the message deferred or bounced, it’s a deliverability problem, not a cron problem.
A more reliable approach than cron email
Cron email is fragile by design: it only fires on output, depends on an MTA you have to run, and lands in spam. Worst of all, if the job stops running entirely, there’s no output — so there’s no email, and you hear nothing.
Flip it around: instead of emailing you when a job runs, get alerted when one doesn’t. Ping a heartbeat on success and let a service watch for the silence:
0 2 * * * /opt/app/run.sh && curl -fsS https://ping.steadycron.com/<your-ping-token>
If the ping is missing or late, SteadyCron emails (or Slacks, or pages) you — no local MTA, no SPF/DKIM headaches, and it catches the case cron email never could: the job that stopped firing.