# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview This project downloads all emails from an IMAP server into individual EML files, preserving the folder hierarchy. Built with Go as a single self-contained binary, fast and cross-platform. ## Development Environment - Go 1.21+ required - Dependencies: `github.com/emersion/go-imap/v2` (auto-installed via `go mod tidy`) - Build with: `make build` or `go build` - Cross-compile with: `make build-all` ## Running the Application First, build the binary: ```bash make build # Or cross-compile for all platforms: make build-all ``` Basic usage (incremental mode - only downloads new emails): ```bash ./imapdown -server imap.example.com -email user@example.com -user user@example.com -password "password" -ssl ``` Full download (ignores previous state, requires empty target directory): ```bash ./imapdown -server imap.example.com -email user@example.com -user user@example.com -password "password" -ssl -full ``` Testing/debugging with limited emails: ```bash ./imapdown -server imap.example.com -email user@example.com -user user@example.com -password "password" -ssl -limit 10 ``` Custom storage directory: ```bash ./imapdown -server imap.example.com -email user@example.com -user user@example.com -password "password" -ssl -output /path/to/backup ``` ## Architecture ### Implementation Structure The code is organized into multiple files for clarity: - `main.go` - Entry point, CLI parsing, orchestration - `imap.go` - IMAP connection and folder operations - `email.go` - Email parsing and attachment extraction - `state.go` - State file management (JSON) - `filename.go` - Filename sanitization and Modified UTF-7 decoding - `Makefile` - Build targets ### State Tracking - The script maintains a `.imapdown_state.json` file in each email account's download folder - Tracks the highest UID (unique identifier) downloaded per IMAP folder - Format: `{"INBOX": 19334, "INBOX.Archive": 1770, "Sent": 892}` - Enables efficient incremental downloads (default mode) ### Download Flow 1. Parse arguments 2. Connect to IMAP server (SSL, STARTTLS, or plain) 3. List all folders and decode modified UTF-7 folder names 4. For each folder: - Load last downloaded UID from state file (if incremental mode) - Search for new messages (UID > last_uid) - Download each message as RFC822 - Save as `.eml` file with naming: `{UID}_{date}_{subject}.eml` - Extract attachments into `.zip` file (same base name) - Update state with highest UID 5. Save state file ### Key Implementation Details **Modified UTF-7 Decoding**: IMAP folder names use modified UTF-7 encoding. This is not standard base64 - it uses `,` instead of `/` and has special `&` handling. Implemented in `DecodeModifiedUTF7()` in `filename.go`. **Filename Sanitization**: Two-stage process: - `SanitizeFilename()`: Removes invalid filesystem characters, max 50 chars for subjects - `SanitizeFolderPath()`: Converts IMAP folder separators (`.` or `/`) to OS path separators **UID-Based Incremental Updates**: Uses IMAP UIDs (not sequence numbers) because UIDs are persistent. When `lastUID > 0`, searches for UIDs > lastUID. On first run (`lastUID == 0`), searches for all messages using an empty SearchCriteria. Some servers return the highest UID even when searching for higher UIDs, so there's additional filtering. **Full Mode Safety**: `-full` mode checks if the download folder already contains `.eml` files and refuses to run. This prevents accidental duplicates. Users must delete the folder first. **Attachment Handling**: - Walks message parts looking for `Content-Disposition: attachment` or `inline` - Handles duplicate attachment filenames by appending `_{counter}` - All attachments for one email go into a single `.zip` file ## Output Structure Without `-output` flag (default: `./{email_address}`): ``` {email_address}/ # sanitized email address in current directory ├── .imapdown_state.json ├── INBOX/ │ ├── 123_20240115_Meeting_notes.eml │ └── 124_20240116_Report.zip └── Sent/ └── 456_20240114_RE_Question.eml ``` With `-output /path/to/backup`: ``` /path/to/backup/ # specified output directory used directly ├── .imapdown_state.json ├── INBOX/ │ ├── 123_20240115_Meeting_notes.eml │ └── 124_20240116_Report.zip └── Sent/ └── 456_20240114_RE_Question.eml ``` ## Building and Installing Build for current platform: ```bash make build ``` Cross-compile for all platforms: ```bash make build-all # Produces: imapdown-linux-amd64, imapdown-linux-arm64, # imapdown-darwin-amd64, imapdown-darwin-arm64, # imapdown-windows-amd64.exe ``` Install to `$GOPATH/bin`: ```bash make install ``` Clean build artifacts: ```bash make clean ``` ## Testing No formal test suite exists. Manual testing approach: - Use `-limit 10` to download a small batch for verification - Test SSL vs STARTTLS connections - Test incremental mode by running twice - Verify `.eml` files open correctly in email clients - Check that folders with special characters (non-ASCII) are handled correctly - Test first run (no state file) to ensure all messages are downloaded