Module 1 · 1.2
English
SMTP: the conversation between mail servers
Module 1: How email works · Reading time: 10 minutes
Learning objective: After this lesson, you'll be able to read an SMTP conversation, explain what EHLO, MAIL FROM, RCPT TO and DATA do, and tell from a response code whether an error is temporary or permanent.
Key concepts: SMTP (RFC 5321), session, EHLO/HELO, MAIL FROM, RCPT TO, DATA, QUIT, response code (2xx, 3xx, 4xx, 5xx), extended status code, extensions (STARTTLS, AUTH, SIZE), null MX
A conversation in plain text
SMTP is a very old protocol (the first version dates from 1982) and is therefore very readable. Two servers send each other lines of text. The sender (the client) sends a command, the recipient (the server) replies with a three digit number and a short explanation. You can read such a conversation back literally in an error message or log, which is exactly why it pays to understand it.
Below is a complete conversation. S: is the receiving server, C: the sending server. The mail goes from anna@example.com to jan@example.net.
S: 220 mx1.mailprovider.example ESMTP ready
C: EHLO out.hosting.example
S: 250-mx1.mailprovider.example Hello out.hosting.example [192.0.2.25]
S: 250-SIZE 52428800
S: 250-8BITMIME
S: 250-STARTTLS
S: 250 SMTPUTF8
C: STARTTLS
S: 220 2.0.0 Ready to start TLS
(from this point the connection is encrypted; the client sends EHLO again)
C: EHLO out.hosting.example
S: 250 ...
C: MAIL FROM:<anna@example.com> SIZE=24310
S: 250 2.1.0 Ok
C: RCPT TO:<jan@example.net>
S: 250 2.1.5 Ok
C: DATA
S: 354 End data with <CR><LF>.<CR><LF>
C: From: Anna <anna@example.com>
C: To: Jan <jan@example.net>
C: Subject: Offerte
C: Date: Sun, 8 Nov 2026 10:15:00 +0100
C: Message-ID: <a1b2c3@example.com>
C:
C: Hoi Jan, hierbij de offerte.
C: .
S: 250 2.0.0 Ok: queued as 4F2A1B
C: QUIT
S: 221 2.0.0 ByeThe commands one by one
| Command | Meaning | Note |
|---|---|---|
| (connecting) | The server greets with 220 and its name. | This is called the banner. If the server immediately says 554, it doesn't want to talk to your IP at all (often a blocklist). |
EHLO name | "Hello, I am out.hosting.example." The server replies with the extensions it knows. | The name should be the real name of the sending server, preferably matching its PTR record (lesson 5.1). HELO is the old variant without extensions. |
STARTTLS | "Let's encrypt from now on." | Only if the server offers it. Between servers this is usually optional (lesson 5.4). |
MAIL FROM:<address> | The envelope sender: error messages go here. | This later becomes the Return-Path header. SPF checks this address. Servers use an empty sender <> for their own error messages, so a bounce never produces a bounce. |
RCPT TO:<address> | The recipient. May appear multiple times, one per recipient. | The server should already say here whether the address exists. A 550 5.1.1 at this point is a clean, immediately recognisable error. |
DATA | "Now the mail itself follows." The server replies 354. | After this come the header fields, a blank line and the text. A line with just a full stop ends it. |
QUIT | End of conversation. |
The key insight: everything before DATA is the envelope, everything after DATA is the content. What's in MAIL FROM and what's in the From: header are supplied separately and don't need to match. The server delivers based on RCPT TO; the To: line in the content plays no role in delivery.
The response codes
The first digit of the code is the most important:
| Starts with | Meaning | What does the sender do? |
|---|---|---|
| 2 | Success. | Move on to the next step. 250 after DATA means: the server has accepted the mail and is now responsible for it. |
| 3 | Go ahead, I'm waiting for more. | Only with 354 after DATA (and when logging in). |
| 4 | Temporary error: not now, try later. | Mail stays in the queue and is offered again later. |
| 5 | Permanent error: this isn't going to work. | Sender gives up and sends an error message (bounce) to the envelope sender. |
Behind the three digits, modern servers add an extended status code in the form class.subject.detail (RFC 3463), for example 5.1.1. The first digit is again 2, 4 or 5. The second digit says what it's about: 1 = address, 2 = mailbox, 3 = mail system, 4 = network and routing, 5 = protocol, 6 = content, 7 = security and policy. A few you'll often see:
550 5.1.1 The email account that you tried to reach does not exist
452 4.2.2 Mailbox full (temporary)
552 5.3.4 Message size exceeds fixed limit
451 4.7.1 Greylisted, please try again later
550 5.7.1 Message rejected (policy: spam, blocklist, DMARC)In module 6 you'll learn to read a complete bounce and find a table with the most common codes.
Why temporary and permanent matters so much
A server that's unsure often replies with a 4xx. A well known example is greylisting: a server that doesn't yet know a sender says "try again later" the first time. A genuine mail server will come back after a few minutes; many spam programs won't. Large recipients also use 4xx to slow things down when they don't yet trust an IP address. For you as a sender, this means a delay, but not a loss. The system usually sorts itself out.
A 5xx is different. There, the sender won't try again. If you get a 5xx back, someone needs to change something: the address, the content, or the settings of the sending domain.
One pitfall: some servers give a 5xx while the problem is actually temporary (for example a full mailbox, 552 5.2.2), and others give a 4xx for something that will never succeed. So always read the text behind the code, not just the number.
Who is responsible?
After 250 on the full stop ending DATA, responsibility lies with the receiving server. If it then fails to put the mail in the mailbox, it must send back an error message itself. That's the source of a tricky phenomenon: backscatter. A server that accepts everything first and only later discovers the address doesn't exist sends a bounce to the envelope sender. If that was forged by a spammer, an innocent third party receives the bounce. That's why servers should reject what can't be delivered already at RCPT TO (see also catch-all in lesson 3.3).
In practice: seeing SMTP in your own environment
An ordinary user rarely sees the whole SMTP conversation, but does see it in pieces:
- a bounce contains the last line of the conversation, for example
Remote-MTA: mx1.mailprovider.exampleandDiagnostic-Code: smtp; 550 5.1.1 ...; - the header fields of a received mail include, for each server, a
Received:line with the EHLO name and IP address (lesson 1.5); - in a panel with a mail log, such as E-mail Tracking in DirectAdmin at WebOké, you see the receiving server's response for each message. With other providers this is called something like message tracking or mail log, and the content is similar.
So you don't need to connect to a mail server yourself to be able to read this. If you'd like to try anyway: with openssl s_client -starttls smtp -connect server:25 you can hold the conversation by hand, but many home internet providers block outgoing traffic on port 25 (lesson 1.4).
Summary
- SMTP is a readable conversation: EHLO, (STARTTLS), MAIL FROM, RCPT TO, DATA, QUIT.
- Everything before DATA is the envelope (delivery and error messages), everything after is the content with the header fields you see.
- 2xx = success, 4xx = temporary (try again later), 5xx = permanent (bounce).
- The extended code
X.Y.Ztells you what it's about; X.1 address, X.2 mailbox, X.7 policy and security. - Always read the text behind the code; servers aren't always consistent.
Quiz
Exercise
Exercise Z1.2: A domain that doesn't receive mail. Look up the MX records for example.com. Fill in what you find and choose what a sending server does with mail for info@example.com: (a) deliver to the server with priority 0, (b) try the A record, (c) give up immediately, or (d) try again later. The program looks up the MX record live and checks your answer.
Further reading
The steps in these articles apply to the panels at WebOké; with other providers it works similarly.
- How sending email works / SMTP
- Mail delivery failed: how to read the error message and what the codes mean
- DirectAdmin guide 9.3: E-mail Tracking: where did my mail go?
- RFC 5321 (SMTP), sections 3 and 4.2 (response codes); RFC 3463 (extended status codes); RFC 7505 (null MX)
