SMTP
SMTP
Simple Mail Transfer Protocol. The protocol email clients use to send outbound messages to mail servers, and that mail servers use to relay messages to each other. Defined in RFC 5321 (with extensions in many other RFCs). Dates to 1982.
SMTP is a one-way push protocol: you connect, you submit a message, you disconnect. Reading mail uses IMAP or POP3 — different protocol, different port.
Wire format
A line-based ASCII protocol. Client issues commands; server responds with 3-digit status codes.
S: 220 mail.example.com ESMTP Postfix
C: HELO client.example.com
S: 250 mail.example.com
C: MAIL FROM:<alice@example.com>
S: 250 OK
C: RCPT TO:<bob@example.com>
S: 250 OK
C: DATA
S: 354 End data with <CR><LF>.<CR><LF>
C: From: alice@example.com
C: To: bob@example.com
C: Subject: hi
C:
C: Hello, Bob.
C: .
S: 250 OK
C: QUIT
S: 221 Bye
The DATA block is the entire RFC 5322 message — headers, blank line, body. Encoded per MIME for anything richer than ASCII text.
Ports
- 25 — server-to-server relay. Most ISPs block outbound 25 from residential IPs to fight spam.
- 587 — message submission. Authenticated, supports STARTTLS upgrade. The standard port for clients to use.
- 465 — implicit TLS submission. Older but widely re-deployed.
- 2525 — common alternate when 587 is blocked.
Authentication
Modern SMTP submission requires authentication. Common mechanisms:
- PLAIN / LOGIN — username + password over TLS. Most common.
- CRAM-MD5 — challenge/response. Less common.
- OAuth2 (XOAUTH2) — Gmail, Outlook. The standard for modern providers. See OAuth for Email.
TLS modes
- STARTTLS — connection starts cleartext, client issues
STARTTLS, connection upgrades to TLS. Port 587. - Implicit TLS — TLS from the first byte. Port 465.
- Cleartext — only for test/dev. Real mail submission is always TLS-protected.
What mxr does
Per Mxr's crates/provider-smtp/src/lib.rs:
- Library:
lettre(async SMTP for Tokio). - Three TLS modes branched on port: 465 → implicit, 587 → STARTTLS, other → cleartext (test only).
- Auth optional but typically required:
Credentials::new(user, pass). Password comes from keychain via the config layer. - Message construction in
crates/outbound/src/email.rs: multipart/alternative with text+HTML, optional multipart/mixed wrapper for attachments. FreshMessage-ID: <uuid@domain>per send. Threading headers (In-Reply-To,References) populated from the draft.
Common pitfalls
- DKIM/SPF/DMARC — sending mail from your own domain requires these to be set up correctly or recipients (especially Gmail) treat your mail as spam. mxr doesn't help with this; it's domain configuration.
- Greylisting — server temporarily rejects with 4xx; client must retry later.
lettrehandles this transparently. - Connection drops mid-DATA — message may or may not have been accepted. Idempotency is the client's problem; usually solved by tracking sent messages with a unique Message-ID.
- Submission rate limits — providers throttle. Burst sends can get throttled or blocked.
SMTP vs alternatives
- POP3 / IMAP — for reading, not sending. Different protocols entirely.
- JMAP — newer (2019) JSON-RPC protocol for both sending and reading. Designed to replace SMTP+IMAP. Adoption is sparse outside Fastmail.
- Gmail / Microsoft Graph APIs — proprietary REST APIs that handle send. mxr uses Gmail's API for Gmail accounts; SMTP for everything else.
See also
- IMAP — the read counterpart
- MIME — the message body format SMTP carries
- OAuth for Email — modern auth for SMTP
- How Email Actually Works — synthesis
- Mxr — concrete reference implementation
- RFC 5321: https://datatracker.ietf.org/doc/html/rfc5321