Wraps Logo
S: 220 mail.example.com ESMTP ready
C: EHLO yourcompany.com
S: 250-mail.example.com Hello
S: 250-STARTTLS
S: 250 Ok
C: MAIL FROM:<you@yourcompany.com>
S: 250 2.1.0 Ok
C: RCPT TO:<alice@example.com>
S: 250 2.1.5 Ok
C: DATA
S: 354 End data with <CR><LF>.<CR><LF>
C: From: you@yourcompany.com
C: To: alice@example.com
C: Subject: Quick question
C: .
S: 250 2.0.0 Ok: queued as ABC123
C: QUIT
S: 221 2.0.0 Bye
S: 220 mx.recipient.org ESMTP Postfix
C: EHLO relay.google.com
S: 250-mx.recipient.org
S: 250-AUTH PLAIN LOGIN
S: 250 Ok
C: MAIL FROM:<bounce+id=abc@yourcompany.com>
S: 250 2.1.0 Ok
C: RCPT TO:<bob@recipient.org>
S: 250 2.1.5 Ok
C: DATA
S: 354 Go ahead
C: DKIM-Signature: v=1; a=rsa-sha256; d=yourcompany.com
C: Authentication-Results: spf=pass dkim=pass dmarc=pass
C: .
S: 250 2.0.0 Ok: queued as DEF456
C: QUIT
S: 221 Bye
S: 220 mail.example.com ESMTP ready
C: EHLO yourcompany.com
S: 250-mail.example.com Hello
S: 250-STARTTLS
S: 250 Ok
C: MAIL FROM:<you@yourcompany.com>
S: 250 2.1.0 Ok
C: RCPT TO:<alice@example.com>
S: 250 2.1.5 Ok
C: DATA
S: 354 End data with <CR><LF>.<CR><LF>
C: From: you@yourcompany.com
C: To: alice@example.com
C: Subject: Quick question
C: .
S: 250 2.0.0 Ok: queued as ABC123
C: QUIT
S: 221 2.0.0 Bye
S: 220 mx.recipient.org ESMTP Postfix
C: EHLO relay.google.com
S: 250-mx.recipient.org
S: 250-AUTH PLAIN LOGIN
S: 250 Ok
C: MAIL FROM:<bounce+id=abc@yourcompany.com>
S: 250 2.1.0 Ok
C: RCPT TO:<bob@recipient.org>
S: 250 2.1.5 Ok
C: DATA
S: 354 Go ahead
C: DKIM-Signature: v=1; a=rsa-sha256; d=yourcompany.com
C: Authentication-Results: spf=pass dkim=pass dmarc=pass
C: .
S: 250 2.0.0 Ok: queued as DEF456
C: QUIT
S: 221 Bye
S: 220 mail.example.com ESMTP ready
C: EHLO yourcompany.com
S: 250-mail.example.com Hello
S: 250-STARTTLS
S: 250 Ok
C: MAIL FROM:<you@yourcompany.com>
S: 250 2.1.0 Ok
C: RCPT TO:<alice@example.com>
S: 250 2.1.5 Ok
C: DATA
S: 354 End data with <CR><LF>.<CR><LF>
C: From: you@yourcompany.com
C: To: alice@example.com
C: Subject: Quick question
C: .
S: 250 2.0.0 Ok: queued as ABC123
C: QUIT
S: 221 2.0.0 Bye
S: 220 mx.recipient.org ESMTP Postfix
C: EHLO relay.google.com
S: 250-mx.recipient.org
S: 250-AUTH PLAIN LOGIN
S: 250 Ok
C: MAIL FROM:<bounce+id=abc@yourcompany.com>
S: 250 2.1.0 Ok
C: RCPT TO:<bob@recipient.org>
S: 250 2.1.5 Ok
C: DATA
S: 354 Go ahead
C: DKIM-Signature: v=1; a=rsa-sha256; d=yourcompany.com
C: Authentication-Results: spf=pass dkim=pass dmarc=pass
C: .
S: 250 2.0.0 Ok: queued as DEF456
C: QUIT
S: 221 Bye
S: 220 mail.example.com ESMTP ready
C: EHLO yourcompany.com
S: 250-mail.example.com Hello
S: 250-STARTTLS
S: 250 Ok
C: MAIL FROM:<you@yourcompany.com>
S: 250 2.1.0 Ok
C: RCPT TO:<alice@example.com>
S: 250 2.1.5 Ok
C: DATA
S: 354 End data with <CR><LF>.<CR><LF>
C: From: you@yourcompany.com
C: To: alice@example.com
C: Subject: Quick question
C: .
S: 250 2.0.0 Ok: queued as ABC123
C: QUIT
S: 221 2.0.0 Bye
S: 220 mx.recipient.org ESMTP Postfix
C: EHLO relay.google.com
S: 250-mx.recipient.org
S: 250-AUTH PLAIN LOGIN
S: 250 Ok
C: MAIL FROM:<bounce+id=abc@yourcompany.com>
S: 250 2.1.0 Ok
C: RCPT TO:<bob@recipient.org>
S: 250 2.1.5 Ok
C: DATA
S: 354 Go ahead
C: DKIM-Signature: v=1; a=rsa-sha256; d=yourcompany.com
C: Authentication-Results: spf=pass dkim=pass dmarc=pass
C: .
S: 250 2.0.0 Ok: queued as DEF456
C: QUIT
S: 221 Bye
S: 220 mail.example.com ESMTP ready
C: EHLO yourcompany.com
S: 250-mail.example.com Hello
S: 250-STARTTLS
S: 250 Ok
C: MAIL FROM:<you@yourcompany.com>
S: 250 2.1.0 Ok
C: RCPT TO:<alice@example.com>
S: 250 2.1.5 Ok
C: DATA
S: 354 End data with <CR><LF>.<CR><LF>
C: From: you@yourcompany.com
C: To: alice@example.com
C: Subject: Quick question
C: .
S: 250 2.0.0 Ok: queued as ABC123
C: QUIT
S: 221 2.0.0 Bye
S: 220 mx.recipient.org ESMTP Postfix
C: EHLO relay.google.com
S: 250-mx.recipient.org
S: 250-AUTH PLAIN LOGIN
S: 250 Ok
C: MAIL FROM:<bounce+id=abc@yourcompany.com>
S: 250 2.1.0 Ok
C: RCPT TO:<bob@recipient.org>
S: 250 2.1.5 Ok
C: DATA
S: 354 Go ahead
C: DKIM-Signature: v=1; a=rsa-sha256; d=yourcompany.com
C: Authentication-Results: spf=pass dkim=pass dmarc=pass
C: .
S: 250 2.0.0 Ok: queued as DEF456
C: QUIT
S: 221 Bye
S: 220 mail.example.com ESMTP ready
C: EHLO yourcompany.com
S: 250-mail.example.com Hello
S: 250-STARTTLS
S: 250 Ok
C: MAIL FROM:<you@yourcompany.com>
S: 250 2.1.0 Ok
C: RCPT TO:<alice@example.com>
S: 250 2.1.5 Ok
C: DATA
S: 354 End data with <CR><LF>.<CR><LF>
C: From: you@yourcompany.com
C: To: alice@example.com
C: Subject: Quick question
C: .
S: 250 2.0.0 Ok: queued as ABC123
C: QUIT
S: 221 2.0.0 Bye
S: 220 mx.recipient.org ESMTP Postfix
C: EHLO relay.google.com
S: 250-mx.recipient.org
S: 250-AUTH PLAIN LOGIN
S: 250 Ok
C: MAIL FROM:<bounce+id=abc@yourcompany.com>
S: 250 2.1.0 Ok
C: RCPT TO:<bob@recipient.org>
S: 250 2.1.5 Ok
C: DATA
S: 354 Go ahead
C: DKIM-Signature: v=1; a=rsa-sha256; d=yourcompany.com
C: Authentication-Results: spf=pass dkim=pass dmarc=pass
C: .
S: 250 2.0.0 Ok: queued as DEF456
C: QUIT
S: 221 Bye
S: 220 mail.example.com ESMTP ready
C: EHLO yourcompany.com
S: 250-mail.example.com Hello
S: 250-STARTTLS
S: 250 Ok
C: MAIL FROM:<you@yourcompany.com>
S: 250 2.1.0 Ok
C: RCPT TO:<alice@example.com>
S: 250 2.1.5 Ok
C: DATA
S: 354 End data with <CR><LF>.<CR><LF>
C: From: you@yourcompany.com
C: To: alice@example.com
C: Subject: Quick question
C: .
S: 250 2.0.0 Ok: queued as ABC123
C: QUIT
S: 221 2.0.0 Bye
S: 220 mx.recipient.org ESMTP Postfix
C: EHLO relay.google.com
S: 250-mx.recipient.org
S: 250-AUTH PLAIN LOGIN
S: 250 Ok
C: MAIL FROM:<bounce+id=abc@yourcompany.com>
S: 250 2.1.0 Ok
C: RCPT TO:<bob@recipient.org>
S: 250 2.1.5 Ok
C: DATA
S: 354 Go ahead
C: DKIM-Signature: v=1; a=rsa-sha256; d=yourcompany.com
C: Authentication-Results: spf=pass dkim=pass dmarc=pass
C: .
S: 250 2.0.0 Ok: queued as DEF456
C: QUIT
S: 221 Bye
S: 220 mail.example.com ESMTP ready
C: EHLO yourcompany.com
S: 250-mail.example.com Hello
S: 250-STARTTLS
S: 250 Ok
C: MAIL FROM:<you@yourcompany.com>
S: 250 2.1.0 Ok
C: RCPT TO:<alice@example.com>
S: 250 2.1.5 Ok
C: DATA
S: 354 End data with <CR><LF>.<CR><LF>
C: From: you@yourcompany.com
C: To: alice@example.com
C: Subject: Quick question
C: .
S: 250 2.0.0 Ok: queued as ABC123
C: QUIT
S: 221 2.0.0 Bye
S: 220 mx.recipient.org ESMTP Postfix
C: EHLO relay.google.com
S: 250-mx.recipient.org
S: 250-AUTH PLAIN LOGIN
S: 250 Ok
C: MAIL FROM:<bounce+id=abc@yourcompany.com>
S: 250 2.1.0 Ok
C: RCPT TO:<bob@recipient.org>
S: 250 2.1.5 Ok
C: DATA
S: 354 Go ahead
C: DKIM-Signature: v=1; a=rsa-sha256; d=yourcompany.com
C: Authentication-Results: spf=pass dkim=pass dmarc=pass
C: .
S: 250 2.0.0 Ok: queued as DEF456
C: QUIT
S: 221 Bye

