💾 Archived View for gemini.circumlunar.space › users › kraileth › neunix › eerie › 2018 › intro_to_e… captured on 2022-01-08 at 14:46:59. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2021-12-05)

-=-=-=-=-=-=-

Here I'm republishing an old blog post of mine originally from April 2018. The article has been slightly improved.

Don't look for part 3 - I started writing it but never completed the article.

Introduction to email (pt. 2): Mail dialog / the "mail" command

The first post of the series discussed some fundamental general knowledge about email (daemons involved, protocols, etc.). It also covered building a test system for actively trying out mail-related things. (I had to update it, however, since I discovered some problems with building the VM.)

Introduction to email (pt. 1): Email basics

I assume that you've built the test system with Vagrant to follow along. If you haven't, please refer back to the previous post to learn how to do this. You're free to use any FreeBSD system of course. Using vagrant has a few advantages, though. The most important is that it allows you to save the state so you can continue to play with your VM while still being able to return to the clean state anytime to follow the next parts of this series. This post will demonstrate how to send mail from the console and point out a few important things involved.

Sending mail with... "mail"

Change to the appropriate directory where you keep your Vagrant file for the mail-vm. If you've tinkered with the VM after the first post, reset it to the last state (if it hasn't changed, you may issue _vagrant up_ instead of restoring the snapshot) and enter the VM:

% cd ~/vagrant/mail-vm
% vagrant snapshot restore mail1
% vagrant ssh

Thanks to the changes we made to the config in the previous post, you should be directly logged in as root. Let's see if root has any mail. As part of FreeBSD's base system comes the _mail_ utility which is a very basic MUA able to compose and view messages. Execute it without any parameters for now:

# mail
No mail for root

Ok, so root does not currently have any messages. On an average FreeBSD system there'd probably be something there as by default the system reports in for e.g. a daily _security run output_. But on this system there's nothing so far. So let's send a message now! We can also use _mail_ for that. With the _-s_ parameter we can specify the subject and of course we need to tell it who we're sending the message to! When we did that, the program will let us type in the actual message. To indicate that we're done, we need to place a single period (.) in line all by itself and hit the return key:

# mail -s "Test mail 1" root
This is a test message!
.
EOT

Mail acknowledged the action by printing _EOT_ (end of text). Congratulations, you've just sent an email from root to root! And yes, this is the same kind of email that you know from writing to other people, only done locally in this case.

Hard to believe? Let's do it again and make use of something else that you know from email: Sending a carbon copy (cc) to another user:

# mail -s "Test mail 2" root -c vagrant
This is another test message!
.
EOT

All done! But did it actually do what we wanted it to? Let's become the vagrant user and check our mail real quick:

# su -l vagrant
% mail
>N 1 root@mail-vm.local Fri Apr 20 20:56 19/719 "Test mail 2"

Nice: There it is! Mail obviously found a message with the subject "Test mail 2" that was sent by root@mail-vm.local. Looks good so far. Let's quit the _mail_ utility by pressing CTRL-D or issuing the command _x_.

Sending and checking mail with - mail (PNG)

The mail dialog

What's next? How about sending an email message back to root - and this time tell mail to be verbose?

% mail -v -s "Test mail 3" root
And yet another!
.
EOT

This time our mail utility shows what's usually happening in the background: The mail dialog! This is basically what the MUA and the MTA are talking to make mail delivery happen.

Beginning of a mail dialog (PNG)

Let's take a closer look at some snippets:

[...]
root... Connecting to [127.0.0.1] via relay...
220 mail-vm ESMTP Sendmail 8.15.2/8.15.2; Fri, 20 Apr 2018 20:59:15 +0200 (CEST)
>>> EHLO mail-vm.local
250-mail-vm.local Hello localhost [127.0.0.1], pleased to meet you
[...]

Here we can see the beginning of the dialog: Our MUA (_mail_) connected to the MTA (_Sendmail_ in this case), said "hello" (or rather _EHLO_ according to the protocol rules) and was greeted by the MTA, too. We'll skip the next bits; client and server agree on various parameters to upgrade their connection to use encryption instead of plain text. While encryption is definitely an important topic when it comes to mail, it also makes things a fair bit more complicated and we'll ignore it for now.

MAIL From: SIZE=48
250 2.1.0 ... Sender ok
>>> RCPT To:
>>> DATA
250 2.1.5 ... Recipient ok
354 Enter mail, end with “.” on a line by itself
>>> .

The MUA announces the sender and the MTA acknowledges it. Then the MUA tells the MTA the recipient as well as the actual message and the latter acknowledges it again.

250 2.0.0 w3KIxFbt000881 Message accepted for delivery
root... Sent (w3KIxFbt000881 Message accepted for delivery)
Closing connection to [127.0.0.1]
>>> QUIT
221 2.0.0 mail-vm.local closing connection

