New guide: how to warm up a dedicated IP without hurting your reputation. Read now →
Log in
MigoSMTP
SMTP and APIUpdated 26 Oct 2026

Send Email from the Linux Command Line: msmtp, curl, mail and Cron Alerts

Send email from a Linux server or script through an authenticated SMTP relay: msmtp configuration, the mail command, curl SMTP, cron and systemd alerts, credential safety and troubleshooting.

JL
Written by Jonas Lindqvist
Security Engineer
Reviewed by Mateus Oliveira
  • Published21 Jul 2026
  • Read time7 min
  • Length1,483 words
Share this guide

Servers need to send email too. A backup script wants to report that it finished, a cron job should tell you when it fails, a monitoring check needs to raise an alert and a certificate renewal hook should confirm that it ran. Running a full mail server on every machine for this is more work than it is worth and a poor idea for deliverability: a server with no reputation, no reverse DNS and a blocked port 25 sends mail that is often rejected or lost. A better design is to keep the server simple and have it hand every message to an authenticated SMTP relay. This guide shows three ways to do that from the command line: msmtp, a small sender that behaves like the classic sendmail program; the mail command on top of it; and curl, which speaks SMTP without any extra software. It then covers cron and systemd alerts, how to keep the password safe and how to troubleshoot. The examples use placeholders. Take real values from your SMTP provider's dashboard.

msmtpLightweight sender that relays through SMTP with TLS and authentication
mailFamiliar command that hands the message to msmtp or sendmail
curlNo install needed: curl can send SMTP with STARTTLS or implicit TLS
CronSet MAILTO and make failures visible

Why relay instead of sending directly

When a server delivers mail itself, the receiving server judges the machine: its IP address, whether the reverse DNS name matches, whether the sending domain has SPF and DKIM and whether the IP has been abused before. Cloud and home networks frequently block outbound port 25 and have addresses that are on shared ranges mailbox providers distrust. A relay turns this around. Your server makes one authenticated, encrypted connection to a service that has a clean reputation and proper authentication, and the service delivers the message. You also get logs, bounce handling and a single place to rotate credentials. If a Postfix installation is already in place, the guide to configuring Postfix as an authenticated relay client is the heavier but more featureful alternative.

Install msmtp

# Debian and Ubuntu
sudo apt install msmtp msmtp-mta ca-certificates

# RHEL, Rocky, Alma and Fedora
sudo dnf install msmtp

The msmtp-mta package on Debian and Ubuntu creates a sendmail compatibility link, so programs that call /usr/sbin/sendmail, including cron, PHP and many monitoring tools, use msmtp automatically. Only install it on a machine that does not already run a mail server, because it takes over the sendmail name.

Write the configuration

msmtp reads /etc/msmtprc for the whole system or ~/.msmtprc for one user. The file holds the relay settings and, unless you store the password elsewhere, the password, so its permissions matter.

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

account        relay
host           smtp.example.com
port           587
from           [email protected]
user           your-smtp-user
passwordeval   "cat /etc/msmtp-password"

account default : relay

Set tls_starttls on with port 587. For implicit TLS on port 465, use port 465 and tls_starttls off. msmtp verifies the server certificate against the trust file, which is the setting that prevents someone on the network from reading your password; do not turn verification off to make an error disappear. The passwordeval line runs a command and uses its output as the password, so the password is not written in the main file and can come from a secrets tool instead. If you are unsure which port to choose, read which SMTP port to use.

sudo sh -c 'printf "%s" "your-smtp-password" > /etc/msmtp-password'
sudo chmod 600 /etc/msmtp-password /etc/msmtprc
sudo chown root:root /etc/msmtp-password /etc/msmtprc

msmtp refuses to read a configuration file that other users can read when it contains a password, which is a useful safeguard. If non-root users, such as a web server user, must send mail, create a group for them and give the file to that group with mode 640, or use a separate file per user.

Send a first message

printf 'To: [email protected]\nFrom: [email protected]\nSubject: Test from server\n\nHello from the command line.\n' \
  | msmtp -a default [email protected]

msmtp does not build headers for you: it sends what it reads from standard input. The envelope recipient is the address after the options, and the To, From and Subject lines are part of the message. Keep a blank line between the headers and the body. Add --debug to see the full conversation, including the TLS negotiation, and remove it afterwards because the output contains encoded credentials.

Use the mail command

Most administrators prefer the familiar mail command. Install a mail user agent such as s-nail or bsd-mailx, which calls sendmail and therefore msmtp.

echo "Backup finished: 42 GB in 18 minutes" \
  | mail -s "Backup report: web01" -r [email protected] [email protected]

