SMTP#
SMTP (Simple Mail Transfer Protocol, RFC 5321) is how email moves
between servers and from mail clients to their submission server.
It’s a plaintext, line-oriented protocol that has barely changed in
40 years; the same HELO, MAIL FROM, RCPT TO, DATA,
QUIT verbs your laptop sends today were defined in RFC 821 in
1982. What’s been bolted on top (TLS, authentication, SPF, DKIM,
DMARC) is what makes modern mail mostly trustworthy.
Three ports matter:
Port |
Role |
|---|---|
25 |
Server-to-server relay. No authentication, plaintext + STARTTLS. Most ISPs block outbound 25 for residential. |
587 |
Submission: client-to-server (RFC 6409). Always authenticated, almost always STARTTLS. |
465 |
Implicit-TLS submission (“SMTPS”). Deprecated, then re-blessed (RFC 8314). Common alongside 587. |
Conversation#
A minimal SMTP delivery, end to end:
sequenceDiagram
participant C as Client / MTA
participant S as Server (port 25)
S-->>C: 220 mx.example.com ESMTP
C->>S: EHLO sender.example.org
S-->>C: 250-mx.example.com<br/>250-STARTTLS<br/>250 SIZE 52428800
C->>S: STARTTLS
S-->>C: 220 Ready to start TLS
Note over C,S: TLS handshake
C->>S: EHLO sender.example.org
S-->>C: 250 ...
C->>S: MAIL FROM:<alice@sender.example.org>
S-->>C: 250 Sender OK
C->>S: RCPT TO:<bob@example.com>
S-->>C: 250 Recipient OK
C->>S: DATA
S-->>C: 354 Send message
C->>S: From: ...<br/>Subject: ...<br/><br/>body<br/>.
S-->>C: 250 OK queued as 0123ABC
C->>S: QUIT
S-->>C: 221 Bye
Status codes follow the 2xx / 4xx / 5xx pattern: 2xx success, 4xx temporary failure (try again), 5xx permanent (don’t retry).
Code |
Meaning |
|---|---|
|
Service ready (initial banner, after STARTTLS) |
|
OK (any successful step) |
|
Start mail input (response to |
|
Service not available (temporary; close connection) |
|
Mailbox unavailable (temporary) |
|
Insufficient storage (temporary; over quota) |
|
Mailbox unavailable / rejected (permanent) |
|
Transaction failed (permanent; spam, blocklist, etc.) |
Manual probe#
The minimum check: can you reach the server, what does it support, and does its TLS work.
# banner only
$ nc -v mx.example.com 25
# probe with STARTTLS upgrade and inspect the TLS cert
$ openssl s_client -connect mx.example.com:25 -starttls smtp
$ openssl s_client -connect submission.example.com:587 -starttls smtp
$ openssl s_client -connect submission.example.com:465 # implicit TLS
Inside s_client you can drive a full SMTP conversation by hand:
EHLO testclient
AUTH LOGIN
<base64-username>
<base64-password>
MAIL FROM:<me@x>
RCPT TO:<you@y>
DATA
Subject: hello
.
QUIT
Send + debug#
swaks is the operator’s standard SMTP client; one binary, every option:
$ swaks --to bob@example.com --from alice@example.org \
--server smtp.example.org:587 \
--auth-user alice --auth-password 'p@ss' \
--tls
$ swaks --to bob@example.com --server mx.example.com \
--header "Subject: ping" --body "test"
# full TLS + DKIM-aware send via msmtp / sendmail / mailx
$ echo "hello" | mail -s "ping" bob@example.com
Anti-spoofing#
The DNS records every operator should know how to read:
Record |
Purpose |
|---|---|
SPF |
TXT record listing IPs allowed to send for a domain;
receiving MTAs reject mismatches. Lookup:
|
DKIM |
Public key in DNS ( |
DMARC |
Policy on top of SPF + DKIM
( |
$ dig +short TXT example.com # SPF
$ dig +short TXT default._domainkey.example.com # DKIM (selector varies)
$ dig +short TXT _dmarc.example.com # DMARC
Postfix server#
The default MTA on most Linuxes; key files:
Path |
Purpose |
|---|---|
|
Main configuration; listeners, TLS, relay restrictions, hostname. |
|
Per-listener config (e.g. |
|
Mail queues (incoming, active, deferred, corrupt, hold). |
|
Operations log (Debian / RHEL paths). |
|
$ sudo systemctl status postfix
$ mailq # show the queue
$ sudo postqueue -f # flush deferred queue
$ sudo postsuper -d <queue-id> # delete a stuck message
$ postconf -n # non-default config