SMTP (Simple Mail Transfer Protocol), defined in RFC 5321, is the internet standard for moving email from one server to another. While users typically interact with email through a client (Outlook, Gmail, Apple Mail), SMTP is the unseen engine that transports messages across the internet.
This post documents an actual SMTP submission session against a production mail server, command by command. Every line that crosses the wire is shown and explained.
Connecting with TLS
SMTP submission is always encrypted. On port 465 the connection is wrapped
in TLS from the first byte (implicit TLS). OpenSSL’s s_client connects
and handles the TLS handshake, then passes raw SMTP commands through the
encrypted channel:
$ openssl s_client -connect smtp.tinkmail.me:465 -crlf
On success, openssl prints certificate and handshake details. The first
SMTP line is the server greeting:
220 smtp.tinkmail.me ESMTP Service Ready
The 220 code means the service is ready. If the server were not
available, it would return a 421 temporary failure instead. (The full
response code taxonomy is covered in SMTP Response
Codes.)
Alternative — STARTTLS (port 587). Some servers use port 587 with the
STARTTLScommand to upgrade a plain-text connection to TLS after theEHLOhandshake. The SMTP commands are identical after encryption is established; only the connection preamble differs. Useopenssl s_client -starttls smtp -connect host:587 -crlffor that variant.
Server Capabilities: EHLO
The client announces itself with EHLO (Extended Hello), and the server
responds with its capabilities:
EHLO client.example.tinkmail.me
250-smtp.tinkmail.me
250-PIPELINING
250-SIZE 35882577
250-8BITMIME
250-AUTH LOGIN PLAIN
250-CHUNKING
250 SMTPUTF8
The 250 response is multi-line. Continuation lines use a dash (250-)
and the final line uses a space (250 ). (See SMTP Response
Codes for the full
multi-line format specification.)
The set of advertised extensions varies per server. A full reference for each capability — PIPELINING, SIZE, 8BITMIME, CHUNKING, SMTPUTF8, and others — is in SMTP Ports, Authentication & Extensions.
Authentication: AUTH LOGIN
Before accepting mail for relay, the server requires proof of identity. We
use AUTH LOGIN. The server issues base64-encoded challenges, and the
client responds with base64-encoded credentials:
C: AUTH LOGIN
S: 334 VXNlcm5hbWU6
VXNlcm5hbWU6 decodes to Username:. The client responds with the
username base64-encoded:
C: ZW1haWxAZXhhbXBsZS50aW5rbWFpbC5tZQ==
S: 334 UGFzc3dvcmQ6
ZW1haWxAZXhhbXBsZS50aW5rbWFpbC5tZQ== decodes to [email protected]. The server
responds 334 UGFzc3dvcmQ6 — Password:.
The client sends the password in the same fashion:
C: bXktdGVzdC1wYXNzd29yZA==
S: 235 2.7.0 Authentication successful
bXktdGVzdC1wYXNzd29yZA== decodes to my-test-password. The 235 code
confirms success. A 535 code would indicate authentication failure.
The wire exchange in full:
| Direction | Raw Wire | Decoded |
|---|---|---|
| Server | 334 VXNlcm5hbWU6 |
Username: |
| Client | ZW1haWxAZXhhbXBsZS50aW5rbWFpbC5tZQ== |
[email protected] |
| Server | 334 UGFzc3dvcmQ6 |
Password: |
| Client | bXktdGVzdC1wYXNzd29yZA== |
my-test-password |
Base64 provides no secrecy.
echo ZW1haWxAZXhhbXBsZS50aW5rbWFpbC5tZQ== | base64 -dreveals the username instantly. The security of this exchange depends entirely on the TLS layer. Without TLS, credentials are exposed in plain text to any observer on the network path.
Message Envelope and Content
After authentication, the SMTP envelope is defined with MAIL FROM
(sender) and RCPT TO (recipient). The envelope is distinct from the
message headers — the envelope is consumed by the SMTP protocol itself,
while headers travel inside the message body and are visible to the
recipient.
C: MAIL FROM: <[email protected]>
S: 250 2.1.0 Ok
C: RCPT TO: <[email protected]>
S: 250 2.1.5 Ok
A 250 response means the server has accepted the envelope. If the
recipient domain were not handled by this server, it would return 550
(mailbox not found) or 551 (user not local).
DATA: Headers vs. Body
The DATA command signals that the message content follows. The server
responds with 354 and waits for the complete message, terminated by
\r\n.\r\n (CRLF + dot + CRLF):
C: DATA
S: 354 End data with <CR><LF>.<CR><LF>
C: From: Sender Name <[email protected]>
C: To: Recipient Name <[email protected]>
C: Subject: SMTP Protocol Demonstration
C: Date: Mon, 28 Jul 2026 14:30:00 +0000
C: Message-ID: <[email protected]>
C: MIME-Version: 1.0
C: Content-Type: text/plain; charset=UTF-8
C: Content-Transfer-Encoding: 7bit
C:
C: This is the message body.
C:
C: Headers above the blank line describe the message metadata.
C: Everything below the blank line is the body content.
C:
C: The message ends with a single dot on its own line.
C: .
S: 250 2.0.0 Ok: queued as 4XpYqZ0v9TzB1kR
The structure is rigid:
headers ← one or more [RFC 5322](https://datatracker.ietf.org/doc/html/rfc5322) header fields, each ending with CRLF
← empty line (CRLF alone) — REQUIRED separator
body ← arbitrary text, terminated by CRLF.CRLF
Headers are structured lines in Field-Name: value format. Common
header fields include From:, To:, Subject:, Date:, Message-ID:,
MIME-Version:, Content-Type:, and Content-Transfer-Encoding. Headers
may span multiple lines by starting continuation lines with whitespace
(folding, RFC 5322 Section 2.2.3).
Body follows the blank line and is whatever the sender chooses. For
multipart content (MIME), the Content-Type header declares a boundary
string that delimits the parts. The SMTP layer does not interpret the
body — it transports it as opaque data.
The 250 2.0.0 Ok: queued as 4XpYqZ0v9TzB1kR response confirms that the
server has accepted the message and assigned it a queue identifier. This
does not mean the message has been delivered to the recipient — only
that it has been handed off to the server’s outbound processing pipeline.
Session Termination
C: QUIT
S: 221 2.0.0 Bye
The 221 response confirms the server is closing the connection. Any
client that does not send QUIT leaves the server to time out the
connection, which wastes server resources.
Post-Queuing: What Happens After 250
The queued as response is the last SMTP interaction, but the message’s
journey is far from over. The server’s internal pipeline proceeds as
follows:
-
Queue insert — The message is written to persistent storage (typically a disk-based queue in Maildir or a database). The queue ID (
4XpYqZ0v9TzB1kR) is the server’s internal reference for tracking, logging, and potential retries. -
Spam and virus scanning — The message content is analysed by the server’s filtering pipeline before it is accepted for relay.
-
DNS resolution — The server extracts the recipient domain (
tinkmail.me), queries its MX record, and resolves the target MTA’s IP address. -
Outbound relay — A new SMTP connection is opened to the target MTA on port 25, and the message is transmitted through the same command sequence (
EHLO,MAIL FROM,RCPT TO,DATA,QUIT) that was just performed by the original client. -
Delivery notification — If the target MTA accepts the message (
250), the queue entry is removed. If a temporary failure (4xx) occurs, the message remains in the queue for retry with exponential backoff. A permanent failure (5xx) generates a bounce message back to the sender.
This pipeline is explored in detail in The SMTP Email Journey.
Complete Session Transcript
$ openssl s_client -connect smtp.tinkmail.me:465 -crlf
# ... TLS handshake output omitted ...
220 smtp.tinkmail.me ESMTP Service Ready
EHLO client.example.tinkmail.me
250-smtp.tinkmail.me
250-PIPELINING
250-SIZE 35882577
250-8BITMIME
250-AUTH LOGIN PLAIN
250-CHUNKING
250 SMTPUTF8
AUTH LOGIN
334 VXNlcm5hbWU6
ZW1haWxAZXhhbXBsZS50aW5rbWFpbC5tZQ==
334 UGFzc3dvcmQ6
bXktdGVzdC1wYXNzd29yZA==
235 2.7.0 Authentication successful
MAIL FROM: <[email protected]>
250 2.1.0 Ok
RCPT TO: <[email protected]>
250 2.1.5 Ok
DATA
354 End data with <CR><LF>.<CR><LF>
From: Sender Name <[email protected]>
To: Recipient Name <[email protected]>
Subject: SMTP Protocol Demonstration
Date: Mon, 28 Jul 2026 14:30:00 +0000
Message-ID: <[email protected]>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 7bit
This is the message body.
Headers above the blank line describe the message metadata.
Everything below the blank line is the body content.
The message ends with a single dot on its own line.
.
250 2.0.0 Ok: queued as 4XpYqZ0v9TzB1kR
QUIT
221 2.0.0 Bye
Protocol Summary
| Phase | Commands | Purpose |
|---|---|---|
| Connection | TCP handshake + TLS | Establish encrypted channel to port 465 (or 587 with STARTTLS). |
| Greeting | Server → 220 |
Server announces readiness. |
| Capabilities | EHLO → 250-... |
Client learns server extensions. |
| Authentication | AUTH LOGIN → 235 |
Client proves identity via SASL. |
| Envelope | MAIL FROM + RCPT TO |
Define sender and recipient for the transport layer. |
| Data Transfer | DATA → 354 … 250 |
Transmit message headers and body. |
| Cleanup | QUIT → 221 |
Graceful session end. |
From here, the next post in this series follows the message through the full relay chain — MX resolution, MTA-to-MTA transfer, inbound filtering, and mailbox delivery.