feat: add comprehensive README documentation and clean up configuration

## Documentation Enhancements
- Create comprehensive README with installation, configuration, and usage examples
- Add simple, advanced, and provider-specific configuration examples
- Document all features: incremental sync, wildcard patterns, keyword filtering, attachment support
- Include production deployment guidance and troubleshooting section
- Add architecture documentation with database structure and document format examples

## Configuration Cleanup
- Remove unnecessary `database` field from CouchDB configuration
- Add `m2c_` prefix to all CouchDB database names for better namespace isolation
- Update GenerateAccountDBName() to consistently prefix databases with `m2c_`
- Clean up all configuration examples to remove deprecated database field

## Test Environment Simplification
- Simplify test script structure to eliminate confusion and redundancy
- Remove redundant populate-test-messages.sh wrapper script
- Update run-tests.sh to be comprehensive automated test with cleanup
- Maintain clear separation: automated tests vs manual testing environment
- Update all test scripts to expect m2c-prefixed database names

## Configuration Examples Added
- config-simple.json: Basic single Gmail account setup
- config-advanced.json: Multi-account with complex filtering and different providers
- config-providers.json: Real-world configurations for Gmail, Outlook, Yahoo, iCloud

## Benefits
- Clear documentation for users from beginner to advanced
- Namespace isolation prevents database conflicts in shared CouchDB instances
- Simplified test workflow eliminates user confusion about which scripts to use
- Comprehensive examples cover common email provider configurations

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Ole-Morten Duesund 2025-08-01 21:26:53 +02:00
commit c2ad55eaaf
17 changed files with 1139 additions and 111 deletions

View file

@ -45,6 +45,18 @@ type AttachmentStub struct {
Stub bool `json:"stub,omitempty"`
}
// SyncMetadata represents sync state information stored in CouchDB
type SyncMetadata struct {
ID string `json:"_id,omitempty"`
Rev string `json:"_rev,omitempty"`
DocType string `json:"docType"` // Always "sync_metadata"
Mailbox string `json:"mailbox"` // Mailbox name
LastSyncTime time.Time `json:"lastSyncTime"` // When this mailbox was last synced
LastMessageUID uint32 `json:"lastMessageUID"` // Highest UID processed in last sync
MessageCount int `json:"messageCount"` // Number of messages processed in last sync
UpdatedAt time.Time `json:"updatedAt"` // When this metadata was last updated
}
// NewClient creates a new CouchDB client from the configuration
func NewClient(cfg *config.CouchDbConfig) (*Client, error) {
parsedURL, err := url.Parse(cfg.URL)
@ -88,9 +100,11 @@ func GenerateAccountDBName(accountName, userEmail string) string {
// CouchDB database names must match: ^[a-z][a-z0-9_$()+/-]*$
validName := regexp.MustCompile(`[^a-z0-9_$()+/-]`).ReplaceAllString(name, "_")
// Ensure it starts with a letter
// Ensure it starts with a letter and add m2c prefix
if len(validName) > 0 && (validName[0] < 'a' || validName[0] > 'z') {
validName = "mail_" + validName
validName = "m2c_mail_" + validName
} else {
validName = "m2c_" + validName
}
return validName
@ -307,3 +321,54 @@ func (c *Client) SyncMailbox(ctx context.Context, dbName, mailbox string, curren
return nil
}
// GetSyncMetadata retrieves the sync metadata for a specific mailbox
func (c *Client) GetSyncMetadata(ctx context.Context, dbName, mailbox string) (*SyncMetadata, error) {
db := c.DB(dbName)
if db.Err() != nil {
return nil, db.Err()
}
metadataID := fmt.Sprintf("sync_metadata_%s", mailbox)
row := db.Get(ctx, metadataID)
if row.Err() != nil {
// If metadata doesn't exist, return nil (not an error for first sync)
return nil, nil
}
var metadata SyncMetadata
if err := row.ScanDoc(&metadata); err != nil {
return nil, fmt.Errorf("failed to scan sync metadata: %w", err)
}
return &metadata, nil
}
// StoreSyncMetadata stores or updates sync metadata for a mailbox
func (c *Client) StoreSyncMetadata(ctx context.Context, dbName string, metadata *SyncMetadata) error {
db := c.DB(dbName)
if db.Err() != nil {
return db.Err()
}
metadata.ID = fmt.Sprintf("sync_metadata_%s", metadata.Mailbox)
metadata.DocType = "sync_metadata"
metadata.UpdatedAt = time.Now()
// Check if metadata already exists to get current revision
existing, err := c.GetSyncMetadata(ctx, dbName, metadata.Mailbox)
if err != nil {
return fmt.Errorf("failed to check existing sync metadata: %w", err)
}
if existing != nil {
metadata.Rev = existing.Rev
}
_, err = db.Put(ctx, metadata.ID, metadata)
if err != nil {
return fmt.Errorf("failed to store sync metadata: %w", err)
}
return nil
}