The three mail protocols, at the telnet level
◈ 4 cardsSMTP pushes mail, POP3 downloads it, IMAP synchronises it — plus an SMTP session read command by command, and why the envelope rather than the headers decides who actually receives a message.
Three protocols, and the direction each one runs
Email is not one protocol, it is three, and picking the wrong one for the job is the first thing that goes wrong in Assignment 4.
SMTP (Simple Mail Transfer Protocol, RFC 5321) is the push protocol. It carries a message from your program to your outgoing server, and from that server onward to the next, until the message lands in somebody's mailbox. It only ever moves mail forward. There is no SMTP command that means "give me my mail".
POP3 (Post Office Protocol version 3, RFC 1939) is the older pull protocol. A client connects, sees a flat numbered list of whatever is sitting in one mailbox, downloads what it wants, and — by default in most clients — deletes it from the server. The canonical copy ends up on your machine.
IMAP (RFC 3501) is the other pull protocol and it inverts that. The canonical copy stays on the server and the client manipulates it in place: named folders, per-message flags, server-side search, fetching a header or a single MIME part without downloading the rest. Two devices looking at one IMAP account see the same state, because there is only one state.
So an Assignment 4 program uses SMTP to send and IMAP (or POP3) to read. Never one protocol for both.
SMTP is a line protocol you can read
Every SMTP exchange is ASCII lines terminated by CRLF. The client sends a command, the server answers with a three-digit reply code and some text. The first digit is the part that matters:
- 2xx — done, carry on.
- 3xx — accepted so far, now send the rest (in practice, only
354afterDATA). - 4xx — temporary failure; the same request may succeed later, so a real mail server queues and retries.
- 5xx — permanent failure; retrying changes nothing.
That 4xx/5xx split is the whole reason mail is reliable without being synchronous: a 450 means "your message still exists, come back", a 550 means "this address does not exist, tell the sender".
The envelope is not the headers
This is the idea worth the lesson. A message on the wire has two independent layers.
The envelope is the MAIL FROM and RCPT TO commands. This is what servers route on: one RCPT TO per recipient, and delivery is decided entirely here.
The headers — From:, To:, Cc:, Subject: — are the first lines inside DATA, above a blank line. They are display data. No server reads them to decide where the message goes.
Nothing forces the two layers to agree. That is why a message can arrive addressed to a list you are not on, and why forging a From: line is trivial.
The consequence for blind carbon copy is exact: there is no Bcc: header on the wire. A blind recipient is one extra RCPT TO and nothing else. If you write a Bcc: header into DATA, every recipient receives it and can read the entire blind list — the precise failure the feature exists to prevent.
Worked example — one SMTP session, command by command
Dana sends one message to Sam, with a blind copy to Quiet. C: is the client, S: is the server.
S: 220 smtp.example.net ESMTP ready
C: EHLO client.example.org
S: 250-smtp.example.net
S: 250-STARTTLS
S: 250 AUTH PLAIN LOGIN
C: MAIL FROM:<dana@example.org>
S: 250 2.1.0 Ok
C: RCPT TO:<sam@example.net>
S: 250 2.1.5 Ok
C: RCPT TO:<quiet@example.net>
S: 250 2.1.5 Ok
C: DATA
S: 354 Start mail input; end with <CRLF>.<CRLF>
C: From: dana@example.org
C: To: sam@example.net
C: Subject: lab notes
C:
C: Numbers attached tomorrow.
C: .
S: 250 2.0.0 Ok: queued
C: QUIT
S: 221 2.0.0 Bye
Read the shape. EHLO is a greeting that also asks what the server can do — the multi-line 250- replies are its extension list, and STARTTLS and AUTH appearing there is how a client learns it may encrypt and log in. Two RCPT TO commands go out, so two mailboxes will receive the message. Inside DATA only one of them is named. The blank line after Subject: is what separates headers from body, and the lone . on its own line ends the message.
Quiet is in the envelope and absent from the headers. That gap, and nothing else, is what BCC means.