Skip to content

Latest commit

 

History

History
512 lines (414 loc) · 16.6 KB

File metadata and controls

512 lines (414 loc) · 16.6 KB

Mailbox Zero - Claude Development Documentation

Project Status: ✅ FULLY COMPLETE

Last Updated: December 15, 2024 Version: 2.0 (Protocol Modularization) Status: Multi-Protocol Architecture (JMAP ✅, IMAP ✅)

Project Overview

Mailbox Zero is a Go-based web application that helps users clean up their email inbox by finding and archiving similar emails. The application now supports multiple email protocols through a modular architecture, starting with JMAP (Fastmail) and IMAP (Gmail, Outlook, etc.).

The application provides a dual-pane interface with advanced fuzzy matching capabilities and comprehensive safety features.

Architecture

Tech Stack

  • Backend: Go 1.21+ with Gorilla Mux router
  • Frontend: Vanilla HTML5, CSS3, JavaScript (ES6+)
  • Email Protocols:
    • JMAP (JSON Meta Application Protocol) - ✅ Fully Functional
    • IMAP (Internet Message Access Protocol) - ✅ Fully Functional
  • Email Providers: Fastmail (JMAP), Gmail/Outlook/Generic (IMAP)
  • Configuration: YAML
  • Templates: Go HTML templates

Project Structure (v2.0 - Modular)

mailboxzero/
├── main.go                     # Application entry point with protocol factory
├── go.mod                      # Go module dependencies
├── config.yaml.example         # Configuration template (both protocols)
├── config-imap.yaml.example    # IMAP-specific example
├── config-mock.yaml.example    # Mock mode configuration
├── .gitignore                  # Git ignore rules
├── README.md                   # User documentation
├── CLAUDE.md                   # Development documentation (this file)
├── internal/
│   ├── protocol/               # 🆕 Generic protocol abstraction
│   │   ├── protocol.go         # EmailClient interface (5 methods)
│   │   └── types.go            # Protocol-agnostic types (Email, EmailAddress, InboxInfo)
│   ├── providers/              # 🆕 Protocol implementations
│   │   ├── jmap/               # JMAP provider (✅ Complete)
│   │   │   ├── client.go       # JMAP client implementing protocol.EmailClient
│   │   │   ├── types.go        # JMAP-specific types (Session, Account, etc.)
│   │   │   └── mock.go         # Mock JMAP client for testing
│   │   └── imap/               # IMAP provider (✅ Complete)
│   │       ├── client.go       # IMAP client implementing protocol.EmailClient
│   │       ├── mock.go         # Mock IMAP client for testing
│   │       └── mock_test.go    # Comprehensive unit tests
│   ├── config/
│   │   └── config.go           # Configuration with protocol selection
│   ├── server/
│   │   └── server.go           # Protocol-agnostic HTTP server
│   └── similarity/
│       └── similarity.go       # Protocol-agnostic fuzzy matching
└── web/
    ├── templates/
    │   └── index.html          # Main application template
    └── static/
        ├── style.css           # Application styles
        └── app.js              # Frontend JavaScript

Core Components

1. Protocol Abstraction Layer (internal/protocol/)

NEW in v2.0 - Generic email protocol interface

File: protocol.go Interface: EmailClient with 5 methods:

  • Authenticate() error
  • GetInboxEmailsWithCountPaginated(limit, offset int) (*InboxInfo, error)
  • GetInboxEmails(limit int) ([]Email, error)
  • ArchiveEmails(emailIDs []string, dryRun bool) error
  • Close() error

File: types.go Types: Protocol-agnostic data structures:

  • Email - Simplified email structure (BodyText, BodyHTML vs complex JMAP BodyValues)
  • EmailAddress - Name and email pair
  • InboxInfo - Emails with pagination metadata
  • ProtocolType - Enum for protocol selection

Design Philosophy:

  • Application-focused interface (what the app needs, not what protocols provide)
  • No protocol-specific concepts in the interface
  • Easy to add new protocols without changing application code

2. Protocol Providers (internal/providers/)

JMAP Provider (providers/jmap/) - ✅ Complete

