Crontab Email (MAILTO): Why It Fails & What to Use Instead
September 20, 2026


Crontab email is one of the oldest "monitoring" mechanisms in Unix, and it's also one of the most quietly broken. Set MAILTO in a crontab, expect a notification when something goes wrong, and instead get nothing — not because the job succeeded, but because the mail never had anywhere to go. Understanding why requires treating cron email as a chain of dependencies, any one of which can fail without telling you.
What MAILTO Actually Does in a Crontab
MAILTO is an environment variable set at the top of a crontab file, before your job entries. When cron runs a command, it captures stdout and stderr. If there's any output, cron tries to email it to the address in MAILTO. No output, no email — this isn't a purpose-built alerting feature, it's a side effect of cron piping console output somewhere instead of letting it vanish.
Basic syntax:
MAILTO="you@example.com"
0 * * * * /usr/local/bin/backup.sh
Per the crontab(5) man page, MAILTO must be set as its own line, and it applies to every job below it until reassigned. You can also set MAILFROM on systems that support it, to control the sender address rather than defaulting to root or the executing user. A cron job email notification is really just "whatever text this command printed," forwarded by whatever mail system happens to be sitting on the machine. If your script is quiet on success and verbose on failure, that's useful. If it prints anything on every run, you'll get flooded regardless of outcome.
How Cron Email Actually Gets Delivered (and Where It Breaks)
The path from MAILTO to your inbox has four links, each a separate point of failure:
- Cron daemon captures the job's output and hands it off internally to be mailed.
- Local MTA (Sendmail, Postfix, or Exim) must be installed and running to accept that mail.
- Relay — the MTA has to be configured to actually reach an outbound mail server, whether that's your ISP's relay, a smarthost, or a cloud provider's SMTP service.
- Inbox — assuming everything upstream worked, the message still has to survive spam filtering and DNS/SPF checks to land somewhere you'll see it.
Most failures happen at step two. Minimal server images, containers, and fresh cloud VMs frequently ship with no MTA at all, since nothing else on the box needs one. Trigger cron mail on one of these and you'll find this line in syslog or journalctl -u cron:
(CRON) info (No MTA installed, discarding output)
That message is cron telling you, quietly and only in a log file you probably aren't watching, that your MAILTO was never functional. It's a well-documented failure mode — see this breakdown of No MTA installed, discarding output — and it's the single most common reason crontab MAILTO stops working after a server migration or fresh OS install: the old box had Postfix configured from years of accumulated setup, the new one doesn't, and nobody notices until a job fails silently in production.
Even with an MTA installed, step three trips people up just as often. A local Postfix or Sendmail install can accept the mail and then fail to relay it — no authenticated relay configured, an ISP blocking outbound port 25, or a self-signed setup rejected by the receiving server. From cron's perspective the job ran fine and the mail was "sent." From your perspective, nothing ever arrives.
Fixing Common MAILTO Problems
If crontab email isn't sending, work the chain in order rather than guessing:
- Check for an installed MTA. Run
which sendmailorsystemctl status postfix(orexim). If nothing's installed, that's your answer — install and configure one, or route around the problem entirely (more below). - Test mail manually, outside of cron. Run
echo "test" | mail -s "test subject" you@example.comfrom a shell. If this fails, cron isn't the problem — your MTA or relay is. - Lightweight relay-only tools. If you don't want a full Postfix install,
ssmtpormsmtpcan forward mail through an external SMTP account (Gmail, SendGrid, etc.) with minimal configuration — often the fastest way to send email from cron without sendmail on a small VM. - Kill the noise. If a job emails on every successful run, either set
MAILTO=""to disable cron email for jobs below that line, or restructure the script so it's silent on success and only prints on error. Redirecting stdout to/dev/nullwhile leaving stderr alone (command >/dev/null) is the simplest way to get cron to send email on failure only. - Fix root mail aliasing. Many systems mail root by default and never deliver anywhere, because root's mail is aliased to nowhere useful. Edit
/etc/aliasesto point root at a real address, then runnewaliases— a detail covered well in nixCraft's MAILTO reference.
These steps fix "email not sending." They don't fix the bigger problem underneath.
Why Email Alone Isn't Reliable Monitoring
Even a perfectly configured MAILTO only fires when cron actually executes the job and that job produces output. It says nothing about a cron job silent failure where the daemon itself never triggered the run — because the crontab entry got dropped in a deploy, the server clock drifted, or the box was down at the scheduled minute. No execution means no output, which means no email, which means everything looks fine from your side until someone notices stale data days later.
The same blind spot applies to the mail chain itself. If the MTA hangs, if a relay silently bounces the message, or if a spam filter eats it, you get no signal that the signal failed. Email tells you about failures inside the job. It can't tell you the job never ran at all — exactly the scenario a dead man's switch approach is designed to catch: something has to notice the absence of a check-in, not just the presence of an error.
A More Reliable Alternative to MAILTO
Reliable cron job monitoring means decoupling failure alerts from local mail infrastructure entirely. Instead of hoping an MTA is installed, configured, and relaying correctly, your job makes a simple HTTP request to confirm it ran — and if that check-in doesn't arrive on schedule, or arrives with a failure signal, you get alerted through a channel that has nothing to do with sendmail, Postfix, or root aliases. That's cron failure alerts without email, catching both output failures and silent non-runs, which MAILTO structurally cannot do.
For teams building this out properly, this framework for avoiding silent cron failures is a useful next step beyond ad-hoc email fixes.
If you're tired of debugging MTA configs just to find out whether a backup script ran, Cronevra gives you HTTP-based check-ins, missed-run detection, and failure alerts that work regardless of what mail software is or isn't installed on your servers. Check the pricing page to see how quickly you can replace a fragile MAILTO setup with monitoring that actually tells you when a job stops running.
Frequently Asked Questions
Why isn't my crontab MAILTO sending any emails?
The most common cause is a missing MTA — no Sendmail, Postfix, or Exim installed to accept the mail cron hands off. Check syslog or journalctl -u cron for "No MTA installed, discarding output," and test manually with echo "test" | mail -s test you@example.com to confirm whether the failure is at the daemon, MTA, or relay level.
How do I stop cron from emailing me every time a job runs?
Set MAILTO="" above the job entries you want silenced, disabling cron email for everything below that line. Alternatively, redirect stdout to /dev/null in the job command so only stderr output — typically actual errors — triggers a mail.
Can I send cron email without installing Postfix or sendmail?
Yes, lightweight tools like ssmtp or msmtp let a machine relay mail through an external SMTP provider without running a full mail server. They're a faster fix for minimal containers or cloud VMs than configuring Postfix from scratch.
Does MAILTO work the same way on every Linux distribution?
The core behavior is consistent, but default MTA presence and root mail aliasing vary widely between distributions and images. A crontab that emailed reliably on one server can go silent after a migration simply because the new OS image doesn't ship with an MTA preinstalled.
How do I get an alert only when a cron job fails, not on every run?
Structure the script to stay silent on success and print only on error, then let MAILTO capture that output as-is. This produces a functional "cron job email on failure" pattern without extra tooling, though it still depends on the underlying mail chain working.
Is MAILTO enough to monitor cron jobs in production?
No — MAILTO only fires when cron executes the job and that job produces output, so it can't detect a job that silently never ran or a mail message that bounced unnoticed. Production monitoring needs an independent check-in mechanism, like an HTTP-based dead man's switch, that flags missed runs regardless of local mail infrastructure.