Finally the MTA tells the MUA that it accepted the message and will take care of delivering it. And that concludes the mail sending action from the perspective of the MUA. The MTA has taken over and will do _something_ with the message.

What you've been reading here is an example of what an _SMTP dialog_ looks like. If the MTA figures that the message cannot be delivered locally, it will try to connect to another MTA and pass the message on using the same protocol. And if it cannot deliver the message at all (e.g. the remote MTA rejected the message, probably because the recipient user does not exist), the MTA is probably configured to send a message to the original sender, letting him know that the message was lost.

Using mail to view messages

We're done with the vagrant user for now so let's exit back to root:

% logout

Root should have received three mails. We can use the mail command again to look at our mailbox:

# mail

The result will look like on the bottom of this picture:

Second part of the SMTP dialog & checking root's unread mail (PNG)

Right, all three were received and are there. Sendmail obviously did its job after taking over the messages from our MUA! Mail also tells us that we have three messages in total of which three are new. And it mentions _/var/mail/root_. What's that? Well, it's a file. But let's quit the MUA again and take a closer look:

# less /var/mail/root

Messages in the inbox file (PNG)

What we've stumbled across here is the root user's mailbox for incoming mail ("inbox"). It's just a file holding the text and headers of all unread messages. Alright, all the messages are there and can be accessed by all means that you typically access text files with. But what about mail? Can you use it to view the messages, too? You bet that's possible. Let's run _mail_ once again:

# mail

Do you see a difference? No? Look more closely! Last time all three messages had an uppercase "N" in front of them, meaning _new_. Now there's a "U": Those messages are still _unread_, but they were already in the inbox last time we checked our mail.

The greater-than sign hints that mail 1 is selected. To read it, issue the command "print" (or use the abbreviation "p"). The _plus_ character selects the next message, while _minus_ does the opposite. If you'd like to play around with the mail MUA a little, you should know that there are many more commands like e.g. "f" to print the current message header. Should you want to know more, the manpage is your friend.

Viewing messages with mail (PNG)

If we exit now, this is what _mail_ tells us:

Saved 2 messages in mbox
Held 1 message in /var/mail/root

What does that mean?

Inbox and mbox

If you like analogies, think of _/var/mail/root_ as the mailbox outside of your house. If you get new mail, it'll be put into there. Let's say you got three letters. The analogy to what we did a minute ago was going to the mailbox and taking only two of the letters out to read them. After we read them we put them somewhere were we use to stash our letters as long as we think that we might need them again. The same thing happened here: There's one message "held" in /var/mail/root because we didn't bother to touch it, yet. The other two were moved to the "mbox".

Ok, what's the _mbox_? It's another file that holds email messages. Actually there's not much different about it compared to the inbox. It's just used differently: To locally store your mail whereas your inbox is typically on a remote system. In our case both are on the same system and so it's just removing a message from one file and putting it in another.

# head -21 ~/mbox

Here you can see the first message and the beginning of the second one (in line 21):

Contents of our mbox (PNG)

Replying to and deleting messages

If we start _mail_ again we know how to view the one remaining message. What else could we do with it? Well, we could reply to it ("r") and then delete ("d") it afterwards:

Replying to and deleting a message (PNG)

That wasn't too hard, was it? Asking _mail_ for the headers returns _no applicable messages_. Now root's inbox should be empty. Let's run _mail_ again. What's that? A new message? Checking back at what we just did, it looks like we sent the reply to both vagrant _and_ root. We didn't mean to receive this message so let's delete it, too.

Alright. Our inbox should now really be clean. Is it? Let's put it to the test:

# mail
No mail for root

It is!

Emptying the inbox again (PNG)

Excellent. But... How do we access the messages that we didn't delete which were moved to the mbox? As I said before, the mbox really is only functionally different from the inbox. In fact the inbox is merely a special mbox. On our system it's special in being the default that _mail_ works with unless told otherwise!

Of course we can tell mail to operate on root's mbox instead. This is done by using "-f":

# mail -f /root/mbox

And there are our messages. No magic going on here.

Accessing root's mbox (PNG)

Intermission

That's it for this article on mail. You should now have a much better understanding of what is happening when a message is being sent - and what a message actually is. Also you've met an old Unix tool that probably isn't going to become your favorite MUA but still gets the job done after several decades. And while it's not very intuitive, it just helped you to get started in better understanding email. Also it might actually still well suffice for some simple tasks. In fact we've only scratched the surface of the _mail_ utility. It can do much, much more. But that's too special a topic and way beyond the goal of this series on email.

You've come to the end of part two. If you've been following along with your Vagrant VM, stop it now, make sure that it's powered off and create a second snapshot:

# shutdown -p now
% vagrant status
% vagrant snapshot save mail2

Until next time!

BACK TO 2018 OVERVIEW