← All posts

Have you ever thought how email works?

One click on Send, six hops, five DNS records and a handshake in plain text.

You press Send and a second later it lands on the other side of the world. Here is the whole journey: SMTP, the servers it passes through, and the DNS records (MX, SPF, DKIM, DMARC) that decide whether it reaches the inbox or the spam folder.

Email is older than the web. The first message between two computers was sent in 1971, and the protocol that still carries almost every email today, SMTP, was written down in 1982. It was designed for a small network of people who trusted each other.

That is why modern email is a stack of fixes on top of a simple, trusting core. Once you see the layers, deliverability problems stop being a mystery.

The journey, hop by hop

Say Asha at asha@sender.com writes to Ravi at ravi@receiver.com. This is what happens after she presses Send.

  1. 1Mail appAsha writes and presses Send (Gmail, Outlook, a phone app)
  2. 2Outgoing serverHer app logs in and hands the message over on port 587
  3. 3DNS lookupHer server asks: what is the MX record for receiver.com?
  4. 4Receiving serverIt connects to that server on port 25 and speaks SMTP
  5. 5ChecksSPF, DKIM and DMARC decide: inbox, spam or reject
  6. 6MailboxRavi’s app fetches it over IMAP and shows it

The cast: MUA, MSA, MTA, MDA

Mail people use four short names for the pieces in that journey. They are worth knowing because every error message uses them.

Who does what
NameStands forWhat it doesExample
MUAMail User AgentThe app you read and write mail inGmail web, Outlook, Apple Mail
MSAMail Submission AgentAccepts mail from your app after you log in (port 587/465)smtp.gmail.com
MTAMail Transfer AgentRelays mail from server to server over SMTP (port 25)Postfix, Exim, Microsoft Exchange
MDAMail Delivery AgentFiles the message into the right mailboxDovecot

SMTP: a conversation in plain text

SMTP is a polite, line-by-line conversation. The sending server says who it is, who the mail is from and who it is for, then sends the message, ending with a line containing a single dot. Every reply starts with a number: 2xx means fine, 3xx means go on, 4xx means try again later, 5xx means no.

S: 220 mx.receiver.com ESMTP ready
C: EHLO mail.sender.com
S: 250-mx.receiver.com Hello
S: 250 STARTTLS
C: STARTTLS
S: 220 Ready to start TLS
   … the rest is encrypted …
C: EHLO mail.sender.com
S: 250 mx.receiver.com Hello
C: MAIL FROM:<asha@sender.com>
S: 250 OK
C: RCPT TO:<ravi@receiver.com>
S: 250 OK
C: DATA
S: 354 End data with <CR><LF>.<CR><LF>
C: From: Asha <asha@sender.com>
C: To: Ravi <ravi@receiver.com>
C: Subject: Lunch on Friday?
C:
C: Are you free at 1?
C: .
S: 250 OK: queued as 4F2A9
C: QUIT
S: 221 Bye
One SMTP delivery
Sending serverReceiving server220 readyEHLO mail.sender.com250 · STARTTLS offeredSTARTTLSnow encryptedMAIL FROM · RCPT TO250 OKDATA … message … .250 queuedQUITSending serverReceiving server220 readyEHLO mail.sender.com250 · STARTTLS offeredSTARTTLSnow encryptedMAIL FROM · RCPT TO250 OKDATA … message … .250 queuedQUIT

The envelope and the letter

Notice there are two "from" addresses. MAIL FROM is the envelope: where bounces go, used by servers. The From: line inside the message is the letter: what the reader sees. SMTP never required them to match, which is exactly how spoofing works, and exactly what SPF, DKIM and DMARC were invented to close.

The DNS records behind every email

Everything above depends on a handful of records in the domain’s DNS. These are the ones that matter, with an example for sender.com.

Email DNS records
RecordWhereExample valueWhat it says
MXsender.com10 mx1.mailhost.comSend mail for this domain to this server. Lower number = tried first.
Amx1.mailhost.com203.0.113.10The IP address of that mail server.
SPF (TXT)sender.comv=spf1 include:_spf.mailhost.com ~allThese servers are allowed to send as this domain.
DKIM (TXT)s1._domainkey.sender.comv=DKIM1; k=rsa; p=MIIBIjAN…The public key to check this domain’s signatures.
DMARC (TXT)_dmarc.sender.comv=DMARC1; p=quarantine; rua=mailto:dmarc@sender.comIf checks fail, do this, and send reports here.
PTR10.113.0.203.in-addr.arpamx1.mailhost.comReverse DNS: the IP names itself, and the name points back.

