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

220

Service ready (initial banner, after STARTTLS)

250

OK (any successful step)

354

Start mail input (response to DATA)

421

Service not available (temporary; close connection)

450

Mailbox unavailable (temporary)

452

Insufficient storage (temporary; over quota)

550

Mailbox unavailable / rejected (permanent)

554

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: dig +short TXT example.com.

DKIM

Public key in DNS (selector._domainkey.example.com); sender signs headers + body with the matching private key, receivers verify the signature.

DMARC

Policy on top of SPF + DKIM (_dmarc.example.com); tells receivers whether to quarantine / reject misaligned mail and where to send aggregate reports.

$ 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

/etc/postfix/main.cf

Main configuration; listeners, TLS, relay restrictions, hostname.

/etc/postfix/master.cf

Per-listener config (e.g. submission on 587 with SASL).

/var/spool/postfix/

Mail queues (incoming, active, deferred, corrupt, hold).

/var/log/mail.log /

Operations log (Debian / RHEL paths).

/var/log/maillog

$ 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

See also#

  • DNS, MX / SPF / DKIM / DMARC records.

  • SSL/TLS, STARTTLS and certificate handling for SMTP.

  • man postfix, man swaks, man postqueue, man postconf.

  • RFC 5321 (SMTP), RFC 6409 (submission), RFC 7208 (SPF), RFC 6376 (DKIM), RFC 7489 (DMARC).