# with an attachment (s-nail)
echo "Report attached" | mail -s "Weekly report" -a report.csv [email protected]

The -r option sets the sender, which must be an address your provider allows. If the From address is not on a verified domain, the relay will reject the message. See the guide on authenticating your sending domain.

Send with curl

If you do not want to install anything, curl can send a message over SMTP. Write the message to a file, including its headers, and give curl the envelope.

cat > /tmp/msg.txt <<'MSG'
From: Alerts <[email protected]>
To: [email protected]
Subject: Disk space warning

The /var volume on web01 is 91% full.
MSG

curl --ssl-reqd --url 'smtp://smtp.example.com:587' \
  --mail-from '[email protected]' \
  --mail-rcpt '[email protected]' \
  --netrc-file /root/.netrc-smtp \
  --upload-file /tmp/msg.txt

The --ssl-reqd option makes curl fail if STARTTLS is not available instead of falling back to clear text. For port 465, use smtps://smtp.example.com:465. Keep the credentials in a file given with --netrc-file, in the format machine smtp.example.com login USER password PASS with mode 600, and avoid --user USER:PASS on the command line: other users on the machine can see command-line arguments in the process list. The same applies to any tool: never put a password in an argument.

Cron and systemd alerts

Cron emails the output of a job to the user that owns it, using sendmail, which msmtp now provides. Set the recipient at the top of the crontab, and keep the job quiet when it succeeds, so that an email always means something.

[email protected]
# Mail only on failure: stdout hidden, errors are mailed
15 2 * * * /usr/local/bin/backup.sh >/dev/null

For systemd services, add an OnFailure= unit that sends a message with the failed unit's name and the last log lines, which you can fetch with journalctl -u NAME -n 30. Alerts that arrive only when something breaks are far more useful than a daily report that everyone ignores. Add a second check that tells you if the expected success message has not arrived, because a dead cron daemon sends nothing at all.

Keep credentials safe

A server credential is only as safe as the weakest machine that holds it. Use a dedicated SMTP user for alerts, separate from the one your application uses, with the lowest limits that work, so a leak has a small blast radius. Keep the file mode at 600, do not commit it to a repository or a configuration-management template in plain text, and rotate the password if a person with access leaves. Avoid passwords in shell history and process lists. Restrict who may run the sending command if the machine is shared, since anyone who can run it can send mail as your domain.

Troubleshooting

SymptomLikely causeFix
msmtp: authentication failed (method PLAIN)Wrong user or password, or a trailing newline in the password fileRe-create the file with printf "%s"; see SMTP error 535
cannot connect or timeoutOutbound port blocked, or wrong hostTest the port from the server using the SMTP test guide
TLS certificate verification failedMissing CA bundle, wrong host name or the system clock is wrongInstall ca-certificates, use the exact host and check the time with timedatectl
configuration file ... must have no more than user read/write permissionsFile mode too openRun chmod 600 on the file
Cron sends nothingNo sendmail on the path, or the job prints nothingCheck which sendmail and run the job by hand
Sender rejectedFrom address not on a verified domainUse -r or from with an authenticated address
Message accepted but in spamNo SPF, DKIM or DMARC for the From domainPublish the records and follow the spam checklist

The msmtp log is the first place to look. Each attempt records the server reply, which tells you whether the problem is the connection, the login or the message. Combine it with the relay's own delivery logs to follow a message from your server to the recipient's domain.

Give your servers an authenticated relay Use a dedicated SMTP user for alerts and see every message in the delivery logs.

Explore the SMTP relay

References and further reading

Frequently asked questions

How do I send email from a Linux script through SMTP?

Install msmtp, configure it with your relay host, port 587 with STARTTLS and your credentials, then pipe a message to msmtp or use the mail command.

Can curl send email?

Yes. Use curl with an smtp:// or smtps:// URL, --mail-from, --mail-rcpt and --upload-file with a message file, and add --ssl-reqd to require encryption.

How do I make cron email me only on failure?

Set MAILTO, send normal output to /dev/null and let errors on standard error be mailed. Also monitor for the success message not arriving.

Where should I keep the SMTP password on a server?

In a file readable only by the sending user, with mode 600, read by passwordeval or a netrc file. Never put it in command-line arguments.

Why does msmtp refuse my configuration file?

Because it contains a password and other users can read the file. Set the mode to 600 or 640 for a dedicated group.

Topics#linux#msmtp#curl#cron#smtp#sysadmin
Was this guide helpful?Your answer helps us improve our documentation.

Start sending in minutes.

Create an account, add your domain and send your first email.

Get started Talk to sales