Version 2.3.0 — 2026-06-30
A lightweight, distro-agnostic email wrapper for Linux. It uses msmtp to send authenticated emails through an external SMTP server, while adding two things msmtp alone does not do: a hostname tag in the subject and local alias resolution (à la sendmail). Perfect for scripts, cron jobs, and system notifications.
Works on RedHat / Rocky Linux / AlmaLinux / Fedora and Debian / Ubuntu (and any
distribution shipping bash, GNU coreutils and msmtp).
🌍 Language / Lingua — 🇬🇧 English · 🇮🇹 Italiano
msmtp is a tiny SMTP client that can relay mail through an authenticated external server,
but it does not behave like a full MTA. When several servers all send notifications through
the same mailbox you usually want two extra things:
- Know which host sent the mail — every subject gets prefixed with the short hostname,
e.g.
[web01] Disk almost full. - Send to local names, not real addresses — scripts and cron keep mailing
root, and the wrapper rewritesrootinto the real address through an alias file.
This wrapper adds exactly that on top of msmtp, and it is configured without editing the script (config file + environment variables), so the same versioned script runs unchanged on every machine.
The wrapper is invoked like a sendmail-style MTA: it reads the raw message from stdin
and takes the recipient as its first argument ($1). For each message it:
- Buffers stdin to a temporary file.
- Determines the recipient — prefers the
To:header (extracting the address inside<...>when a display name is present), falls back to$1, then toDEFAULT_RECIPIENT. - Resolves that name through the alias file (an alias may expand to several comma-separated addresses).
- Rewrites the message: sets the resolved
To:, prefixes theSubject:with the short hostname tag, and adds aFrom:if missing. - Logs the resolution and relays the message through
msmtp.
| File | What it is | Where it goes |
|---|---|---|
msmtp-wrapper.sh |
the wrapper script | /opt/bin/msmtp-wrapper.sh |
msmtp-wrapper.conf |
your wrapper settings (account, sender, paths…) | /opt/etc/msmtp-wrapper.conf |
msmtp-aliases |
local name → real address map | /opt/etc/msmtp-aliases |
msmtprc |
msmtp account / SMTP server credentials | /etc/msmtprc |
- A Linux system with
bashand GNU coreutils (grep,sed,awk,mktemp,hostname) - Access to an SMTP server (host, port, username, password)
msmtpand amailcommand (provided bys-nail)
RedHat / Rocky Linux / AlmaLinux / Fedora
sudo dnf install msmtp s-nailDebian / Ubuntu
sudo apt update
sudo apt install msmtp msmtp-mta s-nail
msmtp-mtaprovides/usr/sbin/sendmail, useful if you later want msmtp to act as the system MTA.s-nailprovides the
Copy the example and edit it with your real SMTP credentials:
sudo cp msmtprc /etc/msmtprc
sudo nano /etc/msmtprcPick the CA trust store path that matches your distribution:
- RedHat / Rocky / AlmaLinux / Fedora →
/etc/ssl/certs/ca-bundle.crt - Debian / Ubuntu →
/etc/ssl/certs/ca-certificates.crt
The file contains a password, so lock it down:
sudo chmod 600 /etc/msmtprcVerify msmtp on its own can send before involving the wrapper:
echo -e "Subject: msmtp direct test\n\nhello" | msmtp -a default you@example.comsudo install -D -m 0755 msmtp-wrapper.sh /opt/bin/msmtp-wrapper.shsudo install -D -m 0644 msmtp-aliases /opt/etc/msmtp-aliasesFormat (one mapping per line; comma-separate multiple targets):
root: admin@example.com
postmaster: postmaster@example.com
team: alice@example.com, bob@example.com
sudo install -D -m 0644 msmtp-wrapper.conf /opt/etc/msmtp-wrapper.conf
sudo nano /opt/etc/msmtp-wrapper.confSet at least MSMTP_ACCOUNT (must match the account in /etc/msmtprc) and MAILFROM.
This is the step people miss.
root. You must tell the system to use the wrapper as its mailer.
Option A — point s-nail (the mail command) at the wrapper (matches the test below).
Add this line to the system mail config (/etc/mail.rc on RedHat/Rocky/Alma,
/etc/s-nail.rc on Debian/Ubuntu), or to your ~/.mailrc:
set mta=/opt/bin/msmtp-wrapper.sh
Option B — make the wrapper the system sendmail (also covers cron and anything that
calls sendmail). Point /usr/sbin/sendmail at the wrapper, e.g.:
sudo ln -sf /opt/bin/msmtp-wrapper.sh /usr/sbin/sendmailUse Option B only if you want the wrapper to be the machine-wide mailer. It is fine because the script now parses sendmail-style arguments (
-i,-oi,-t,-f, …).
echo "This is the body of the test email." | mail -s "Test email via msmtp" rootThen check the logs:
sudo tail -n 5 /var/log/msmtp-wrapper.log # alias resolution by the wrapper
sudo tail -n 20 /var/log/msmtp.log # the SMTP transactionIf
/var/log/msmtp-wrapper.loggets no new line, the wrapper was not invoked — revisit step 6, the mailer is still bypassing it.
All parameters resolve in three layers, highest precedence first:
- Environment variables — e.g.
MSMTP_ACCOUNT=foo /opt/bin/msmtp-wrapper.sh - Config file —
/opt/etc/msmtp-wrapper.conf(change its path withMSMTP_WRAPPER_CONFIG) - Built-in defaults in the script
So you never edit the versioned script: put values in the config file, or pass them as environment variables (handy for one-off overrides and testing).
| Variable | Default | Description |
|---|---|---|
MSMTP_ACCOUNT |
default |
msmtp account, selected with msmtp -a (must exist in /etc/msmtprc) |
MAILFROM |
(empty) | envelope sender override; empty = use the from in /etc/msmtprc |
FROM_HEADER |
(empty) | visible From: header (may include a display name); empty = use the account's from (auth user) |
SUBJECT_PREFIX |
[<short-hostname>] |
text prepended to every Subject |
ALIAS_FILE |
/opt/etc/msmtp-aliases |
local alias file |
LOGFILE |
/var/log/msmtp-wrapper.log |
wrapper log (best-effort) |
MSMTP_BIN |
autodetected (command -v msmtp) |
path to the msmtp binary |
DEFAULT_RECIPIENT |
root |
recipient when none is provided |
Mail still goes to root / aliases not resolved. The wrapper is not in the delivery
path. Re-check step 6: after a test there
must be a fresh line in /var/log/msmtp-wrapper.log.
553 5.7.1 Sender address rejected: not owned by user …. The envelope sender does not
match the authenticated SMTP user. Leave MAILFROM empty so msmtp uses the from in
/etc/msmtprc (which matches your login), or set MAILFROM to an address the server lets
that user send as. The from argument that mail/s-nail passes (e.g. root@host) is
intentionally ignored by the wrapper.
cannot use a network connection / TLS errors. Wrong tls_trust_file for your distro
— see step 2.
msmtp è un piccolo client SMTP che inoltra la posta tramite un server esterno
autenticato, ma non si comporta come un MTA completo. Quando più server inviano notifiche
attraverso la stessa casella, di solito servono due cose in più:
- Sapere quale host ha mandato la mail — ogni oggetto viene prefissato con l'hostname
breve, es.
[web01] Disco quasi pieno. - Inviare a nomi locali, non a indirizzi reali — script e cron continuano a scrivere a
root, e il wrapper riscriverootnell'indirizzo reale tramite un file di alias.
Questo wrapper aggiunge esattamente questo sopra a msmtp, e si configura senza modificare lo script (file di configurazione + variabili d'ambiente): lo stesso script versionato gira invariato su ogni macchina.
Il wrapper viene invocato come un MTA in stile sendmail: legge il messaggio grezzo da
stdin e prende il destinatario come primo argomento ($1). Per ogni messaggio:
- Salva lo stdin in un file temporaneo.
- Determina il destinatario — preferisce l'header
To:(estraendo l'indirizzo dentro<...>se c'è un nome visualizzato), poi ricade su$1, infine suDEFAULT_RECIPIENT. - Risolve quel nome tramite il file degli alias (un alias può espandersi in più indirizzi separati da virgola).
- Riscrive il messaggio: imposta il
To:risolto, antepone all'Subject:il tag con l'hostname breve e aggiunge unFrom:se assente. - Registra la risoluzione nel log e inoltra il messaggio tramite
msmtp.
| File | Cos'è | Dove va |
|---|---|---|
msmtp-wrapper.sh |
lo script wrapper | /opt/bin/msmtp-wrapper.sh |
msmtp-wrapper.conf |
le tue impostazioni del wrapper (account, mittente, percorsi…) | /opt/etc/msmtp-wrapper.conf |
msmtp-aliases |
mappa nome locale → indirizzo reale | /opt/etc/msmtp-aliases |
msmtprc |
account / credenziali del server SMTP per msmtp | /etc/msmtprc |
- Un sistema Linux con
bashe GNU coreutils (grep,sed,awk,mktemp,hostname) - Accesso a un server SMTP (host, porta, utente, password)
msmtpe un comandomail(fornito das-nail)
RedHat / Rocky Linux / AlmaLinux / Fedora
sudo dnf install msmtp s-nailDebian / Ubuntu
sudo apt update
sudo apt install msmtp msmtp-mta s-nail
msmtp-mtafornisce/usr/sbin/sendmail, utile se in seguito vuoi che msmtp faccia da MTA di sistema.s-nailfornisce il comando
Copia l'esempio e inserisci le tue credenziali SMTP reali:
sudo cp msmtprc /etc/msmtprc
sudo nano /etc/msmtprcScegli il percorso del CA trust store adatto alla tua distribuzione:
- RedHat / Rocky / AlmaLinux / Fedora →
/etc/ssl/certs/ca-bundle.crt - Debian / Ubuntu →
/etc/ssl/certs/ca-certificates.crt
Il file contiene una password, quindi proteggilo:
sudo chmod 600 /etc/msmtprcVerifica che msmtp da solo riesca a inviare, prima di coinvolgere il wrapper:
echo -e "Subject: test diretto msmtp\n\nciao" | msmtp -a default tu@example.comsudo install -D -m 0755 msmtp-wrapper.sh /opt/bin/msmtp-wrapper.shsudo install -D -m 0644 msmtp-aliases /opt/etc/msmtp-aliasesFormato (una mappatura per riga; più destinatari separati da virgola):
root: admin@example.com
postmaster: postmaster@example.com
team: alice@example.com, bob@example.com
sudo install -D -m 0644 msmtp-wrapper.conf /opt/etc/msmtp-wrapper.conf
sudo nano /opt/etc/msmtp-wrapper.confImposta almeno MSMTP_ACCOUNT (deve corrispondere all'account in /etc/msmtprc) e
MAILFROM.
È lo step che quasi tutti saltano.
root. Devi dire al sistema di usare il wrapper come mailer.
Opzione A — fai puntare s-nail (il comando mail) al wrapper (è quella usata nel test
qui sotto). Aggiungi questa riga alla config di posta di sistema (/etc/mail.rc su
RedHat/Rocky/Alma, /etc/s-nail.rc su Debian/Ubuntu), oppure al tuo ~/.mailrc:
set mta=/opt/bin/msmtp-wrapper.sh
Opzione B — rendi il wrapper il sendmail di sistema (copre anche cron e qualsiasi cosa
chiami sendmail). Fai puntare /usr/sbin/sendmail al wrapper, es.:
sudo ln -sf /opt/bin/msmtp-wrapper.sh /usr/sbin/sendmailUsa l'Opzione B solo se vuoi che il wrapper sia il mailer di tutta la macchina. È sicura perché ora lo script interpreta gli argomenti in stile sendmail (
-i,-oi,-t,-f, …).
echo "Questo è il corpo dell'email di test." | mail -s "Email di test via msmtp" rootPoi controlla i log:
sudo tail -n 5 /var/log/msmtp-wrapper.log # risoluzione alias da parte del wrapper
sudo tail -n 20 /var/log/msmtp.log # la transazione SMTPSe in
/var/log/msmtp-wrapper.lognon compare una riga nuova, il wrapper non è stato invocato: rivedi lo step 6, il mailer lo sta ancora scavalcando.
Tutti i parametri si risolvono su tre livelli, in ordine di precedenza decrescente:
- Variabili d'ambiente — es.
MSMTP_ACCOUNT=foo /opt/bin/msmtp-wrapper.sh - File di configurazione —
/opt/etc/msmtp-wrapper.conf(percorso modificabile conMSMTP_WRAPPER_CONFIG) - Valori di default integrati nello script
Così non modifichi mai lo script versionato: metti i valori nel file di configurazione, oppure passali come variabili d'ambiente (comodo per override temporanei e per i test).
| Variabile | Default | Descrizione |
|---|---|---|
MSMTP_ACCOUNT |
default |
account msmtp, selezionato con msmtp -a (deve esistere in /etc/msmtprc) |
MAILFROM |
(vuoto) | override del mittente di busta; vuoto = usa il from di /etc/msmtprc |
FROM_HEADER |
(vuoto) | header From: visibile (può includere un display name); vuoto = usa il from dell'account (utente di autenticazione) |
SUBJECT_PREFIX |
[<hostname-breve>] |
testo anteposto a ogni Subject |
ALIAS_FILE |
/opt/etc/msmtp-aliases |
file degli alias locali |
LOGFILE |
/var/log/msmtp-wrapper.log |
log del wrapper (best-effort) |
MSMTP_BIN |
rilevato automaticamente (command -v msmtp) |
percorso del binario msmtp |
DEFAULT_RECIPIENT |
root |
destinatario quando non ne viene fornito alcuno |
La posta continua ad andare a root / gli alias non vengono risolti. Il wrapper non è
nel percorso di consegna. Ricontrolla lo step 6:
dopo un test deve comparire una riga nuova in /var/log/msmtp-wrapper.log.
553 5.7.1 Sender address rejected: not owned by user …. Il mittente di busta non
corrisponde all'utente SMTP autenticato. Lascia MAILFROM vuoto così msmtp usa il
from di /etc/msmtprc (che combacia con il tuo login), oppure imposta MAILFROM a un
indirizzo che il server consente di usare a quell'utente. Il mittente che mail/s-nail
passa (es. root@host) viene volutamente ignorato dal wrapper.
Errori TLS / cannot use a network connection. tls_trust_file sbagliato per la tua
distro — vedi lo step 2.
