All posts

Cron Mail Explained: Why It Breaks and What to Use Instead

August 21, 2026

What "Cron Mail" Actually Means

If you searched "cron mail," you likely landed here for one of two reasons: cron was supposed to email job output and didn't, or you're trying to understand why cron needs mail configuration at all. Cron mail isn't a mail client or notification service — it's cron's built-in behavior of capturing a job's output and attempting to deliver it as an email using whatever mail transfer mechanism exists on the system. No dashboard, no retry logic, no delivery guarantee.

This is distinct from the MAILTO variable, which just tells cron where to send that mail. For syntax details — scoping, blank behavior, quirks — see our MAILTO deep-dive. This article covers the plumbing behind cron email notifications: what has to exist on the server for that mail to actually leave the box.

How Cron Actually Delivers Mail

Cron's mail behavior is mechanically simple, which is exactly why it's easy to misconfigure. When a cron job produces output on STDOUT or STDERR and isn't redirected elsewhere, cron pipes that output to /usr/sbin/sendmail, the same interface used by traditional Unix mail systems. Cron knows nothing about SMTP, TLS, authentication, or inboxes — it just calls sendmail and considers its job done.

That's how cron sends mail: it delegates entirely. sendmail is usually a symlink or wrapper around whatever Mail Transfer Agent (MTA) is installed — Postfix, Exim, or actual Sendmail. The MTA queues the message, resolves the recipient's mail server, and speaks SMTP to hand it off. If no MTA is installed — the default on most minimal cloud images, Docker containers, and stripped-down VPS setups — the call to /usr/sbin/sendmail fails silently or the binary doesn't exist. Cron raises no alert. The mail evaporates, and the job's actual success or failure becomes unknowable from the outside.

This single missing dependency explains most "cron sendmail isn't working" complaints. MAILTO=you@example.com is a destination address, not a delivery mechanism.

Setting Up Cron Mail on a Server

Getting cron mail working means picking one of two delivery paths: a local MTA, or relaying through an external SMTP provider.

Option 1: Install a Local MTA (Postfix or sendmail)

For servers that just need root/cron mail to land in a local mailbox (readable via mail or forwarded through /etc/aliases), a minimal Postfix install is fastest:

sudo apt install postfix

During setup, choose "Local only" if the server doesn't need to send mail beyond itself. This satisfies cron's call to /usr/sbin/sendmail and queues messages locally. To forward mail to a real external address, add an entry to /etc/aliases mapping root to your address, then run newaliases. This works for internal alerting or single-admin servers, but won't reliably deliver to Gmail, Outlook, or other major providers, since a fresh, unauthenticated local Postfix instance has no sending reputation and gets filtered or rejected.

Option 2: Relay Through an External SMTP Provider (msmtp/ssmtp)

To get cron mail into an actual external inbox, the common pattern is installing a lightweight relay client — msmtp or ssmtp — configured to authenticate against an SMTP provider like Gmail, then pointing /usr/sbin/sendmail at it via a symlink. This is the classic msmtp cron setup: install msmtp, write credentials and SMTP host details into ~/.msmtprc, then configure it as the system's sendmail alternative.

Two things break this constantly. First, ssmtp has been unmaintained for years and shouldn't be used in new setups — msmtp is the maintained equivalent. Second, Gmail and Outlook have moved away from simple username/password authentication toward app passwords and OAuth2, and periodically restrict older auth methods. A cron mail SMTP relay that worked for years can stop overnight when a provider retires basic auth or requires a token refresh a static config file can't handle.

Why Cron Mail Stops Working (and How to Check)

