Read and Send Email from the Linux Command Line with mail
Learn to send email, read local mailboxes, open mbox files, and troubleshoot Linux mail, mailx, and GNU mailutils mail.
The mail command is a basic text-based mail user agent for Linux. It lets you compose and send messages from a terminal and read messages delivered to a local Linux mailbox.
This lesson assumes familiarity with Bash, shell command syntax, users, home directories, standard input, and filesystem paths.
What the mail Command Does
mail is a command-line mail utility. Depending on the installed implementation, the same family of tools may be invoked as mail, mailx, or GNU Mailutils mail.
It performs two related tasks:
- It composes and submits outgoing messages to the local mail system.
- It opens and reads messages delivered to the current user's local mailbox.
It is not an IMAP or POP client. The command does not normally log in to a remote mail provider and download messages. Remote retrieval requires a different mail client or synchronization tool.
For external delivery, a local mail transfer agent (MTA) must be configured. An MTA accepts, routes, queues, and delivers mail. Common MTAs include Postfix, Sendmail, Exim, and nullmailer. The mail command normally hands a message to this local service rather than delivering SMTP mail by itself.
Check Which mail Implementation Is Installed
Option behavior can vary slightly between distributions and implementations. First locate the executable and then read the local manual page.
command -v mail
command -v mailx
readlink -f "$(command -v mail)"
man mail
If mail is unavailable, a mail client package may not be installed, or the distribution may provide a related command such as mailx. Use the operating system's package manager to install the appropriate mail client package, then verify its documentation.
Send a Basic Email Interactively
The general form is:
mail -s "Subject" recipient
The -s option supplies the message subject. The recipient is placed at the end of the command line. After the command starts, type the message body directly into the terminal.
mail -s "Hello" bob
Type the body, for example:
Hello Bob,
This is a test message from Linux.
Finish the message by pressing Ctrl+D at an empty or new input boundary. This sends an end-of-input signal to mail and submits the message.
A local username such as bob is appropriate when that account is hosted by the local system or local mail domain. For a recipient outside the local mail environment, use a fully qualified email address containing a local part and domain:
mail -s "Status update" admin@example.com
External delivery still depends on a correctly configured outbound MTA, DNS, network access, and any required relay authorization.
Subjects, Primary Recipients, and CC
The primary recipient is the person or account directly listed as the destination. A carbon copy (CC) recipient receives a visible additional copy.
mail -s "Hello" -c jack bob
bobis the primary recipient.jackis a CC recipient.- Both recipients are listed on the message headers.
Some implementations support additional header options, including blind carbon copy (BCC). Because syntax differs, verify support with man mail before using those options in scripts.
Send Mail Noninteractively
For scripts, monitoring, scheduled jobs, and automation, provide the message body through standard input instead of typing it interactively.
printf '%s\n' 'Backup completed successfully.' | mail -s "Backup status" admin@example.com
printf writes the body, and the pipe sends that output to mail as its input.
Use careful quoting when shell variables are included. Single quotes prevent expansion, while double quotes allow variables to expand. Do not put untrusted text into a shell command without understanding quoting and argument boundaries.
recipient='admin@example.com'
subject='Backup status'
body='Backup completed successfully.'
printf '%s\n' "$body" | mail -s "$subject" "$recipient"
Quoting each variable helps preserve spaces and prevents accidental word splitting or shell metacharacter interpretation.
Read the Current User's Local Mail
Run mail without recipient arguments to open the current user's default local mailbox:
mail
A typical interface displays a message list containing:
- A message number used to select a message.
- An unread or read indicator, depending on the implementation.
- The sender.
- The date or time.
- The subject.
Select a message by entering its number at the mail prompt. For example, enter 1 to view message 1. After reading it, use the implementation's documented navigation and quit commands to move through the mailbox or exit.
Interactive commands differ somewhat between mail, mailx, and GNU Mailutils. Consult the local manual page for commands that list, delete, preserve, reply to, save, or quit messages. At a conceptual level, the workflow is:
- Run
mail. - Review the message list.
- Enter a message number to display its contents.
- Navigate or save messages as needed.
- Quit using the command documented by the installed implementation.
Open Saved Mail and mbox Files
An mbox is a mailbox file format that stores multiple messages in one file. Depending on configuration and exit behavior, read messages may be moved or copied to an mbox file in the user's home directory, often ~/mbox.
Open a specific saved mailbox with -f:
mail -f ~/mbox
The actual saved-mail filename and location can differ. The default local mailbox, saved mail, and mail behavior on exit are controlled by the mail client and local mail configuration.
How Local Mail Delivery Works
The main components form a delivery path:
- The
mailclient creates a message and submits it. - The local MTA accepts the message.
- The MTA either delivers it locally or places it in an outgoing mail queue.
- For local delivery, the message is written to the recipient's mailbox spool.
- For remote delivery, the MTA contacts another mail server, subject to its configuration and network policies.
A mail spool is a system-managed location containing local user mailbox files. Common examples include:
/var/mail/USERNAME
/var/spool/mail/USERNAME
These paths are not universal. Permissions, mailbox formats, delivery agents, and system configuration may place mail elsewhere.
These stages are different: a message in the outgoing queue has not necessarily reached the recipient's mailbox, while a message in a local spool has been delivered locally.
Recipient Formats
Verify Local Delivery Safely
Start with a test to your own account or another account you are authorized to use. This avoids testing against an unintended external recipient.
printf '%s\n' 'Local mail test.' | mail -s "Local test" "$USER"
mail
Open the mailbox after sending and look for the new subject. You can also test another authorized local account:
printf '%s\n' 'Testing local delivery.' | mail -s "Delivery test" bob
mail
When using the second command, open the mailbox belonging to bob, not necessarily your own.
To inspect common spool paths, use:
ls -l /var/mail/$USER /var/spool/mail/$USER 2>/dev/null
Do not assume that being able to read a file means you should access it. Mailbox files contain private communications and are protected by system permissions.
Security and Privacy
Command-line email is not inherently encrypted. The message may be stored locally in plaintext, transferred through unencrypted links, or passed through mail servers that are not under your control.
- Do not send passwords, private keys, tokens, or other sensitive data through an untrusted mail path.
- Confirm the recipient address before sending automated messages.
- Use an appropriately configured encrypted transport and trusted relay when confidentiality matters.
- Protect scripts, logs, shell history, and mailbox files from unauthorized access.
Troubleshooting
mail: command not found
Check both common command names:
command -v mail
command -v mailx
If neither command exists, install the distribution's mail client package. The package may provide a mailx implementation or GNU Mailutils. Read the package documentation and verify the resulting command with command -v.
External mail never arrives
The local command may have accepted the message even though external delivery failed. Common causes include a missing or stopped MTA, an unavailable DNS service, firewall restrictions, an unauthorized SMTP relay, or a message waiting in the queue.
systemctl status postfix
This is an example for Postfix. Substitute the service name for the MTA installed on the system. Inspect the MTA's queue and logs using commands appropriate for that implementation. Test local delivery separately before debugging remote delivery.
The mailbox is empty
There may be no messages for the current user, the message may have been sent to another local account, or the wrong mailbox file may be open. Confirm the recipient account, inspect common spool paths, and explicitly open a saved file if needed:
mail -f ~/mbox
Ctrl+D does not finish the message
Make sure mail is currently accepting the message body and that the terminal is not waiting at another prompt. As an alternative, avoid interactive input:
printf '%s\n' 'Message body' | mail -s "Subject" user@example.com
A local username reaches the wrong person
The name may not identify the intended local account, a local alias may redirect it, or the intended recipient may actually be external. Verify the username and use a complete address for remote mail. Review local aliases and MTA routing configuration when appropriate.
Options behave differently
The installed command may be a different mail implementation. Locate it and read its manual:
command -v mail
readlink -f "$(command -v mail)"
man mail
Use the syntax documented for that implementation rather than assuming that every mail command supports identical options.
Quick Reference
# Interactive local message
mail -s "Hello" bob
# Primary recipient plus CC
mail -s "Hello" -c jack bob
# Fully qualified recipient
mail -s "Status update" admin@example.com
# Noninteractive message
printf '%s\n' 'Message body' | mail -s "Subject" user@example.com
# Read the default local mailbox
mail
# Open a saved mbox file
mail -f ~/mbox
# Locate the command and read its manual
command -v mail && man mail