fix: correct duplicate message reporting in Go implementation

- Add DocumentSkippedError custom error type to distinguish between skipped and stored documents
- Fix counter bug where skipped messages were incorrectly reported as "stored"
- Enhance status reporting to show "X skipped as duplicates" for better visibility
- Fix Rust implementation binary attachment handling to support all file types (images, PDFs, etc.)
- Update test scripts to use correct binary names (mail2couch-go, mail2couch-rs)
- Add comprehensive test configurations for implementation comparison

Before: "Summary: Processed 30 messages, stored 30 new messages" (misleading when all were duplicates)
After: "Summary: Processed 30 messages, stored 0 new messages" with detailed "Stored 0/30 messages from INBOX (30 skipped as duplicates)"

🤖 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-04 00:36:01 +02:00
commit 436276f0ef
9 changed files with 127 additions and 18 deletions

View file

@ -2,6 +2,7 @@ package main
import (
"context"
"errors"
"fmt"
"log"
"time"
@ -174,16 +175,26 @@ func processImapSource(source *config.MailSource, couchClient *couch.Client, dbN
stored := 0
if !dryRun {
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
var skipped int
for i, doc := range docs {
err := couchClient.StoreMessage(ctx, dbName, doc, messages[i])
if err != nil {
log.Printf(" ERROR: Failed to store message %s: %v", doc.ID, err)
var skipErr *couch.DocumentSkippedError
if errors.As(err, &skipErr) {
skipped++
} else {
log.Printf(" ERROR: Failed to store message %s: %v", doc.ID, err)
}
} else {
stored++
}
}
cancel()
fmt.Printf(" Stored %d/%d messages from %s\n", stored, len(messages), mailbox)
if skipped > 0 {
fmt.Printf(" Stored %d/%d messages from %s (%d skipped as duplicates)\n", stored, len(messages), mailbox, skipped)
} else {
fmt.Printf(" Stored %d/%d messages from %s\n", stored, len(messages), mailbox)
}
} else {
stored = len(messages) // In dry-run, assume all would be stored
fmt.Printf(" DRY-RUN: Would store %d messages from %s\n", len(messages), mailbox)