6.0 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
ParaClub AI Mailer is an automated email response system written in Go that:
- Fetches emails via IMAP from a configured mailbox
- Gathers context from configured URLs (HTML content extraction)
- Uses OpenRouter AI API to generate context-aware email replies
- Saves AI-generated responses as email drafts
- Processes emails sequentially with configurable polling intervals
The system is designed as a long-running service with graceful shutdown handling.
Build and Run Commands
# Install dependencies
go mod download
# Build the application
go build -o paraclub-ai-mailer ./cmd/paraclub-ai-mailer
# Run with default config (config.yaml in current directory)
./paraclub-ai-mailer
# Run with custom config path
./paraclub-ai-mailer -config /path/to/config.yaml
# Run tests (if any exist)
go test ./...
# Format code
go fmt ./...
# Vet code for issues
go vet ./...
Configuration
The application requires a config.yaml file. Use config.yaml.example as a template.
Key configuration sections:
- imap: Server details, credentials, mailbox folders
- ai: OpenRouter API key, model selection, temperature, max tokens
- context: List of URLs to fetch as context for AI
- polling: Email check interval (e.g., "5m")
- logging: Log level and file path
Credentials support three formats:
- Direct value:
password: "mypassword" - Environment variable:
password: "${IMAP_PASSWORD}" - File reference:
password: "file:///path/to/password.txt"
Code Architecture
Module Structure
cmd/paraclub-ai-mailer/main.go # Entry point, orchestration
config/config.go # Configuration loading and validation
internal/
├── logger/logger.go # Centralized logging wrapper (logrus)
├── imap/imap.go # IMAP client, email operations
├── fetcher/fetcher.go # HTML content fetching and text extraction
└── ai/ai.go # OpenRouter AI integration
Key Design Patterns
Email Processing Flow (main.go:92-172):
- Fetch unprocessed emails (UNSEEN flag)
- Fetch context from all configured URLs
- For each email:
- Detect language via AI
- Generate AI reply with context
- Save as draft with original email quoted
- Mark as processed (move to processed_box, mark as read)
IMAP Client (internal/imap/imap.go):
- Connection handling with automatic reconnection (ensureConnection, reconnect)
- Folder path normalization with delimiter detection
- Gmail-specific logic in ensureFolder (uses "/" delimiter, handles system folders)
- Email content extraction handles multipart messages and quoted-printable encoding
- Draft formatting includes HTML response + quoted original message
- Panic recovery in SaveDraft and MarkAsProcessed
AI Integration (internal/ai/ai.go):
- Two-stage process: language detection, then reply generation
- Language-aware responses (system prompt includes detected language)
- Output must be raw HTML (not markdown-wrapped)
- Retry logic with max 3 attempts
Context Fetching (internal/fetcher/fetcher.go):
- HTML to plain text extraction (strips tags, extracts text nodes)
- 30-second timeout per URL
- Batch fetching fails if any URL fails
Important Implementation Details
MIME Email Parsing (internal/imap/imap.go:287-510):
extractMessageContenthandles multipart and single-part messages- Content-Transfer-Encoding support: quoted-printable
cleanMessageContenthas aperformHeaderStrippingflag (true for fallback, false for parsed content)- Extensive debug logging for troubleshooting email parsing issues
Folder Management (internal/imap/imap.go:512-663):
ensureFolderdetects Gmail vs generic IMAP servers- Gmail: Uses "/" delimiter, skips CREATE for system folders like "[Gmail]/Drafts"
- Generic IMAP: Lists mailboxes to detect delimiter, creates folders if missing
- Has timeout protection (30s for LIST, 35s overall)
- Includes panic recovery
Logging Strategy:
- All modules use
internal/loggerwrapper around logrus - Structured logging with fields (logrus.Fields)
- Debug level logs include detailed information (e.g., email content lengths, folder paths)
- Recent commits show enhanced logging for troubleshooting email extraction
Development Guidelines
Error Handling
- Use defer/recover for panic protection in critical IMAP operations (SaveDraft, MarkAsProcessed, ensureFolder)
- Retry mechanisms in AI client (max 3 attempts)
- IMAP connection auto-reconnection on failure
- Continue processing remaining emails if one fails
Adding New Features
- New AI models: Update config.yaml model parameter (passed to OpenRouter API)
- New context sources: Add URLs to config.yaml context.urls array
- New IMAP operations: Add methods to IMAPClient struct, ensure connection handling
- Email format changes: Modify draft template in SaveDraft (line 242-266)
Testing Considerations
- Email parsing logic is complex (multipart, encoding) - test with various email formats
- Gmail behavior differs from generic IMAP servers
- Test with different folder delimiters ("/" vs ".")
- Language detection affects response language
Dependencies
Core dependencies (go.mod):
github.com/emersion/go-imap- IMAP client librarygithub.com/sirupsen/logrus- Structured logginggolang.org/x/net/html- HTML parsing for context extractiongopkg.in/yaml.v3- Configuration file parsing
Common Issues
IMAP Folder Issues:
- Check logs for delimiter detection (ensureFolder)
- Gmail requires special handling for system folders
- Folder names are case-sensitive
Email Content Extraction:
- Multi-part emails may require different handling
- Check Content-Transfer-Encoding header
- Recent fixes improved header stripping and content cleaning
AI Response Issues:
- Verify API key is correctly loaded from environment/file
- Check model name is valid for OpenRouter
- Response must be raw HTML (system prompt enforces this)