When cron isn't sending mail, work through these in order:

  • No MTA installed — check whether /usr/sbin/sendmail even exists. On many minimal images, it doesn't.
  • Port 25 blocked — most cloud providers (AWS, DigitalOcean, GCP, Azure) block outbound port 25 by default to curb spam, silently killing direct MTA delivery. This is why relay setups exist.
  • Empty or wrong MAILTO — an unset MAILTO still mails root locally by default; a typo'd address just vanishes.
  • Output redirected to /dev/null — a script ending in > /dev/null 2>&1 gives cron nothing to mail, by design.
  • Expired app passwords or OAuth tokens — Gmail/Outlook relay configs using static credentials break the moment the provider rotates auth requirements.
  • Spam filtering — mail from an unfamiliar server IP with no SPF/DKIM often lands in spam or gets dropped, even when delivery technically "succeeded."

To fix cron mail delivery, test the pipeline directly, independent of your cron job: run echo "test" | mail -s "test subject" you@example.com and check /var/log/mail.log or journalctl -u postfix for delivery errors. If that fails, the problem is your MTA/relay config, not your crontab.

Why Email Was Never a Good Monitoring Channel

Even a perfectly working cron mail setup has a structural flaw: it can't tell you whether your job failed or whether your mail pipeline failed. Silence means one of two very different things, and you can't distinguish them from the inbox side. There's no history to review trends, no escalation if the first alert is missed, and no way to see whether a job has been quietly failing for a week versus running fine — it's just a message sitting in a folder next to newsletters and calendar invites, easy to miss and easy to distrust.

Cron email notifications also depend on your own MTA or relay — another single point of failure bolted onto the thing you're trying to monitor. If your server loses outbound connectivity, cron mail and the job it was meant to report on fail together.

That's the case for treating job monitoring as a separate, owned system rather than a byproduct of mail delivery. Instead of debugging Postfix queues or refreshing an OAuth token every few months, point each cron job at a Cronevra HTTP ping URL. Cronevra tracks whether the ping arrived on schedule, keeps execution history, and handles failure alerts through channels you actually check — no MTA, no SMTP relay, no silent gaps. If you're still setting up your crontab entries, see our crontab scheduling walkthrough first, and compare monitoring options — including how Cronitor stacks up — before picking a tool. When you're ready, check Cronevra's pricing and stop relying on an inbox to tell you whether your jobs are alive.

Frequently Asked Questions

Why isn't my cron job sending mail even though MAILTO is set correctly?

MAILTO only sets the destination address — it doesn't create a delivery mechanism. If no MTA like Postfix is installed, or /usr/sbin/sendmail isn't configured, cron has no way to transmit the message, so it fails silently regardless of how correctly MAILTO is set.

Do I need to install Postfix just to get cron mail working?

You need some MTA or relay client, and Postfix is the most common choice, but not the only one. A local-only Postfix install works for root/internal mail, while msmtp configured against an external SMTP provider is often better if you need delivery to a real inbox like Gmail.

Can I use Gmail to receive cron job emails?

Yes, by configuring msmtp (not the unmaintained ssmtp) as a relay authenticated with a Gmail app password or OAuth2 credentials, then pointing your server's sendmail alias at msmtp. Gmail periodically tightens auth requirements, which can break long-running relay configs without warning.

What's the difference between sendmail, Postfix, and msmtp for cron mail?

Sendmail is both the historical MTA and the generic command-line interface cron calls; Postfix is a modern, widely-used MTA that typically provides that sendmail interface today. Msmtp is a lightweight relay client, not a full MTA, designed specifically to forward mail to an external SMTP provider like Gmail.

Is cron mail still a reliable way to monitor scheduled jobs in 2026?

No — even when correctly configured, cron mail can't distinguish between "job failed" and "mail delivery failed," offers no history or escalation, and depends on infrastructure (your MTA or relay) that can break independently of your jobs. Dedicated monitoring tools that track execution via HTTP pings are structurally more reliable.

How do I test if cron mail is working on my server?

Run a manual test independent of cron, such as echo "test" | mail -s "test" you@example.com, then check /var/log/mail.log or your MTA's logs for delivery errors. If the manual test fails, the issue is in your MTA or relay configuration, not your crontab or job script.