How Email Actually Works

You click Send. What happens in the next 3 seconds? An interactive journey from compose window to inbox — through SMTP handshakes, DNS lookups, relay hops, and authentication.

20 min readWraps Team

Chapter 1: The Compose

Every email starts with a lie — or at least a convenient illusion. The compose window shows you simple fields: To, From, Subject, Body. But underneath that friendly UI, your email client is building a structured document with dozens of headers, MIME encoding, and an envelope that's completely separate from the message itself.

This distinction between the envelope and the content is fundamental. The envelope (MAIL FROM and RCPT TO) tells servers where to route the message. The content (the From: and To: headers) is what you see in your inbox. They don't have to match — and that mismatch is exactly how email spoofing works.

Try editing the compose form below and watch the raw SMTP message update in real-time. Notice how the same information appears in two different formats — human-readable and machine-readable.

What you see
What the server sees
EHLO yourcompany.com
MAIL FROM:<you@yourcompany.com>
RCPT TO:<alice@example.com>
DATA
From: you@yourcompany.com
To: alice@example.com
Subject: Quick question about the project
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Date: Fri, 06 Mar 2026 20:32:27 GMT
Message-ID: <1772829147115@yourcompany.com>

Hi Alice,

Just wanted to follow up on our conversation yesterday.

Best,
You
.
QUIT

