Networking Interview Prep
Application Protocols

Email Protocols

SMTP, POP3 & IMAP

LinkedIn Hook

Most developers know how to send an email in code — nodemailer.sendMail() and done.

But do you know what actually happens between the moment you click Send and the moment the recipient's inbox lights up?

Three protocols. Three separate jobs. Zero overlap.

Here is what the interview expects you to know:

  • SMTP is the postal truck — it delivers your mail to the destination server
  • POP3 downloads your mail to your device and the server shreds its copy
  • IMAP lets you read your mail at the post office — the server keeps everything, every device stays in sync
  • SMTP uses three different ports for three distinct handoff points — knowing which port does what separates juniors from seniors
  • Your email touches at least four machines and two DNS lookups before it lands in an inbox
  • Without SPF, DKIM, and DMARC, your carefully crafted emails go straight to spam

The full journey — raw SMTP dialogue included — is in the lesson below.

Read the full lesson → [link]

#Networking #SMTP #EmailProtocols #BackendEngineering #SystemDesign #InterviewPrep


Email Protocols thumbnail


What You'll Learn

  • Why email uses three separate protocols instead of one
  • How SMTP works — ports 25, 587, and 465, and when each is used
  • The raw SMTP dialogue between two mail servers, line by line
  • How POP3 downloads and deletes vs. how IMAP syncs across devices
  • The full end-to-end journey an email takes from sender to recipient inbox
  • How MX records, MTAs, and MUAs fit together in the email architecture
  • Email authentication: SPF, DKIM, and DMARC — why they exist and what they do
  • How to send email programmatically in Node.js using nodemailer

The Analogy That Makes This Click

Picture a physical postal system.

SMTP is the postal truck. When you drop a letter in the mailbox, a truck picks it up and drives it to the recipient's local post office. The truck does not care how you will eventually read the letter — it just delivers.

POP3 is picking up your mail from the post office and taking it home. Once you take the letter, the post office shreds their copy. It is yours now. If you lose it, it is gone. If you check from your phone, your phone gets nothing — the letter is already at home.

IMAP is reading your mail at the post office, with the post office keeping the master copy. You can walk in from any branch in any city, and your mailbox looks exactly the same. Folders, read/unread status, everything in sync — because the post office (the server) is the source of truth.

Three protocols. Three jobs. The confusion disappears once you see them as a pipeline: SMTP pushes mail forward, POP3 or IMAP pulls it down at the other end.


SMTP — Simple Mail Transfer Protocol

SMTP is the universal language mail servers use to hand email to each other. It is a text-based, command-response protocol — every step is a human-readable command followed by a three-digit status code.

The Three SMTP Ports

PortNameWho Uses ItEncryption
25SMTP (MTA relay)Server-to-server deliveryNone (or STARTTLS)
587SubmissionYour email client → your mail serverSTARTTLS (required)
465SMTPSYour email client → your mail serverImplicit TLS

Port 25 is the internet's original mail port — it is how Gmail's servers talk to Yahoo's servers. It is almost always blocked outbound by ISPs and cloud providers (AWS, GCP, Azure) to prevent spam. You cannot use port 25 to send email from an EC2 instance by default.

