raspberry-pi beginner 20 min

Raspberry Pi: send email alerts from shell scripts with msmtp

Configure msmtp on a Raspberry Pi so any shell script or cron job can send email alerts through your own SMTP relay. The pattern that survives.

Code available for: Python
Published Sep 22, 2026

Every Pi project eventually needs to tell you something. The disk is full. The backup did not run. The garage is still open at midnight. My answer to all of these is the same: an email from the command line. Not a push service, not a Telegram bot, not a SaaS dashboard. Email. It works on every device I own, it archives itself, and the script that sends it is three lines long.

The tool for this on a Pi is msmtp. It is not a mail server. It is a tiny client that hands your message to a real SMTP server and walks away. That distinction is the whole point: a Pi does not need to receive mail, retry queues, or store anything. It needs to shout once and get back to work.

What you need

Needed

  • A Raspberry Pi running Raspberry Pi OS (any model; Lite is fine)
  • An SMTP account that sends from your own infrastructure. A mail
  • 20 minutes

Nice to have

  • An anti-static wristband (cheap insurance around the Pi’s GPIO header)
  • A small screwdriver kit for the case and camera ribbon clips

Install

One package. That is the entire install:

sudo apt update
sudo apt install msmtp msmtp-mta

msmtp-mta adds the sendmail shim, so anything on the Pi that expects /usr/sbin/sendmail (e.g. cron’s own mail, logwatch, any script using mail -s) just works without being reconfigured.

Configure

Create the config as root so system services can read it:

sudo nano /etc/msmtprc

Paste this in and edit the three lines that name your relay:

# /etc/msmtprc
defaults
auth           on
tls            on
tls_trust_file /etc/ssl/certs/ca-certificates.crt
logfile        /var/log/msmtp.log

account        default
host           mail.yourdomain.com
port           587
from           pi@yourdomain.com
user           pi@yourdomain.com
password       your-mail-password

Then lock the permissions down, because msmtp refuses to run if the config is world-readable (it treats your password as leaked and rightly so):

sudo chmod 600 /etc/msmtprc

Now the test. This is the part that saves you an hour later, so do not skip it:

echo "Test from the Pi" | msmtp you@yourdomain.com

No output means it sent. Check the inbox. If it is not there, the log at /var/log/msmtp.log names the exact failure (auth failed, TLS refused, DNS miss).

If your relay only speaks plain SMTP on port 25 inside your own network, that is fine too: set tls off and port 25. Just make sure the Pi and the relay stay on the trusted side of your router.

The code

Any script can now send mail through one command. The alert about a full disk looks like this:

#!/bin/bash
# disk-alert.sh: email when root filesystem passes 90%
THRESHOLD=90
USAGE=$(df --output=pcent / | tail -1 | tr -dc '0-9')
if [ "$USAGE" -ge "$THRESHOLD" ]; then
    {
        echo "Subject: Pi disk alert: ${USAGE}% full"
        echo ""
        echo "The root filesystem on $(hostname) is at ${USAGE}%."
        echo "Time to find out what grew: du -xh / --max-depth=2 | sort -h"
    } | msmtp you@yourdomain.com
fi

Notice the subject line is just a header in the message body. That is the sendmail convention: headers, a blank line, then the text. msmtp parses it out and the rest becomes the body.

Schedule it so the check happens whether you remember or not:

crontab -e

Add:

0 * * * * /home/pi/bin/disk-alert.sh

Every hour, on the hour, the script checks and stays quiet unless the disk crosses the line. An alert system that sends nothing is a system that works.

One step up: attach what went wrong instead of describing it. The backup-failure alert that includes the last 20 lines of the log:

tail -20 /var/log/backup.log | mail -s "backup failed on $(hostname)" you@yourdomain.com

(mail from the mailutils package uses the same sendmail shim, so it goes out through msmtp without extra setup.)

What you learned

  • msmtp is a send-only mail client: it authenticates to an SMTP relay you control, sends, and exits. Nothing listens, nothing stores.
  • The sendmail shim (msmtp-mta) makes every mail-sending tool on the Pi work through the same config.
  • The pattern in 1 sentence: any script, one pipe into msmtp, and the alert is in your inbox with a timestamp you can search later.

When something breaks

  • Nothing arrives, no error. Check /var/log/msmtp.log. Nine times out of ten it is auth: the password has special characters that need quoting, or the relay expects the full email address as the username, not just the part before the @.
  • “Cannot connect to SMTP server”. The relay hostname does not resolve from the Pi (e.g. you typoed it, or the Pi’s DNS is still on the router and the relay is internal). Test with ping mail.yourdomain.com, then fix the host line.
  • “sendmail: cannot log” or permission errors after an OS update. Package updates occasionally reset config permissions. Re-run sudo chmod 600 /etc/msmtprc and the send test again.
  • Cron runs the script but no mail. Cron’s PATH is minimal and it does not inherit your shell environment. Use absolute paths inside the script (/usr/bin/msmtp, not msmtp) and test the script by running it as cron would: env -i /bin/bash /home/pi/bin/disk-alert.sh.
  • Gmail-style providers reject the message. If you are relaying through a large provider instead of your own server, they may require an app password and refuse everything else. That is the account-expiry problem from the top of this post coming back. Own the relay, skip the dance.

What to build next

Pair the alert script with the SQLite logging tutorial: the logger emails you only when a sensor value crosses a threshold, and the database keeps the full history for the review afterwards. The ntfy notification tutorial is the lower-latency sibling for phone pings (e.g. email for the record, ntfy for the right now). If you want the alerts delivered anywhere in the world, the WireGuard tutorial gets the Pi reachable without exposing it. —Brian