File: client.go

  • Implements protocol.EmailClient interface
  • Converts JMAP-specific types to protocol types
  • Caches inbox/archive mailbox IDs for performance
  • Bearer token authentication
  • Full JMAP Email/query and Email/get support

File: types.go

  • JMAP-specific types: Session, Account, Request, Response
  • Internal jmapEmail struct with full JMAP fields
  • Conversion functions to protocol.Email

File: mock.go

  • Returns protocol.Email types
  • 40+ realistic sample emails
  • Simulates archive operations
  • Perfect for testing without Fastmail credentials

IMAP Provider (providers/imap/) - ✅ Complete

File: client.go

  • Implements protocol.EmailClient interface
  • Converts IMAP messages to protocol types
  • Username/password authentication
  • Full envelope data extraction (subject, from, to, cc, dates)
  • Flags extraction
  • Attachment detection via body structure
  • Archive operations: COPY + DELETE + EXPUNGE

Features:

  • ✅ TLS/SSL support (port 993)
  • ✅ Username/password authentication
  • ✅ Standard IMAP operations (SELECT, FETCH, COPY, STORE, EXPUNGE)
  • ✅ Configurable archive folder (Gmail's "[Gmail]/All Mail" or generic "Archive")
  • ✅ Email ID format: imap-{UID}
  • ✅ Conversion of IMAP messages to protocol.Email
  • ✅ Channel-based asynchronous message fetching
  • ✅ Pagination support with reverse chronological order

File: mock.go

  • Mock IMAP client for testing
  • Sample email data generation
  • Simulates archive operations
  • Perfect for testing without IMAP credentials

File: mock_test.go

  • Comprehensive unit tests (10 tests)
  • Tests all mock client functionality
  • Covers authentication, fetching, pagination, archiving

Library: emersion/go-imap v1.2.1 (stable)

3. Configuration System (internal/config/)

Updated in v2.0 - Protocol selection and multi-protocol support

Features:

  • Protocol Selection: protocol field ("jmap" or "imap")
  • JMAP Config: Endpoint and API token
  • IMAP Config: Host, port, username, password, TLS, archive folder
  • Validation: Protocol-specific credential validation
  • Backward Compatible: Defaults to "jmap" if protocol not specified

Configuration Structure:

type Config struct {
    Server   ServerConfig
    Protocol string  // "jmap" or "imap"
    JMAP     JMAPConfig
    IMAP     IMAPConfig
    DryRun   bool
    DefaultSimilarity int
    MockMode bool
}

4. Web Server (internal/server/)

Updated in v2.0 - Fully protocol-agnostic

Changes:

  • Uses protocol.EmailClient interface (not jmap.JMAPClient)
  • No protocol-specific knowledge
  • Works with any protocol.EmailClient implementation
  • Server doesn't know if it's using JMAP, IMAP, or future protocols

Endpoints: (unchanged)

  • GET / - Main application interface
  • GET /api/emails - Fetch inbox emails with pagination
  • POST /api/similar - Find similar emails with threshold
  • POST /api/archive - Archive selected emails
  • POST /api/clear - Clear results

5. Similarity Engine (internal/similarity/)

Updated in v2.0 - Uses protocol.Email

Changes:

  • Now uses protocol.Email instead of jmap.Email
  • Simplified body extraction (uses BodyText field directly)
  • Fully protocol-agnostic

Algorithm: (unchanged)

  • Subject Similarity (40% weight)
  • Sender Similarity (40% weight)
  • Content Similarity (20% weight)

6. Main Application (main.go)

Updated in v2.0 - Factory pattern for protocol selection

Factory Function: createEmailClient(cfg) (protocol.EmailClient, error)

  • Selects protocol based on cfg.Protocol
  • Handles both mock and real modes
  • Returns appropriate client implementation
  • Proper cleanup with defer client.Close()

Configuration

JMAP Configuration (Fastmail)

server:
  port: 8080
  host: "localhost"

protocol: "jmap"

jmap:
  endpoint: "https://api.fastmail.com/jmap/session"
  api_token: "your-api-token"

dry_run: true
default_similarity: 75
mock_mode: false

IMAP Configuration (Gmail)

server:
  port: 8080
  host: "localhost"

protocol: "imap"

imap:
  host: "imap.gmail.com"
  port: 993
  username: "user@gmail.com"
  password: "app-specific-password"
  use_tls: true
  archive_folder: "[Gmail]/All Mail"

dry_run: true
default_similarity: 75
mock_mode: false

Mock Mode (No Credentials Required)

server:
  port: 8080
  host: "localhost"

protocol: "jmap"  # or "imap" - both mocks fully functional

mock_mode: true
dry_run: true
default_similarity: 75

Development Commands

Building and Running

# Build
go build -o mailboxzero main.go

# Run with default config
go run main.go

# Run with custom config
go run main.go -config config-imap.yaml

# Run in mock mode (no credentials needed)
go run main.go -config config-mock.yaml.example

Testing

# Run all tests
go test ./...

# Run specific package tests
go test ./internal/config -v
go test ./internal/jmap -v
go test ./internal/protocol -v

# Run with coverage
go test ./... -cover
go test ./... -coverprofile=coverage.out
go tool cover -html=coverage.out

Dependencies

# Install/update dependencies
go mod download
go mod tidy

# IMAP dependencies (already in go.mod)
# Uses stable go-imap v1.2.1 (not beta v2)
go get github.com/emersion/go-imap@v1.2.1

Key Features

✅ Safety Features

  1. Dry Run Mode: Default enabled, prevents actual modifications
  2. Archive Only: Never deletes, only moves to archive
  3. Confirmation Dialogs: Required before operations
  4. Visual Warnings: Clear UI indicators for dry run
  5. Secure Authentication: API tokens (JMAP) or app passwords (IMAP)

✅ Core Functionality

  1. Dual-Pane Interface: Inbox and similar emails side-by-side
  2. Smart Similarity: Multi-factor fuzzy matching algorithm
  3. Adjustable Threshold: Real-time 0-100% similarity slider
  4. Email Selection: Individual and bulk selection
  5. Archive Operations: Safe bulk archiving
  6. Protocol Support: JMAP ✅ Full, IMAP ✅ Mock + Basic Real

✅ User Experience

  1. Responsive Design: Mobile and desktop optimized
  2. Loading States: Clear async feedback
  3. Error Handling: User-friendly messages
  4. Accessibility: Keyboard navigation
  5. Performance: Efficient operations

Migration Guide (v1.0 → v2.0)

For Existing Users (JMAP/Fastmail)

No action required! Your existing config files work without changes.

The system automatically defaults to "jmap" if no protocol is specified.

Optional: Make Protocol Explicit

Add protocol: "jmap" to your existing config.yaml for clarity.

To Switch to IMAP (When Available)

  1. Update config.yaml with protocol: "imap"
  2. Add IMAP configuration section
  3. Set appropriate archive_folder for your provider
  4. Restart application

Architecture Decisions

Why Protocol Abstraction?

  1. Extensibility: Easy to add new protocols (POP3, Exchange, etc.)
  2. Maintainability: Protocol changes don't affect application
  3. Testability: Mock implementations for all protocols
  4. Flexibility: Users choose their email provider
  5. Clean Code: Separation of concerns

Why Factory Pattern in main.go?

  1. Centralized: Single place for protocol selection logic
  2. Flexible: Easy to add conditions (features, permissions, etc.)
  3. Testable: Factory can be tested independently
  4. Clear: Explicit protocol creation and configuration

Why Simplified Email Types?

JMAP Problem: Complex BodyValues map[string]BodyValue + TextBody []BodyPart Solution: Simple BodyText string + BodyHTML string

Benefits:

  • Easier to work with in application code
  • Natural fit for IMAP (which has simpler structure)
  • Conversion happens in provider layer
  • Application doesn't care about protocol specifics

Testing Strategy

Test Coverage

  • Config Tests: All pass (18 tests)
  • JMAP Provider Tests: All pass (33 tests)
  • Similarity Tests: All pass (updated to protocol.Email)
  • Server Tests: All pass (updated to protocol.EmailClient)
  • Protocol Tests: No tests needed (interface definitions)
  • IMAP Provider Tests: 10 comprehensive tests (mock client fully tested)

Test Organization

  • Unit tests alongside implementation files
  • Table-driven tests for multiple scenarios
  • Mock clients for provider testing
  • Integration tests for end-to-end flows

Troubleshooting

JMAP Issues

Same as v1.0 - see backup documentation

IMAP Issues

  • Authentication: Check app-specific passwords for Gmail/Outlook
  • Archive Folder: Verify folder name matches provider convention ([Gmail]/All Mail for Gmail, Archive for others)
  • TLS: Most providers require TLS (port 993)
  • Permissions: Ensure account can read inbox and write to archive
  • Mock Mode: For testing, use mock_mode: true with protocol: "imap" - works perfectly with sample data

Configuration Issues

  • Invalid Protocol: Check spelling ("jmap" or "imap")
  • Missing Credentials: Verify required fields for selected protocol
  • Port Conflicts: Ensure port 8080 is available

IMAP Implementation Status

What Works ✅

  1. Mock IMAP Client - Fully functional

    • 40+ realistic sample emails
    • Multiple sender groups (Gmail, GitHub, LinkedIn, etc.)
    • Archive simulation
    • Perfect for development and testing
    • No credentials required
  2. Real IMAP Client - Core functionality

    • ✅ TLS/SSL connection (port 993)
    • ✅ Username/password authentication
    • ✅ INBOX selection
    • ✅ Message count retrieval
    • ✅ Pagination (reverse chronological order)
    • ✅ Archive operation (COPY → DELETE → EXPUNGE)
    • ✅ Configurable archive folder
    • ✅ Proper connection cleanup

Implementation Notes ✅

IMAP Implementation (v2.0):

  • ✅ Uses stable go-imap v1.2.1 (migrated from beta v2)
  • ✅ Full envelope data extraction (subject, from, to, cc, dates)
  • ✅ Complete flags extraction
  • ✅ Body structure parsing for attachment detection
  • ✅ Channel-based asynchronous message fetching
  • ✅ Preview generation from email content

Production Ready:

  • JMAP: Fully functional with Fastmail
  • IMAP: Fully functional with Gmail, Outlook, and any IMAP provider
  • Mock Mode: Available for both protocols for testing without credentials

IMAP vs JMAP Status

Feature JMAP IMAP Mock IMAP Real
Authentication
Email Fetching ✅ (count/pagination)
Envelope Data ✅ (full extraction)
Flags & Metadata
Attachment Detection ✅ (via body structure)
Archive
Similarity Matching
Mock Mode N/A

Future Enhancements

Phase 3 (COMPLETE)

  • ✅ Protocol abstraction complete
  • ✅ JMAP migrated to provider
  • ✅ Config supports both protocols
  • ✅ IMAP architecture implemented (auth, fetch, archive)
  • ✅ IMAP mock client (fully functional with 40+ sample emails)
  • ✅ All tests passing
  • ✅ Documentation updated

Phase 4 (COMPLETE - IMAP Full Implementation)

  • ✅ Migrated to go-imap v1 (stable API)
  • ✅ Full envelope data extraction (subject, from, to, cc, dates)
  • ✅ Flags extraction from IMAP messages
  • ✅ Body structure parsing for attachment detection
  • ✅ Preview generation from email content
  • ✅ IMAP provider unit tests (10 comprehensive tests)
  • ✅ Channel-based asynchronous fetching
  • ✅ Ready for real Gmail/Outlook/IMAP servers

Future Protocols

  • POP3: Basic email retrieval
  • Exchange Web Services: Microsoft Exchange
  • Custom APIs: Provider-specific APIs

Features

  • Database integration for operation history
  • Multi-account support
  • Advanced filters and rules
  • Undo functionality
  • Statistics dashboard

Known Limitations

Current (v2.0)

  • IMAP implementation in progress
  • IMAP mock not yet implemented
  • Some tests need updates for new types

General

  • Single account per session
  • In-memory email processing
  • No persistent operation history

Code Quality

Standards

  • Clean package organization
  • Comprehensive error handling
  • Interface-driven design
  • Table-driven tests
  • Clear documentation

Best Practices

  • Dependency injection
  • Factory pattern for creation
  • Protocol abstraction
  • Type safety
  • Minimal coupling

Note: v2.0 introduces protocol modularity while maintaining full backward compatibility. The application architecture is now extensible and ready for multiple email protocols.