Automate Email Sending with msmtp and CronAutomating email sending on a Unix-like system is useful for notifications, backups, monitoring alerts, and scheduled reports. This guide shows how to configure msmtp — a lightweight SMTP client — and use cron to send emails automatically. It covers installation, configuration, secure authentication, composing messages, scheduling with cron, and troubleshooting.
What is msmtp?
msmtp is a simple SMTP client that forwards mail from local programs (like mailx, mutt, or custom scripts) to an external SMTP server. It is lightweight, easy to configure, and supports TLS/SSL and authentication mechanisms required by modern SMTP servers (e.g., Gmail, Outlook, corporate SMTP). Unlike full mail transfer agents (MTAs) such as Postfix or Exim, msmtp does not queue or accept incoming mail — it simply relays outgoing messages.
Why use msmtp + cron?
- Minimal resource usage compared to full MTAs.
- Straightforward configuration and integration with scripts.
- Works well for automated notifications (backup completion, system health checks, CI/CD).
- Cron provides reliable time-based scheduling available on virtually all Unix-like systems.
Installation
On Debian/Ubuntu:
sudo apt update sudo apt install msmtp msmtp-mta
On Fedora:
sudo dnf install msmtp msmtp-mta
On Arch:
sudo pacman -S msmtp
On macOS (Homebrew):
brew install msmtp
msmtp-mta provides a symlink so programs expecting sendmail can call msmtp.
msmtp configuration
msmtp reads configuration from /etc/msmtprc (system-wide) and ~/.msmtprc (per-user). File permissions should be restricted to the owner (600).
Example ~/.msmtprc with TLS and login authentication:
# ~/.msmtprc # Set default account defaults auth on tls on tls_trust_file /etc/ssl/certs/ca-certificates.crt logfile ~/.msmtp.log # Account for Gmail account gmail host smtp.gmail.com port 587 user [email protected] passwordeval "gpg --quiet --for-your-eyes-only --no-tty -d ~/.mail/gmail.pass.gpg" # Set a default account account default : gmail
Important notes:
- Use
passwordeval
to avoid plaintext passwords;passwordeval
runs a command and uses its stdout as the password. - For simple setups you can use
password
instead ofpasswordeval
, but ensure~/.msmtprc
is permission 600. tls_trust_file
path may vary by distro: common locations include /etc/ssl/certs/ca-certificates.crt or /etc/ssl/cert.pem.
Encrypting password with GPG example:
echo -n "your_app_password" | gpg --symmetric --cipher-algo AES256 -o ~/.mail/gmail.pass.gpg chmod 600 ~/.mail/gmail.pass.gpg
Then passwordeval
example above decrypts it when msmtp runs.
For Gmail specifically:
- If using regular account password, Gmail may block access. Use an App Password (recommended) with 2-Step Verification enabled, or configure OAuth2 (more complex).
Sending an email from the command line
msmtp expects a full RFC-5322 message on stdin. A quick way to send a simple message:
printf "From: [email protected] To: [email protected] Subject: Test from msmtp Hello from msmtp. " | msmtp [email protected]
Using a file:
msmtp [email protected] < /path/to/message.eml
Composing with heredoc in a script:
msmtp [email protected] <<EOF From: [email protected] To: [email protected] Subject: Backup completed Backup finished successfully at $(date). EOF
For attachments, use a tool like mutt, mailx, or uuencode to create MIME messages, or build MIME manually.
Example with mailx (s-nail) configured to use msmtp as sendmail:
echo "Backup completed" | mailx -s "Backup report" -a /path/to/log.txt [email protected]
Ensure mailx is configured to call msmtp (msmtp-mta package or sendmail symlink).
Integrating into scripts
Create a script that generates the message and calls msmtp.
Example backup notification script /usr/local/bin/backup-notify.sh:
#!/usr/bin/env bash set -euo pipefail RECIP="[email protected]" SUBJ="Backup finished on $(hostname)" BODY="/tmp/backup_body_$$.txt" cat > "$BODY" <<EOF From: backup@$(hostname) To: $RECIP Subject: $SUBJ Backup completed successfully. Date: $(date) EOF msmtp "$RECIP" < "$BODY" && rm -f "$BODY"
Make it executable:
chmod +x /usr/local/bin/backup-notify.sh
Scheduling with cron
Edit the crontab for the user who has msmtp configured:
crontab -e
Example entries:
- Run backup daily at 02:00 and send notification: 0 2 * * * /usr/local/bin/perform-backup.sh && /usr/local/bin/backup-notify.sh
- Send weekly report every Monday at 07:30: 30 7 * * 1 /usr/local/bin/send-weekly-report.sh
Tips:
- Use full paths for scripts and binaries in cron.
- Cron environment is minimal; explicitly set PATH, HOME, and other env vars at top of crontab if needed: PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin HOME=/home/youruser
- Log cron output to a file for debugging: 0 2 * * * /usr/local/bin/backup-notify.sh >> /var/log/backup-notify.log 2>&1
Secure authentication options
- App Passwords: For providers like Gmail, create an App Password when 2FA is enabled and use it with msmtp.
- GPG-encrypted password files: store SMTP password encrypted and use passwordeval to decrypt.
- OAuth2: msmtp supports XOAUTH2 via passwordeval scripts that fetch and refresh tokens. This is more complex but removes long-term passwords from disk.
Simple passwordeval example that reads GPG-decrypted password:
passwordeval "gpg -q --for-your-eyes-only --no-tty -d ~/.mail/gmail.pass.gpg"
Handling attachments and HTML
msmtp itself sends raw RFC-5322 messages. To include attachments or HTML you must build a MIME message. Use tools:
- mutt or neomutt
- mailx (s-nail)
- msmtp + uuencode (older)
- python (email.mime) to generate MIME
Example using mutt:
echo "See attached log" | mutt -s "Backup log" -a /var/log/backup.log -- [email protected]
Configure mutt to use msmtp as sendmail, or ensure msmtp-mta provides sendmail compatibility.
Example using Python (script creates MIME and sends via msmtp):
#!/usr/bin/env python3 from email.message import EmailMessage import subprocess msg = EmailMessage() msg['From'] = 'backup@hostname' msg['To'] = '[email protected]' msg['Subject'] = 'Backup log' msg.set_content('See attached log.') with open('/var/log/backup.log','rb') as f: data = f.read() msg.add_attachment(data, maintype='text', subtype='plain', filename='backup.log') # Send via msmtp proc = subprocess.Popen(['msmtp','[email protected]'], stdin=subprocess.PIPE) proc.communicate(msg.as_bytes())
Troubleshooting
- Permission errors: ensure ~/.msmtprc is chmod 600 and readable only by owner.
- TLS errors: verify tls_trust_file path and CA bundle. Use
tls on
and correct CA file. - Authentication failures: check username/password or app password; test with verbose mode: msmtp –debug –from=default -t < /path/to/message.eml
- Connection issues: confirm firewall allows outbound SMTP (ports 587/465/25) and provider accepts connections.
- Cron emails not being sent: capture cron stdout/stderr to a log file and run script manually to replicate.
Example: end-to-end setup for daily report
- Create ~/.msmtprc with encrypted password and default account.
- Create /usr/local/bin/send-daily-report.sh that composes a MIME message (or plain) and calls msmtp.
- Add cron entry: 0 8 * * * /usr/local/bin/send-daily-report.sh >> /var/log/daily-report.log 2>&1
Conclusion
msmtp plus cron provides a dependable, low-overhead solution to automate outgoing email from scripts and scheduled tasks. With proper configuration (secure passwords, TLS, and careful cron setup), you can reliably send notifications, reports, and alerts without running a full mail server.
Leave a Reply