Port 587 is the modern standard for mail submission — your email application (Outlook, Thunderbird, Gmail's mobile app) connects to your own mail server on 587 and authenticates before handing off the message. STARTTLS upgrades the plain-text connection to encrypted after the initial handshake.

Port 465 was briefly standardized, then deprecated, then widely re-adopted in practice. It uses implicit TLS — the TLS handshake happens immediately on connection, before any SMTP commands are exchanged. Many libraries and services still support it; prefer 587 for new integrations unless the service explicitly requires 465.


The Raw SMTP Dialogue

When two mail servers communicate, the conversation looks like this. The S: lines are the server; the C: lines are the client (the sending server).

S: 220 mail.recipient.com ESMTP Postfix ready
C: EHLO mail.sender.com
S: 250-mail.recipient.com Hello mail.sender.com
S: 250-SIZE 52428800
S: 250-STARTTLS
S: 250-AUTH LOGIN PLAIN
S: 250 HELP
C: MAIL FROM:<alice@sender.com>
S: 250 2.1.0 Ok
C: RCPT TO:<bob@recipient.com>
S: 250 2.1.5 Ok
C: DATA
S: 354 End data with <CR><LF>.<CR><LF>
C: From: Alice <alice@sender.com>
C: To: Bob <bob@recipient.com>
C: Subject: Hello from SMTP
C: Date: Tue, 22 Apr 2026 10:00:00 +0000
C: MIME-Version: 1.0
C: Content-Type: text/plain
C:
C: Hey Bob, this is the email body.
C: .
S: 250 2.0.0 Ok: queued as A1B2C3D4E5
C: QUIT
S: 221 2.0.0 Bye

Breaking down the commands:

  • EHLO — Extended HELLO. The sending server identifies itself and asks for the server's capabilities. The server responds with what it supports (size limits, STARTTLS, authentication methods).
  • MAIL FROM — Declares the envelope sender (the return address on the envelope — not necessarily what the user sees as "From").
  • RCPT TO — Declares one recipient. This command can be repeated for multiple recipients.
  • DATA — Signals the start of the message headers and body. The server responds with 354, telling the client to send the content and terminate it with a lone period on its own line (<CR><LF>.<CR><LF>).
  • The message body contains RFC 2822 headers (From, To, Subject, Date, MIME-Version) followed by a blank line, then the actual body text.
  • QUIT — Ends the session cleanly.

The three-digit response codes follow a pattern: 2xx means success, 3xx means continue (more data expected), 4xx means temporary failure (try again later), 5xx means permanent failure (do not retry).


POP3 — Post Office Protocol Version 3

POP3 was designed in an era when internet connections were slow and intermittent. The model: download everything, disconnect, read offline.

How POP3 Works

  1. Your email client connects to the mail server on port 110 (plain) or port 995 (SSL/TLS).
  2. The client authenticates with username and password.
  3. The server lists available messages.
  4. The client downloads each message to the local device.
  5. By default, the server deletes the messages after download.
  6. The client disconnects.

POP3 Characteristics

  • Offline-first: Once downloaded, messages live on your device. No internet required to read them.
  • No sync: If you download on your laptop, your phone sees an empty inbox the next time it connects. The server has nothing left to deliver.
  • Simple: POP3 has fewer than 20 commands. It is designed to do one thing.
  • Suitable for: Single-device setups, users who want local backups, or environments where server storage is expensive.

POP3 Ports

PortEncryption
110None (plain text)
995SSL/TLS (POP3S)

You should never use port 110 over an untrusted network — credentials and message content travel in plain text.


IMAP — Internet Message Access Protocol

IMAP was designed for the modern reality: you check email on a phone, a laptop, a tablet, and a web browser. All four need to see the same thing.

How IMAP Works

  1. Your email client connects to the mail server on port 143 (plain + STARTTLS) or port 993 (implicit TLS).
  2. The client authenticates.
  3. The server exposes your mailbox structure — folders (INBOX, Sent, Drafts, etc.).
  4. The client fetches only message headers initially — sender, subject, date — without downloading full bodies.
  5. When you open a message, the client fetches just that message's body.
  6. All state changes (read/unread, moved to folder, deleted) happen on the server.
  7. Every other device connecting later sees the same state.

IMAP Characteristics

  • Server-authoritative: The server holds the canonical copy of every message. Devices are views into the server's state.
  • Efficient: Only downloads what is needed. A mailbox with 10,000 messages does not require downloading 10,000 messages to see your inbox.
  • Folder support: IMAP supports hierarchical folder structures, server-side search, and message flags (Seen, Answered, Flagged, Deleted, Draft).
  • Suitable for: Anyone using more than one device, any modern email workflow.

IMAP Ports

PortEncryption
143STARTTLS (upgrades after connect)
993Implicit TLS (IMAPS)

POP3 vs IMAP — Side by Side

FeaturePOP3IMAP
Default behaviorDownload + delete from serverKeep on server
Multi-device syncNoYes
Offline accessYes (after download)Partial (cached)
Server storage usedMinimal (clears after download)Ongoing (all mail stored)
Folder supportNoYes
Server-side searchNoYes
Best forSingle device, offline useMultiple devices, modern use

How Email Actually Travels — The Full Journey

Here is what happens when you compose an email in Gmail and send it to someone on Outlook.

[1] You (MUA: Gmail web app)
      |
      | SMTP port 587 + auth + TLS
      v
[2] Gmail's Outbound SMTP Server (MTA)
      |
      | DNS: lookup MX record for outlook.com
      | → MX record returns: outlook-com.olc.protection.outlook.com
      |
      | SMTP port 25 (server-to-server)
      v
[3] Microsoft's Inbound SMTP Server (MTA)
      |
      | Spam filtering, SPF check, DKIM verify, DMARC policy
      |
      v
[4] Microsoft's Mail Store (Mailbox server)
      |
      | IMAP port 993 (or POP3 port 995)
      v
[5] Recipient's Device (MUA: Outlook app)

Step-by-step breakdown:

Step 1 — Compose and submit: You write the email in Gmail (a Mail User Agent, or MUA). When you click Send, Gmail's browser client hands the message to Gmail's SMTP submission server on port 587, authenticating with your credentials over TLS.

Step 2 — Gmail's MTA takes over: Gmail's outbound Mail Transfer Agent (MTA) accepts the message. It needs to know where to deliver it. It does a DNS lookup for the recipient's domain (outlook.com) requesting the MX record (Mail Exchanger record). The MX record returns the hostname(s) of the servers authorized to receive mail for that domain, with priority values.

Step 3 — Server-to-server delivery: Gmail's MTA opens a TCP connection to Microsoft's inbound MTA on port 25 and runs the full SMTP dialogue shown earlier. This is the only hop where port 25 is legitimately used.

Step 4 — Filtering and storage: Microsoft's inbound servers run spam detection, verify authentication records (SPF, DKIM, DMARC), and if all checks pass, store the message in the recipient's mailbox.

Step 5 — Recipient fetches the message: The recipient's Outlook app connects to Microsoft's mail server via IMAP on port 993. It sees the new message in INBOX, downloads the headers, and displays the notification. When the recipient opens the email, the full body is fetched.

The whole process typically takes between 1 and 30 seconds, but the architecture supports retries — if Step 3 fails (the receiving server is temporarily down), Gmail's MTA queues the message and retries for up to 48–72 hours before returning a bounce message.


Email Authentication — SPF, DKIM, and DMARC

Without authentication, anyone can send email claiming to be from @yourbank.com. These three mechanisms exist to prevent exactly that.

SPF — Sender Policy Framework

SPF is a DNS TXT record that lists the IP addresses authorized to send email for a domain.

TXT record for sender.com:
"v=spf1 include:_spf.google.com include:sendgrid.net ip4:203.0.113.10 ~all"

When Microsoft's inbound server receives a message claiming to be from alice@sender.com, it looks up sender.com's SPF record and checks whether the sending server's IP is listed. If it is not, the message fails SPF.

The ~all at the end is a soft fail (mark suspicious), \-all is a hard fail (reject).

SPF protects the envelope sender — the server-level return address — not the human-visible From header.

DKIM — DomainKeys Identified Mail

DKIM adds a cryptographic signature to outgoing emails. The sending server signs the message headers and body with a private key. The public key is published in a DNS TXT record.

Email header added by sender's SMTP server:
DKIM-Signature: v=1; a=rsa-sha256; d=sender.com; s=mail2026;
    h=from:to:subject:date:message-id;
    bh=47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=;
    b=XyZ1a2...

The receiving server fetches mail2026._domainkey.sender.com from DNS, retrieves the public key, and verifies the signature. If the signature is valid, the message content has not been tampered with in transit and genuinely originated from a server with access to that domain's private key.

DMARC — Domain-based Message Authentication Reporting and Conformance

DMARC builds on SPF and DKIM. It tells receiving servers what to do when SPF or DKIM fail, and where to send reports.

TXT record for sender.com:
"v=DMARC1; p=quarantine; rua=mailto:dmarc-reports@sender.com; pct=100"

Policies:

  • p=none — monitor only, take no action
  • p=quarantine — send failing messages to spam
  • p=reject — reject failing messages outright

DMARC also requires alignment — the domain in the From header must match the SPF or DKIM domain. This closes the gap that SPF alone cannot cover (the visible From address vs. the envelope sender).

The minimum setup for a deliverable domain: SPF + DKIM. Adding DMARC gives you reporting and enforcement. Skipping all three is the fastest path to the spam folder.


Sending Email Programmatically — Node.js with nodemailer

nodemailer is the standard Node.js library for sending email via SMTP. Here is a complete, working example that connects to an SMTP server over port 587 with STARTTLS.

import nodemailer from 'nodemailer';

// Create a reusable transporter configured for port 587 (STARTTLS)
const transporter = nodemailer.createTransport({
  host: 'smtp.yourprovider.com',  // e.g., smtp.gmail.com, smtp.sendgrid.net
  port: 587,
  secure: false,        // false = STARTTLS (upgrades after connect)
                        // true  = implicit TLS (use port 465)
  auth: {
    user: process.env.SMTP_USER,     // your SMTP username / email address
    pass: process.env.SMTP_PASSWORD, // your SMTP password or app-specific password
  },
});

// Define the email content (RFC 2822 headers mapped to friendly fields)
const mailOptions = {
  from: '"Alice Dev" <alice@yourprovider.com>',  // visible From header
  to: 'bob@recipient.com',                        // RCPT TO (comma-separated for multiple)
  cc: 'carol@recipient.com',
  subject: 'Hello from Node.js + SMTP',
  text: 'Plain text version — always include this for email clients that cannot render HTML.',
  html: `
    <h1 style="color: #00cfff;">Hello Bob!</h1>
    <p>This email was sent via <strong>nodemailer</strong> on port 587.</p>
    <p>SMTP is just TCP with a very chatty handshake.</p>
  `,
  // Optional: attachments
  attachments: [
    {
      filename: 'report.pdf',
      path: './reports/monthly-report.pdf',    // local file path
      contentType: 'application/pdf',
    },
  ],
};

// Send the email — nodemailer handles the full SMTP dialogue internally
async function sendEmail() {
  try {
    const info = await transporter.sendMail(mailOptions);
    console.log('Message sent:', info.messageId);
    // info.messageId: the unique ID assigned by the receiving server
    // e.g., <01000182a3b4c5d6-abc123-abc1-abc2-abc3-abcdefabcdef-000000@email.amazonses.com>
  } catch (error) {
    console.error('Failed to send email:', error.message);
    // Common errors:
    // ECONNREFUSED: wrong host/port, server not listening
    // EAUTH: bad credentials
    // 550 5.7.1: recipient server rejected — check SPF/DKIM
    throw error;
  }
}

sendEmail();

Using a transactional email service (recommended for production):

In production, you almost never run your own SMTP server. Instead, you use a transactional email service — SendGrid, AWS SES, Postmark, Resend — and configure nodemailer to authenticate with their SMTP endpoint.

// SendGrid example — replace host and credentials
const transporter = nodemailer.createTransport({
  host: 'smtp.sendgrid.net',
  port: 587,
  secure: false,
  auth: {
    user: 'apikey',                          // literal string 'apikey' for SendGrid
    pass: process.env.SENDGRID_API_KEY,      // your SendGrid API key
  },
});

// AWS SES example
const transporter = nodemailer.createTransport({
  host: 'email-smtp.us-east-1.amazonaws.com',
  port: 587,
  secure: false,
  auth: {
    user: process.env.SES_SMTP_USER,   // SMTP credentials (different from IAM)
    pass: process.env.SES_SMTP_PASS,
  },
});

Why not use port 25 from your server?

AWS, GCP, and Azure block outbound port 25 by default on all compute instances. This prevents compromised servers from being used as spam relays. Your code will hang or get ECONNREFUSED if you try. Always use 587 or 465 through an authenticated submission endpoint.

Testing without a real server:

// Ethereal Email: a fake SMTP server for development
// Messages are captured — never actually delivered
const testAccount = await nodemailer.createTestAccount();

const transporter = nodemailer.createTransport({
  host: 'smtp.ethereal.email',
  port: 587,
  secure: false,
  auth: {
    user: testAccount.user,
    pass: testAccount.pass,
  },
});

const info = await transporter.sendMail(mailOptions);
// Preview the captured email in a browser:
console.log('Preview URL:', nodemailer.getTestMessageUrl(info));

Common Mistakes

  • Sending on port 25 from a cloud server: Port 25 outbound is blocked by virtually every major cloud provider (AWS, GCP, Azure, DigitalOcean) to combat spam. If you hardcode port 25 for client submission, your email will never leave the machine. Use a transactional email service (SendGrid, AWS SES, Postmark, Resend) and connect on port 587 or 465 through their authenticated endpoint.

  • Using POP3 when users check from multiple devices: POP3 downloads messages and deletes them from the server by default. If your user checks email on a laptop in the morning, the server copy is gone — their phone sees an empty inbox, their webmail shows nothing. For any multi-device workflow, use IMAP (port 993). If you are building an email client or integration, default to IMAP unless there is a specific reason not to.

  • Not setting up SPF and DKIM records: Even if your SMTP delivery succeeds (your server can connect to the recipient's MTA on port 25), modern mail servers run authentication checks before accepting delivery. A domain with no SPF record, or one whose sending IP does not match its SPF record, will see messages quarantined or rejected. A missing DKIM signature means the receiving server cannot verify the message was not tampered with. The result: your transactional emails (password resets, receipts, invites) land in spam. Set up SPF and DKIM on day one, add DMARC once you have confirmed they are working.


Interview Questions

1. What is the difference between POP3 and IMAP?

POP3 downloads messages from the server to the local device and (by default) deletes them from the server afterward. There is no sync — checking from a second device shows nothing. IMAP keeps the canonical copy on the server and treats devices as synchronized views. State changes (read/unread, moved folders) are reflected on all connected devices because the server is the source of truth. POP3 uses ports 110/995; IMAP uses ports 143/993.

2. What ports does SMTP use and when is each used?

SMTP uses three ports for different handoff points:

  • Port 25 — server-to-server relay (MTA to MTA). This is how Gmail delivers to Yahoo. Almost always blocked outbound by ISPs and cloud providers to prevent spam.
  • Port 587 — client-to-server submission. Your email app authenticates to your own mail server here. Uses STARTTLS to encrypt. The modern standard for submission.
  • Port 465 — SMTPS with implicit TLS. Deprecated by RFC but widely used in practice. TLS is established before any SMTP commands are exchanged.

3. How does an email get from sender to recipient? Walk through the full journey.

(1) The sender composes the email in their MUA (Mail User Agent — e.g., Gmail). (2) The MUA submits it to the sender's SMTP server on port 587 with authentication over TLS. (3) The sender's MTA does a DNS lookup for the recipient domain's MX record to find the receiving mail server. (4) The sender's MTA connects to the recipient's MTA on port 25 and runs the SMTP dialogue: EHLO, MAIL FROM, RCPT TO, DATA, QUIT. (5) The recipient's MTA runs spam filtering and authentication checks (SPF, DKIM, DMARC). (6) If the message passes, it is stored in the recipient's mailbox. (7) The recipient's MUA connects to the mailbox server via IMAP (port 993) or POP3 (port 995) and fetches the message.

4. What is SPF and why does it exist?

SPF (Sender Policy Framework) is a DNS TXT record that lists the IP addresses allowed to send email on behalf of a domain. It exists because SMTP has no built-in authentication — without SPF, any server on the internet can send an email with a From address of @yourbank.com and SMTP will happily relay it. When a receiving server gets a message claiming to be from example.com, it looks up example.com's SPF record and checks whether the sending server's IP is listed. If not, the message fails SPF and the receiving server can quarantine or reject it based on the domain's DMARC policy. SPF alone is not sufficient (it only covers the envelope sender, not the visible From header) — it works as part of the SPF + DKIM + DMARC trio.


Quick Reference — Cheat Sheet

Protocol Comparison Table

ProtocolPort (plain)Port (encrypted)PurposeDirection
SMTP (relay)2525 + STARTTLSServer → server deliveryOutbound
SMTP (submit)587587 + STARTTLSClient → mail serverOutbound
SMTPS465 (implicit TLS)Client → mail serverOutbound
POP3110995Fetch + delete from serverInbound
IMAP143993Sync with serverInbound

The Full Email Journey (Numbered)

1. User composes email in MUA (Gmail, Outlook, Thunderbird)
2. MUA submits via SMTP → port 587, STARTTLS, authenticated
3. Sender's MTA does DNS lookup → MX record for recipient domain
4. Sender's MTA connects to recipient's MTA → port 25, SMTP dialogue
   EHLO → MAIL FROM → RCPT TO → DATA → body → . → QUIT
5. Recipient's MTA runs: SPF check + DKIM verify + DMARC policy
6. Message stored in recipient's mailbox on mail server
7. Recipient's MUA fetches via IMAP (port 993) or POP3 (port 995)
8. Recipient reads the message

SMTP Response Codes

CodeMeaning
220Service ready
250Command OK
354Start mail input
421Service unavailable (temporary)
450Mailbox unavailable (try again)
500Syntax error (permanent)
550Mailbox unavailable / rejected (permanent)

Email Auth Quick Reference

MechanismDNS Record TypeProtectsWhat It Does
SPFTXTEnvelope sender IPLists authorized sending IPs
DKIMTXTMessage integrityCryptographic signature on headers + body
DMARCTXTFrom header alignmentPolicy: none / quarantine / reject

nodemailer Port Selection

// Port 587 — STARTTLS (recommended default)
{ port: 587, secure: false }

// Port 465 — Implicit TLS
{ port: 465, secure: true }

// Never use port 25 from cloud servers

Previous: Lesson 5.4 — FTP & SFTP (04-ftp-sftp.md) Next: Lesson 6.1 — What is DNS? (../ch06-dns/01-what-is-dns.md)


This is Lesson 5.5 of the Networking Interview Prep Course — 8 chapters, 32 lessons.

On this page