Project 11: POP3 and IMAP Client
Build a client that can list and fetch email via POP3 and IMAP, comparing their state models.
Quick Reference
| Attribute | Value |
|---|---|
| Difficulty | Intermediate |
| Time Estimate | 2-3 weeks |
| Language | Python (Alternatives: Go, Rust) |
| Prerequisites | TCP clients, TLS basics |
| Key Topics | POP3 states, IMAP commands, MIME parsing |
1. Learning Objectives
- Implement POP3 and IMAP connections with TLS.
- List and fetch messages with both protocols.
- Handle IMAP mailboxes, flags, and search.
- Compare stateless POP3 to stateful IMAP behavior.
2. Theoretical Foundation
2.1 Core Concepts
- POP3: Simple, stateless, download-and-delete model.
- IMAP: Stateful, server-side folders, flags, and search.
- TLS: STARTTLS or implicit TLS on 995/993.
- MIME parsing: Email messages often contain multipart content.
2.2 Why This Matters
Understanding retrieval protocols reveals how email clients sync, how flags work, and why IMAP is dominant for modern clients.
2.3 Historical Context / Background
POP3 was designed for intermittent connectivity. IMAP evolved to support multiple clients and persistent server state.
2.4 Common Misconceptions
- Misconception: POP3 and IMAP are interchangeable. Reality: IMAP supports complex server-side state.
- Misconception: Message IDs are always stable. Reality: IMAP UID and sequence numbers differ.
3. Project Specification
3.1 What You Will Build
A CLI tool that connects to a mailbox, lists messages, and fetches message headers and bodies via POP3 and IMAP.
3.2 Functional Requirements
- Support POP3 USER/PASS and STAT/LIST/RETR/QUIT.
- Support IMAP LOGIN/SELECT/SEARCH/FETCH/LOGOUT.
- Handle STARTTLS or implicit TLS.
- Parse basic MIME structure for multipart messages.
3.3 Non-Functional Requirements
- Performance: Fetch headers for 100 messages quickly.
- Reliability: Handle server errors gracefully.
- Usability: Provide clear output with message counts.
3.4 Example Usage / Output
$ ./mail-client --imap imap.example.com --user a --pass b --list
Mailbox INBOX: 32 messages
UID 1001 \Seen Subject: Hello
UID 1002 \Recent Subject: Invoice
3.5 Real World Outcome
You can retrieve and inspect messages using both protocols and explain the tradeoffs between POP3 and IMAP.
4. Solution Architecture
4.1 High-Level Design
Client
-> Connection (TLS)
-> POP3 Handler
-> IMAP Handler
-> MIME Parser
4.2 Key Components
| Component | Responsibility | Key Decisions |
|---|---|---|
| Connection | TCP/TLS setup | STARTTLS vs implicit |
| POP3 | Implement POP3 states | transaction/update states |
| IMAP | Tag-based commands | tag generation strategy |
| MIME | Parse multipart | basic boundary parsing |
4.3 Data Structures
class ImapResponse:
def __init__(self, tag, lines):
self.tag = tag
self.lines = lines
4.4 Algorithm Overview
Key Algorithm: IMAP Command Parsing
- Send tagged command (A001 LOGIN …).
- Read until tagged response is received.
- Parse untagged responses for data.
Complexity Analysis:
- Time: O(n) for response size
- Space: O(n)
5. Implementation Guide
5.1 Development Environment Setup
python -m venv .venv
source .venv/bin/activate
5.2 Project Structure
mail-client/
├── pop3.py
├── imap.py
├── mime.py
└── README.md
5.3 The Core Question You’re Answering
“How do email clients retrieve messages, and why do POP3 and IMAP behave so differently?”
5.4 Concepts You Must Understand First
Stop and research these before coding:
- POP3 states: authorization, transaction, update
- IMAP tags and untagged responses
- TLS for mail retrieval
- MIME boundaries and parts
5.5 Questions to Guide Your Design
- How will you generate and track IMAP tags?
- How do you map POP3 message numbers to IMAP UIDs?
- How will you parse multipart bodies?
5.6 Thinking Exercise
If a new message arrives while an IMAP client is connected, how does IMAP notify the client? How does POP3 handle this?
5.7 The Interview Questions They’ll Ask
- “What is the difference between IMAP UID and sequence number?”
- “Why is IMAP considered stateful?”
- “How does POP3 delete messages?”
5.8 Hints in Layers
Hint 1: Start with POP3
- It is simpler and good for validating socket code.
Hint 2: Implement IMAP tags carefully
- Each command must be tagged and matched.
Hint 3: Use a basic MIME parser
- Do not try to implement full RFC 2045 immediately.
5.9 Books That Will Help
| Topic | Book | Chapter |
|---|---|---|
| POP3 | RFC 1939 | All |
| IMAP | RFC 3501 | Sections 3-6 |
| MIME | RFC 2045 | Sections 5-6 |
5.10 Implementation Phases
Phase 1: Foundation (4-5 days)
Goals:
- Connect with TLS and implement POP3
Tasks:
- POP3 USER/PASS and STAT.
- LIST and RETR.
Checkpoint: Download a message via POP3.
Phase 2: Core Functionality (1 week)
Goals:
- Implement IMAP list and fetch
Tasks:
- LOGIN and SELECT.
- SEARCH and FETCH headers.
Checkpoint: List messages with UIDs.
Phase 3: Polish and Edge Cases (4-5 days)
Goals:
- MIME parsing and robust errors
Tasks:
- Parse multipart bodies.
- Handle server errors and timeouts.
Checkpoint: Fetch and display multipart content.
5.11 Key Implementation Decisions
| Decision | Options | Recommendation | Rationale |
|---|---|---|---|
| TLS | implicit vs STARTTLS | both | common in real servers |
| IMAP parsing | line-based vs full parser | line-based | simpler for learning |
| MIME handling | simple vs full | simple | scope control |
6. Testing Strategy
6.1 Test Categories
| Category | Purpose | Examples |
|---|---|---|
| Unit Tests | Tag parsing | correct tag matching |
| Integration Tests | Real server | local IMAP/POP3 |
| Edge Case Tests | Large mailbox | handle paging |
6.2 Critical Test Cases
- IMAP tagged response properly matched.
- POP3 retrieval gets full message.
- MIME multipart parsed into parts.
6.3 Test Data
Content-Type: multipart/alternative; boundary=abc
7. Common Pitfalls and Debugging
7.1 Frequent Mistakes
| Pitfall | Symptom | Solution |
|---|---|---|
| Wrong IMAP tag handling | hangs | read until tag line |
| Misreading POP3 dot termination | truncated message | handle dot-stuffing |
| MIME parsing errors | missing parts | parse boundaries carefully |
7.2 Debugging Strategies
- Use server logs or test servers.
- Log raw responses for inspection.
7.3 Performance Traps
- Fetching full messages when headers only are needed. Use IMAP FETCH BODY.PEEK[HEADER].
8. Extensions and Challenges
8.1 Beginner Extensions
- Add support for TOP in POP3.
- Add IMAP IDLE for notifications.
8.2 Intermediate Extensions
- Implement IMAP flags updates.
- Support folder listing and selection.
8.3 Advanced Extensions
- Build a sync cache for offline access.
- Implement OAuth2 auth for IMAP.
9. Real-World Connections
9.1 Industry Applications
- Mail clients use IMAP for sync.
- Legacy systems still use POP3 for batch retrieval.
9.2 Related Open Source Projects
- OfflineIMAP: https://www.offlineimap.org/
- mu: https://github.com/djcb/mu
9.3 Interview Relevance
- IMAP state management and protocol parsing are common in networking interviews.
10. Resources
10.1 Essential Reading
- RFC 1939 - POP3
- RFC 3501 - IMAP
- RFC 2045 - MIME
10.2 Video Resources
- IMAP and POP3 protocol walkthroughs
10.3 Tools and Documentation
- openssl s_client for testing TLS
- mailutils for reference behavior
10.4 Related Projects in This Series
11. Self-Assessment Checklist
11.1 Understanding
- I can explain POP3 vs IMAP
- I understand IMAP tags
- I can parse MIME boundaries
11.2 Implementation
- Lists and fetches via POP3
- Lists and fetches via IMAP
- Handles TLS correctly
11.3 Growth
- I can explain why IMAP is stateful
- I can design a sync strategy
12. Submission / Completion Criteria
Minimum Viable Completion:
- Connect to POP3 and retrieve a message
Full Completion:
- Implement IMAP listing and fetching
Excellence (Going Above and Beyond):
- Add IMAP IDLE and offline sync
This guide was generated from EMAIL_SYSTEMS_DEEP_DIVE_PROJECTS.md. For the complete learning path, see the parent directory.