
Learn through the super-clean Baeldung Pro experience:
>> Membership and Baeldung Pro.
No ads, dark-mode and 6 months free of IntelliJ Idea Ultimate to start with.
Last updated: March 18, 2024
As one of the oldest still used forms of electronic message exchange, mails (emails, e-mails) emulate the real-world postal services, sometimes called snail mail. This is not much different from the internal Linux mailing system.
In this tutorial, we explore the Linux built-in mail exchange mechanism. First, we do a general overview of the internal Linux mail. Next, we continue with configuration. After that, we go through the mail directories, files, and formats. Then, we send some emails. Later, we understand how automatic mail checking works. Finally, we read the emails we sent.
We tested the code in this tutorial on Debian 12 (Bookworm) with GNU Bash 5.2.15. It should work in most POSIX-compliant environments unless otherwise specified.
To begin with, the mailing mechanism is in place for many Linux distributions out of the box. This doesn’t mean every system is a global mail server. To have that, we require special packages and configuration, as well as the use of protocols like POP3 and IMAP.
Here, we only focus on mail processing within the system, not external network interaction.
Similar to traditional electronic mail, Linux offers a message exchange system with many benefits:
Still, almost every Linux installation can internally route mails to users:
+-----------------------------+
| | Mail | Users |
| |------|-------|
| | +--->| user1 |
| | | |-------|
| System | +---<| user2 |
| | |-------|
| | | ... |
| | |-------|
| | | userN |
+-----------------------------+
In fact, this is roughly equivalent to sending mail from and to the same domain of a public email service.
To facilitate the actual message exchange activities, Linux distributions can provide different commands and tools such as mutt and others.
Most often, we have the GNU mail command:
In general, this utility has evolved from the initial UNIX and BSD versions to the GNU implementation from the mailutils package that most installations use today.
In addition to mail, the ubiquitous mailutils provides several other tools:
Hence, we use the package for this article. Now, let’s go over some typical scenarios.
The main global configuration file for Linux mail as implemented by mailutils is typically /etc/mailutils.conf:
$ cat /etc/mailutils.conf
address {
email-domain gerganov.com;
};
Here, we only specify what automatic email address domain name we’d like.
In addition, we have the /etc/mail.rc RC file with commands.
On the other hand, we can also have a local user configuration in $HOME/.mail and user commands in $HOME/.mailrc.
In these files, we can control many mail aspects:
The configuration can employ variables and has a fairly simple syntax with a comprehensive set of options.
By default, there are two main directories responsible for keeping and preserving emails:
Usually, /var/spool/mail is a symbolic link to /var/mail. We can check this via realpath:
$ realpath /var/spool/mail
/var/mail
In any case, all messages are in the MBOX format:
$ cat $HOME/mbox
From SENDER@domain Wed Nov 22 10:06:56 2023
Return-path: <SENDER@domain>
Envelope-to: RECIPIENT@domain
Delivery-date: Wed, 22 Nov 2023 10:06:56
Received: from USERNAME by DOMAIN with local (Exim 4.94.2)
(envelope-from <SENDER@domain>)
id 1r7uR1-000Jqc-EU; Wed, 22 Nov 2023 10:06:56
Subject: Mail Subject
To: <RECIPIENT@domain>
X-Mailer: mail (GNU Mailutils 3.10)
Message-Id: <E1r6661-000Jqc-DD@domain>
From: SENDER@domain
Date: Wed, 22 Nov 2023 10:06:56
Mail Body.
In short, this is a basic text format with mail fields such as From, Subject:, To:, and similar, as defined in RFC 2074 – Common Internet Message Headers.
Of course, we can send emails via the mail command:
$ whoami
user2
$ mail -s 'Mail Subject' user1 <<EOI
Mail body.
EOI
First, we use whoami to verify the current user is user2. After that, we invoke mail and set the [-s]ubject as Mail Subject and the intended recipient as user1. For the main body, we use a here-string with the EOI terminator.
Alternatively, we can compose our message interactively:
$ mail user1
Cc: [Return]
Subject: Interactive Message[Return]
Write message body here and press Ctrl+D (EOF) to submit.[Return]
[Return]
This way, messages can be on multiple lines.[Return]
[Ctrl+D]
Notably, we start by entering any Cc: recipients and the mail Subject:. Then, we continue with the mail body until Ctrl+D (EOF) is pressed.
At this point, we’ve sent two emails from user2 to user1.
Let’s send a message to several recipients simultaneously:
$ mail -s 'Multimail' user1,user3 <<EOI
Body.
EOI
Now, user1 should have three messages in their mailbox.
In most environments, the login and shell-spawn events trigger a mail check. This is usually done via configuration files.
However, modern shells often facilitate this via a feature called mailcheck, responsible for polling a preconfigured path of mail files at certain times.
When it comes to Bash, mail checks are automated and controlled by several variables:
Mail checks are done just before each primary prompt refresh. To disable interval mail checking, we can assign $MAILCHECK a non-integer non-zero value or just unset it.
Now, let’s see where the mail variables and other triggers are potentially set.
In addition to the check at regular intervals, the pam_mail Pluggable Authentication Module (PAM) ensures we see notifications at certain login events.
In particular, three files often hold lines that configure mail initialization:
So, we can check the regular login setting:
$ cat /etc/pam.d/login
# Prints the status of the user's mailbox upon successful login
# (Replaces the `MAIL_CHECK_ENAB' option from login.defs).
#
# This also defines the MAIL environment variable
# However, userdel also needs MAIL_DIR and MAIL_FILE variables
# in /etc/login.defs to make sure that removing a user
# also removes the user's mail spool file.
# See comments in /etc/login.defs
session optional pam_mail.so standard
Notably, the $MAIL variable isn’t set for SSH sessions:
$ cat /etc/pam.d/sshd
# Print the status of the user's mailbox upon successful login.
session optional pam_mail.so standard noenv # [1]
Finally, using su doesn’t produce any notifications:
$ cat /etc/pam.d/su
# Defines the MAIL environment variable
# However, userdel also needs MAIL_DIR and MAIL_FILE variables
# in /etc/login.defs to make sure that removing a user
# also removes the user's mail spool file.
# See comments in /etc/login.defs
#
# "nopen" stands to avoid reporting new mail when su'ing to another user
session optional pam_mail.so nopen
To disable any of these behaviors, we can comment out the respective line.
First, we can check the login notification:
xost login: user1
Password:
[...]
You have mail.
$ echo $MAIL
/var/mail/user1
Next, we see the example notifications after su:
$ whoami
user2
$ mail -s 'Mail 1' user1 <<< 'Mail body.'
$ su user1
$ echo $MAIL
/var/mail/user1
$ [wait 60 seconds] [Return]
You have new mail in /var/mail/user1
$
Also, let’s try an SSH session:
$ ssh user1@xost
[...]
You have new mail.
Last login: Wed Nov 22 11:10:00 2023
$ echo $MAIL
$
Finally, we can read these emails.
While the rudimentary messages, readmsg, from (frm), and similar utilities are convenient for automation, mail is usually the preferred choice when it comes to user mail interaction:
$ mail
"/var/mail/user1": 3 messages 3 new
>N 1 user2@xost Wed Nov 22 11:11 15/430 Mail Subject
N 2 user2@xost Wed Nov 22 11:11 17/530 Interactive Message
N 3 user2@xost Wed Nov 22 11:11 14/419 Multimail
?
Here, we see our user mail inbox at /var/mail/user1 and the three emails from earlier in several columns:
Now, let’s read each message by supplying its number at the ? prompt:
? 1
Return-path: <user2@xost>
Envelope-to: user1@xost
Delivery-date: Wed, 22 Nov 2023 11:11:11 -0600
Received: from user2 by xost with local (Exim 4.94.2)
(envelope-from <user2@xost>)
id 1r80gN-00666y-Ke
for user1@xost; Wed, 22 Nov 2023 11:11:11 -0600
Subject: Mail Subject
To: <user1@xost>
X-Mailer: mail (GNU Mailutils 3.10)
Message-Id: <E1r80gN-00666y-Ke@xost>
From: user2@xost
Date: Wed, 22 Nov 2023 11:11:11 -0600
Mail body.
? 2
[...]
Subject: Interactive Message
[...]
Write message body here and press Ctrl+D (EOF) to submit.
This way, messages can be on multiple lines.
? 3
[...]
Subject: Multimail
[...]
Body.
?
At this point, we can q[uit], so our messages automatically get saved in our home folder mbox file:
? quit
Saved 3 messages in /home/user1/mbox
Held 0 messages in /var/mail/user1
Thus, we can use mail –file with /home/user1/mbox and browse saved messages.
Should we use e[xit] or x[it] instead, no messages are moved to the user mbox. However, since spools are meant to be temporary, it’s usually a good idea to move messages to a more permanent location.
Of course, mail has many other features and a useful help system.
In this article, we talked about the mail system of Linux.
In conclusion, even though there are alternatives to mail, mailutils is usually preinstalled on many Linux distributions.