SPF: who is allowed to send

SPF is a list of servers allowed to send mail for your domain, published as a TXT record. The receiving server takes the domain from MAIL FROM, looks up its SPF record and checks whether the connecting IP is on the list.

The ending matters: -all means reject anything else, ~all means treat it as suspicious. An SPF record may trigger at most 10 DNS lookups, and every include: counts, so adding one more email tool can quietly break it.

DKIM: a signature that survives the trip

DKIM signs the message itself. The sending server hashes the important headers and the body, signs the hash with a private key, and adds a DKIM-Signature header naming the domain (d=) and a selector (s=). The receiver fetches the public key from selector._domainkey.domain and checks the signature.

If anyone changes the message on the way, the signature fails. Unlike SPF, DKIM still passes after a message is forwarded, because it travels with the message rather than depending on which server sent it.

DMARC: the policy that ties it together

SPF and DKIM each check a domain, but not necessarily the one the reader sees. DMARC adds the missing rule: at least one of them must pass and match the domain in the visible From: line. That match is called alignment.

The DMARC record then says what to do when a message fails, and where to send daily reports. Most domains start at p=none to watch the reports, then move to quarantine, then reject.

DMARC policies
PolicyWhat the receiver does with a failing message
p=noneDelivers it normally, but reports it. Good for the first weeks.
p=quarantinePuts it in spam.
p=rejectRefuses it during the SMTP conversation. Full protection from spoofing.

Reading your mail: IMAP or POP3

Getting mail out of the mailbox
IMAPPOP3
Where mail livesOn the serverDownloaded to one device
Many devicesYes, all in syncAwkward
Folders and read stateSyncedLocal only
Port (TLS)993995
Use it forAlmost everything todayOne device, offline archives

Why your email lands in spam

  • No SPF, DKIM or DMARCLarge providers now expect all three from anyone who sends in bulk, and treat missing ones as a red flag.
  • SPF that is too longMore than 10 lookups and SPF fails for every message.
  • From: does not alignSending as you@yourdomain.com through a tool that signs as its own domain fails DMARC.
  • No reverse DNSA sending IP with no PTR record, or one that does not match, looks like a home computer.
  • A cold IP or domainBrand new senders need to start slow and build a reputation.
  • Content and complaintsSpammy wording, broken links and people pressing "report spam" all count against you.

A short history

How email grew its safety layers
YearWhat happened
1971The first email between two computers on ARPANET, and the @ sign
1982SMTP is standardised (RFC 821)
1984 / 1986POP and IMAP arrive for reading mail from a server
2006SPF is published as an experimental RFC (later RFC 7208, 2014)
2007 / 2011DKIM is standardised (RFC 4871, then RFC 6376)
2015DMARC is published (RFC 7489)
2024Gmail and Yahoo require SPF, DKIM and DMARC from bulk senders

Check your own domain

You can read every record in this post yourself from a terminal. Try it on your own domain.

nslookup -type=MX yourdomain.com
nslookup -type=TXT yourdomain.com             # SPF lives here
nslookup -type=TXT _dmarc.yourdomain.com      # DMARC
nslookup -type=TXT s1._domainkey.yourdomain.com   # DKIM (use your selector)

In Gmail, open any message, choose "Show original" and you will see SPF, DKIM and DMARC each marked PASS or FAIL. It is the fastest way to see this whole post at work.

Keep reading

  • Backend
  • Architecture

Why your microservices should stop shouting JSON

gRPC and Protocol Buffers in plain words, and where REST still wins.

Why services inside a system often talk gRPC instead of JSON over HTTP, what a .proto file gives you, and where REST still fits.

  • Real-time
  • Backend

Is anyone there? How the web learned to talk back

From polling to WebSockets: the whole story, with diagrams.

How the web went from asking "anything new?" over and over to one open, two-way connection. The tricks that came before, how a WebSocket actually works, and when you should and should not use one.

  • AI Agents
  • Automation

Let the AI draft. Let a human press Send.

Why the smartest AI agents stop exactly one click short.

The most useful AI agents I build do almost everything, then stop one step short. Here is why the last click belongs to a person, and how to design for it.

Have a process worth automating?

Tell me what eats your team's week. I'll tell you what I'd automate first.

Start a project Remote · PrimeX Meta, Dubai · teams across time zones