Chapter 2: The Handshake

SMTP is a surprisingly conversational protocol. Your server doesn't just blast a message at the recipient — it has a structured back-and-forth dialogue, like two people on a phone call. The server introduces itself, the recipient confirms it's listening, then they negotiate how to transfer the message.

The conversation starts with a TCP connection to port 25 (server-to-server) or port 587 (client submission with auth). The receiving server responds with a 220 greeting — its way of saying "I'm here and ready." Your server then says EHLO (Extended Hello), and the conversation begins.

Every SMTP response starts with a three-digit code. 2xx means success. 3xx means "keep going" (like 354 after DATA). 4xx is a temporary error (try again). 5xx is permanent failure (don't retry). The entire protocol runs on this simple numbering system defined in 1982.

Try it yourself. The terminal below simulates a real SMTP session — type each command and watch the server respond.

smtp — telnet mail.example.com 25
S: 220 mail.example.com ESMTP ready
Step 1/6: Connect to the mail server
>

Chapter 3: The Lookup

Before your server can deliver the message, it needs to find out where to send it. The recipient's address says alice@example.com, but what IP address actually handles mail for example.com?

This is where MX records come in. Your server queries DNS for the MX (Mail Exchange) records of the recipient domain. These records list one or more mail servers, each with a priority number. Lower priority = tried first. If the primary server is down, email falls back to the next one.

The DNS resolution path goes: root servers → TLD servers (.com, .org) → authoritative nameserver for the domain → MX records. This usually takes 20-100ms. The result is cached, so subsequent emails to the same domain skip the lookup.

Try looking up the MX records for any domain below. You'll see exactly which servers accept mail for that domain and in what priority order.

MX Record Lookup

Chapter 4: The Relay

Email rarely goes directly from sender to recipient. It hops through multiple servers — your outbound mail server, possibly a relay service (like AWS SES or Google's SMTP relay), the recipient's inbound MX server, and finally the IMAP store where the message lands.

Each server that touches the email adds a Received: header — a stamp showing where the message came from, which server processed it, and when. These headers stack in reverse order: the top Received header is the last hop, and the bottom one is the first.

This chain of Received headers is how you trace an email's journey across the internet. It's also how receiving servers detect suspicious routing — if an email claims to be from Google but the Received chain shows it originated from an unknown server in a different country, that's a red flag.

Your Server
Received: from yourcompany.com
Outbound MTA
Received: by smtp-relay.gmail.com
Recipient MX
Received: from smtp-relay by mx.example.com
Inbox Server
Received: by imap.example.com

Chapter 5: The Trust Check

SMTP was designed in 1982 — before spam, before phishing, before anyone imagined email would carry financial transactions. The protocol has zero built-in authentication. Any server can claim to be sending from any domain. It's like a postal system where anyone can write any return address on an envelope.

Three protocols were added later to fix this: SPF (2006), DKIM (2007), and DMARC (2012). Together, they form the authentication chain that modern email depends on. When the recipient's server receives your message, it runs all three checks before deciding whether to deliver, quarantine, or reject.

SPF

Is this server allowed to send for this domain?

1Receiving server extracts Return-Path domain
2Queries DNS for SPF record (TXT)
3Checks if sending IP is in the allowed list
4Returns Pass, Fail, SoftFail, or Neutral
SPFDKIMDMARCInbox or Reject
Prediction

An email passes DKIM but fails SPF. The domain has DMARC with p=reject. What happens?

The key insight: DMARC requires alignment. It's not enough for SPF or DKIM to pass — the domain in the result must match the From: header domain. This prevents attackers from using their own authenticated domain while spoofing a different From: address.

Prediction

Your company uses Google Workspace for email but sends marketing emails through AWS SES. What happens with SPF?

Chapter 6: The Inbox

After passing authentication, the email lands in the recipient's mail store. The recipient's email client retrieves it using IMAP (Internet Message Access Protocol) or the older POP3. IMAP keeps messages on the server and syncs across devices; POP3 downloads and (traditionally) deletes from the server.

The full circle is complete. From compose window to SMTP handshake, through DNS resolution and server relays, past authentication checks, and into the inbox. The entire journey typically takes 1-5 seconds — though queuing, greylisting, or retry logic can extend it to minutes or hours.

Below is the complete Received header chain from our email's journey. Each header was added by a different server at a different step — read bottom to top to trace the path.

The Complete Header Chain

Received headers are added in reverse order — the top header is the last hop. Read bottom to top to trace the email's journey.

Chapter 7: Deep Cuts

Email's simplicity hides layers of complexity. Here are the edge cases and failure modes that keep email administrators up at night.

Build on Top of Email Infrastructure You Own

Wraps deploys production-ready email infrastructure — DKIM, SPF, DMARC, bounce handling, and sending — to your AWS account. One command. You own everything.

Terminal
$ npx @wraps.dev/cli email init

No credit card · Open source · Infrastructure you own