diff --git a/CLAUDE.md b/CLAUDE.md index ba23357..295351e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -5,121 +5,44 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## Project Overview mail2couch is a utility for backing up mail from various sources (primarily IMAP) to CouchDB. The project supports two implementations: -- **Go implementation**: Located in `/go/` directory, builds as `mail2couch-go` -- **Rust implementation**: Located in `/rust/` directory, builds as `mail2couch-rs` (fully functional, more advanced) +- **Go implementation**: Located in `/go/` directory (currently the active implementation) +- **Rust implementation**: Planned but not yet implemented ## Development Commands -### Universal Build Commands (Recommended) - -```bash -# Build both implementations -just build - -# Build individual implementations -just build-go # Builds go/mail2couch-go -just build-rust # Builds rust/target/release/mail2couch-rs - -# Build optimized release versions -just build-release - -# Install both binaries to ~/bin (user-local) -just install - -# Install both binaries to /usr/local/bin (system-wide) -sudo just system-install - -# Uninstall from ~/bin -just uninstall - -# Uninstall from /usr/local/bin -sudo just system-uninstall - -# Run tests for both implementations -just test - -# Clean all build artifacts -just clean - -# Format and check code -just fmt -just check - -# Show binary sizes -just sizes - -# Compare versions -just versions - -# List all available recipes -just --list -``` - -### Go Implementation +### Go Implementation (Primary) ```bash # Build the application -cd go && go build -o mail2couch-go . +cd go && go build -o mail2couch . # Run the application with automatic config discovery -cd go && ./mail2couch-go +cd go && ./mail2couch # Run with specific config file -cd go && ./mail2couch-go --config /path/to/config.json +cd go && ./mail2couch --config /path/to/config.json # Run with message limit (useful for large mailboxes) -cd go && ./mail2couch-go --max-messages 100 +cd go && ./mail2couch --max-messages 100 -# Run with dry-run mode -cd go && ./mail2couch-go --dry-run +# Run with both config and message limit +cd go && ./mail2couch --config /path/to/config.json --max-messages 50 # Run linting/static analysis cd go && go vet ./... -# Run unit tests -cd go && go test ./... - -# Check dependencies -cd go && go mod tidy -``` - -### Rust Implementation - -```bash -# Build the application (release mode recommended) -cd rust && cargo build --release - -# Run the application with automatic config discovery -cd rust && ./target/release/mail2couch-rs - -# Run with specific config file -cd rust && ./target/release/mail2couch-rs --config /path/to/config.json - -# Run with message limit -cd rust && ./target/release/mail2couch-rs --max-messages 100 - -# Run with dry-run mode -cd rust && ./target/release/mail2couch-rs --dry-run - -# Run linting/static analysis -cd rust && cargo clippy -- -D warnings - -# Run unit tests -cd rust && cargo test - -# Format code -cd rust && cargo fmt -``` - -### Integration Testing - -```bash # Run integration tests with Podman containers cd test && ./run-tests.sh # Run specialized tests cd test && ./test-wildcard-patterns.sh cd test && ./test-incremental-sync.sh + +# Run unit tests (none currently implemented) +cd go && go test ./... + +# Check dependencies +cd go && go mod tidy ``` ## Architecture @@ -167,11 +90,11 @@ This design ensures the same `config.json` format will work for both Go and Rust ### Current Implementation Status -#### Both Implementations - ✅ Configuration loading with automatic file discovery -- ✅ Command line flag support (--config/-c, --max-messages/-m, --dry-run/-n) +- ✅ Command line flag support for config file path - ✅ Per-account CouchDB database creation and management - ✅ IMAP connection and mailbox listing +- ✅ Build error fixes - ✅ Real IMAP message retrieval and parsing - ✅ Email storage to CouchDB framework with native attachments - ✅ Folder filtering logic with wildcard support (`*`, `?`, `[abc]` patterns) @@ -181,40 +104,15 @@ This design ensures the same `config.json` format will work for both Go and Rust - ✅ Sync vs Archive mode implementation - ✅ CouchDB attachment storage for email attachments - ✅ Full message body and attachment handling with MIME multipart support +- ✅ Command line argument support (GNU-style --max-messages/-m and --config/-c flags) - ✅ Per-account CouchDB databases for better organization - ✅ Incremental sync functionality with IMAP SEARCH and sync metadata tracking -- ✅ Comprehensive --dry-run mode for safe configuration testing - -#### Rust Implementation Additional Features -- ✅ Asynchronous processing with concurrent network operations -- ✅ Server-side IMAP keyword filtering (more efficient) -- ✅ Automatic retry logic with exponential backoff -- ✅ Structured error handling with detailed context -- ✅ Enhanced CLI with rich help system -- ✅ Comprehensive unit test coverage -- ✅ Emoji-enhanced logging for better user experience - -#### Go Implementation Characteristics -- ✅ Sequential processing (simple and reliable) -- ✅ Minimal dependencies and fast compilation -- ✅ Client-side keyword filtering -- ✅ Basic error handling with continue-on-error semantics +- ❌ Rust implementation ### Key Dependencies -#### Go Implementation - `github.com/emersion/go-imap/v2`: IMAP client library - `github.com/go-kivik/kivik/v4`: CouchDB client library -- `github.com/spf13/pflag`: GNU-style command line flags -- `github.com/emersion/go-message`: Email parsing - -#### Rust Implementation -- `async-imap`: Asynchronous IMAP client -- `reqwest`: HTTP client for CouchDB API -- `tokio`: Async runtime and utilities -- `clap`: Command line argument parsing -- `serde`: Serialization framework -- `mail-parser`: Email parsing with MIME support ### Incremental Sync Implementation diff --git a/IMPLEMENTATION_COMPARISON.md b/IMPLEMENTATION_COMPARISON.md index 4288f27..4275ef5 100644 --- a/IMPLEMENTATION_COMPARISON.md +++ b/IMPLEMENTATION_COMPARISON.md @@ -442,8 +442,6 @@ Both implementations currently share the same security limitations and features: ### Go Implementation Deployment -**Binary Name**: `mail2couch-go` - **Advantages**: - Single binary deployment - Minimal system dependencies @@ -452,21 +450,16 @@ Both implementations currently share the same security limitations and features: **Best Practices**: ```bash -# Build for production using justfile -just build-go-release - -# Or build directly -cd go && go build -ldflags="-s -w" -o mail2couch-go . +# Build for production +cd go && go build -ldflags="-s -w" -o mail2couch . # Deploy with systemd service -sudo cp go/mail2couch-go /usr/local/bin/ -sudo systemctl enable mail2couch-go.service +sudo cp mail2couch /usr/local/bin/ +sudo systemctl enable mail2couch.service ``` ### Rust Implementation Deployment -**Binary Name**: `mail2couch-rs` - **Advantages**: - Better resource utilization under load - Superior error recovery @@ -475,33 +468,18 @@ sudo systemctl enable mail2couch-go.service **Best Practices**: ```bash -# Build optimized release using justfile -just build-rust-release - -# Or build directly +# Build optimized release cd rust && cargo build --release # Deploy with enhanced monitoring -sudo cp rust/target/release/mail2couch-rs /usr/local/bin/ -sudo systemctl enable mail2couch-rs.service +sudo cp target/release/mail2couch /usr/local/bin/ +sudo systemctl enable mail2couch.service # Configure structured logging export RUST_LOG=info export MAIL2COUCH_LOG_FORMAT=json ``` -### Universal Installation - -```bash -# Build and install both implementations (user-local) -just install -# This installs to ~/bin/mail2couch-go and ~/bin/mail2couch-rs - -# Build and install both implementations (system-wide) -sudo just system-install -# This installs to /usr/local/bin/mail2couch-go and /usr/local/bin/mail2couch-rs -``` - --- ## Future Development Roadmap diff --git a/go/couch/couch.go b/go/couch/couch.go index 5ad565b..c75c3b6 100644 --- a/go/couch/couch.go +++ b/go/couch/couch.go @@ -15,15 +15,6 @@ import ( "mail2couch/mail" ) -// DocumentSkippedError indicates that a document was skipped because it already exists -type DocumentSkippedError struct { - DocumentID string -} - -func (e *DocumentSkippedError) Error() string { - return fmt.Sprintf("document %s already exists, skipped", e.DocumentID) -} - // Client wraps the Kivik client type Client struct { *kivik.Client @@ -158,7 +149,7 @@ func (c *Client) StoreMessage(ctx context.Context, dbName string, doc *MailDocum } if exists { - return &DocumentSkippedError{DocumentID: doc.ID} + return nil // Document already exists, skip } // Store the document first (without attachments) diff --git a/go/mail2couch-go b/go/mail2couch similarity index 64% rename from go/mail2couch-go rename to go/mail2couch index 11b890c..cd300c5 100755 Binary files a/go/mail2couch-go and b/go/mail2couch differ diff --git a/go/main.go b/go/main.go index fa04250..1523b09 100644 --- a/go/main.go +++ b/go/main.go @@ -2,7 +2,6 @@ package main import ( "context" - "errors" "fmt" "log" "time" @@ -175,26 +174,16 @@ 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 { - var skipErr *couch.DocumentSkippedError - if errors.As(err, &skipErr) { - skipped++ - } else { - log.Printf(" ERROR: Failed to store message %s: %v", doc.ID, err) - } + log.Printf(" ERROR: Failed to store message %s: %v", doc.ID, err) } else { stored++ } } cancel() - 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) - } + 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) diff --git a/justfile b/justfile deleted file mode 100644 index 4a24fb5..0000000 --- a/justfile +++ /dev/null @@ -1,229 +0,0 @@ -# Justfile for mail2couch project -# Builds both Go and Rust implementations with distinct binary names - -# Default recipe -default: build - -# Build both implementations -build: build-go build-rust - -# Build Go implementation as mail2couch-go -build-go: - @echo "Building Go implementation..." - cd go && go build -o mail2couch-go . - @echo "✅ Built: go/mail2couch-go" - -# Build Rust implementation as mail2couch-rs -build-rust: - @echo "Building Rust implementation..." - cd rust && cargo build --release - @echo "✅ Built: rust/target/release/mail2couch-rs" - -# Build optimized release versions -build-release: build-go-release build-rust-release - -# Build optimized Go release -build-go-release: - @echo "Building optimized Go release..." - cd go && go build -ldflags="-s -w" -o mail2couch-go . - @echo "✅ Built optimized: go/mail2couch-go" - -# Build optimized Rust release (already built with --release above) -build-rust-release: build-rust - -# Install binaries to ~/bin (user-local installation) -install: build-release - @echo "Installing binaries to ~/bin..." - mkdir -p ~/bin - cp go/mail2couch-go ~/bin/ - cp rust/target/release/mail2couch-rs ~/bin/ - chmod +x ~/bin/mail2couch-go - chmod +x ~/bin/mail2couch-rs - @echo "✅ Installed mail2couch-go and mail2couch-rs to ~/bin" - @echo "💡 Make sure ~/bin is in your PATH" - -# Install binaries to /usr/local/bin (system-wide installation, requires sudo) -system-install: build-release - @echo "Installing binaries to /usr/local/bin..." - sudo cp go/mail2couch-go /usr/local/bin/ - sudo cp rust/target/release/mail2couch-rs /usr/local/bin/ - sudo chmod +x /usr/local/bin/mail2couch-go - sudo chmod +x /usr/local/bin/mail2couch-rs - @echo "✅ Installed mail2couch-go and mail2couch-rs to /usr/local/bin" - -# Uninstall binaries from ~/bin -uninstall: - @echo "Uninstalling binaries from ~/bin..." - rm -f ~/bin/mail2couch-go - rm -f ~/bin/mail2couch-rs - @echo "✅ Uninstalled mail2couch-go and mail2couch-rs from ~/bin" - -# Uninstall binaries from /usr/local/bin (requires sudo) -system-uninstall: - @echo "Uninstalling binaries from /usr/local/bin..." - sudo rm -f /usr/local/bin/mail2couch-go - sudo rm -f /usr/local/bin/mail2couch-rs - @echo "✅ Uninstalled mail2couch-go and mail2couch-rs from /usr/local/bin" - -# Run tests for both implementations -test: test-go test-rust - -# Test Go implementation -test-go: - @echo "Running Go tests..." - cd go && go test ./... - -# Test Rust implementation -test-rust: - @echo "Running Rust tests..." - cd rust && cargo test - -# Clean build artifacts -clean: - @echo "Cleaning build artifacts..." - cd go && rm -f mail2couch-go mail2couch - cd rust && cargo clean - @echo "✅ Cleaned build artifacts" - -# Check code formatting and linting -check: check-go check-rust - -# Check Go code -check-go: - @echo "Checking Go code..." - cd go && go fmt ./... - cd go && go vet ./... - -# Check Rust code -check-rust: - @echo "Checking Rust code..." - cd rust && cargo fmt --check - cd rust && cargo clippy -- -D warnings - -# Fix code formatting -fmt: fmt-go fmt-rust - -# Format Go code -fmt-go: - @echo "Formatting Go code..." - cd go && go fmt ./... - -# Format Rust code -fmt-rust: - @echo "Formatting Rust code..." - cd rust && cargo fmt - -# Development convenience - build and test Go version -dev-go: build-go - ./go/mail2couch-go --help - -# Development convenience - build and test Rust version -dev-rust: build-rust - ./rust/target/release/mail2couch-rs --help - -# Show binary sizes -sizes: build - @echo "Binary sizes:" - @ls -lh go/mail2couch-go rust/target/release/mail2couch-rs | awk '{print $5 "\t" $9}' - -# Run both binaries with --version to compare -versions: build - @echo "Go version:" - @./go/mail2couch-go --help | head -1 - @echo "" - @echo "Rust version:" - @./rust/target/release/mail2couch-rs --version - -# Clean and rebuild everything -rebuild: clean build - -# Systemd service management - -# Install systemd user service files -install-services: - @echo "Installing systemd user service files..." - mkdir -p ~/.config/systemd/user - cp systemd/*.service ~/.config/systemd/user/ - cp systemd/*.timer ~/.config/systemd/user/ - systemctl --user daemon-reload - @echo "✅ Installed systemd user services and timers" - @echo "💡 Enable with: systemctl --user enable mail2couch-{go,rs}.service" - @echo "💡 Enable timers with: systemctl --user enable mail2couch-{go,rs}.timer" - -# Uninstall systemd user service files -uninstall-services: - @echo "Uninstalling systemd user service files..." - systemctl --user stop mail2couch-go.service mail2couch-rs.service || true - systemctl --user stop mail2couch-go.timer mail2couch-rs.timer || true - systemctl --user stop mail2couch-go-hourly.timer mail2couch-rs-hourly.timer || true - systemctl --user stop mail2couch-go-daily.timer mail2couch-rs-daily.timer || true - systemctl --user disable mail2couch-go.service mail2couch-rs.service || true - systemctl --user disable mail2couch-go.timer mail2couch-rs.timer || true - systemctl --user disable mail2couch-go-hourly.timer mail2couch-rs-hourly.timer || true - systemctl --user disable mail2couch-go-daily.timer mail2couch-rs-daily.timer || true - rm -f ~/.config/systemd/user/mail2couch-*.service - rm -f ~/.config/systemd/user/mail2couch-*.timer - systemctl --user daemon-reload - @echo "✅ Uninstalled systemd user services and timers" - -# Show systemd service status -service-status: - @echo "Service status:" - systemctl --user status mail2couch-go.service || true - systemctl --user status mail2couch-rs.service || true - @echo "" - @echo "Timer status:" - systemctl --user list-timers mail2couch-* - -# Enable Go implementation with default 30-minute timer -enable-go: - systemctl --user enable mail2couch-go.service - systemctl --user enable mail2couch-go.timer - systemctl --user start mail2couch-go.timer - @echo "✅ Enabled Go implementation with 30-minute timer" - -# Enable Rust implementation with default 30-minute timer -enable-rust: - systemctl --user enable mail2couch-rs.service - systemctl --user enable mail2couch-rs.timer - systemctl --user start mail2couch-rs.timer - @echo "✅ Enabled Rust implementation with 30-minute timer" - -# Enable Go implementation with hourly timer -enable-go-hourly: - systemctl --user enable mail2couch-go.service - systemctl --user enable mail2couch-go-hourly.timer - systemctl --user start mail2couch-go-hourly.timer - @echo "✅ Enabled Go implementation with hourly timer" - -# Enable Rust implementation with hourly timer -enable-rust-hourly: - systemctl --user enable mail2couch-rs.service - systemctl --user enable mail2couch-rs-hourly.timer - systemctl --user start mail2couch-rs-hourly.timer - @echo "✅ Enabled Rust implementation with hourly timer" - -# Enable Go implementation with daily timer -enable-go-daily: - systemctl --user enable mail2couch-go.service - systemctl --user enable mail2couch-go-daily.timer - systemctl --user start mail2couch-go-daily.timer - @echo "✅ Enabled Go implementation with daily timer" - -# Enable Rust implementation with daily timer -enable-rust-daily: - systemctl --user enable mail2couch-rs.service - systemctl --user enable mail2couch-rs-daily.timer - systemctl --user start mail2couch-rs-daily.timer - @echo "✅ Enabled Rust implementation with daily timer" - -# Disable all timers and services -disable-all: - systemctl --user stop mail2couch-go.timer mail2couch-rs.timer || true - systemctl --user stop mail2couch-go-hourly.timer mail2couch-rs-hourly.timer || true - systemctl --user stop mail2couch-go-daily.timer mail2couch-rs-daily.timer || true - systemctl --user disable mail2couch-go.timer mail2couch-rs.timer || true - systemctl --user disable mail2couch-go-hourly.timer mail2couch-rs-hourly.timer || true - systemctl --user disable mail2couch-go-daily.timer mail2couch-rs-daily.timer || true - systemctl --user disable mail2couch-go.service mail2couch-rs.service || true - @echo "✅ Disabled all timers and services" \ No newline at end of file diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 2b070ac..b10a27e 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -65,5 +65,5 @@ name = "mail2couch" path = "src/lib.rs" [[bin]] -name = "mail2couch-rs" +name = "mail2couch" path = "src/main.rs" \ No newline at end of file diff --git a/rust/src/imap.rs b/rust/src/imap.rs index 0b24ed7..6b3d553 100644 --- a/rust/src/imap.rs +++ b/rust/src/imap.rs @@ -578,9 +578,9 @@ impl ImapClient { let headers = self.extract_headers(&parsed_message); // Extract attachments and their data - let (has_attachments, _attachment_stubs, attachment_data) = self.extract_attachments_with_data(&parsed_message); + let (has_attachments, attachment_stubs, attachment_data) = self.extract_attachments_with_data(&parsed_message); - let mail_doc = MailDocument::new( + let mut mail_doc = MailDocument::new( uid.to_string(), mailbox.to_string(), from, @@ -705,14 +705,21 @@ impl ImapClient { // Generate a filename for the attachment let filename = self.get_attachment_filename(part, index); - // Get the binary content data using the proper mail-parser API - // This works for both text and binary attachments (images, PDFs, etc.) - let body_data = part.get_contents().to_vec(); - log::debug!("Found attachment content: {} bytes (content-type: {})", body_data.len(), content_type.c_type); + // Get the content data (try different methods based on content type) + let body_data = if let Some(text_content) = part.get_text_contents() { + // Text-based attachments + log::debug!("Found text attachment content: {} bytes", text_content.len()); + text_content.as_bytes().to_vec() + } else { + // For now, skip attachments without text content + // TODO: Implement binary attachment support with proper mail-parser API + log::debug!("Skipping non-text attachment for part {} (content-type: {})", index, content_type.c_type); + vec![] + }; let content_type_str = content_type.c_type.to_string(); - // Create attachment stub - get_contents() always returns the full data + // Only create attachment stub if we have actual data if !body_data.is_empty() { let attachment_stub = AttachmentStub { content_type: content_type_str.clone(), @@ -731,6 +738,12 @@ impl ImapClient { (has_attachments, attachment_stubs, attachment_data) } + /// Extract attachments from a parsed message (deprecated - use extract_attachments_with_data) + /// Returns (has_attachments, attachment_stubs) + fn extract_attachments(&self, message: &Message) -> (bool, HashMap) { + let (has_attachments, attachment_stubs, _) = self.extract_attachments_with_data(message); + (has_attachments, attachment_stubs) + } /// Determine if a message part is an attachment fn is_attachment_part(&self, part: &mail_parser::MessagePart, content_type: &mail_parser::ContentType) -> bool { diff --git a/systemd/mail2couch-go-daily.timer b/systemd/mail2couch-go-daily.timer deleted file mode 100644 index fab6817..0000000 --- a/systemd/mail2couch-go-daily.timer +++ /dev/null @@ -1,17 +0,0 @@ -[Unit] -Description=Run mail2couch Go Implementation daily -Documentation=https://kode.naiv.no/olemd/mail2couch -Requires=mail2couch-go.service - -[Timer] -# Run daily at 2:30 AM with some randomization -OnCalendar=*-*-* 02:30:00 -# Run 10 minutes after boot if we missed a scheduled run -OnBootSec=10min -# If the system was off, run shortly after startup -Persistent=true -# Add up to 30 minutes randomization to spread load -RandomizedDelaySec=1800 - -[Install] -WantedBy=timers.target \ No newline at end of file diff --git a/systemd/mail2couch-go-hourly.timer b/systemd/mail2couch-go-hourly.timer deleted file mode 100644 index bfd159d..0000000 --- a/systemd/mail2couch-go-hourly.timer +++ /dev/null @@ -1,17 +0,0 @@ -[Unit] -Description=Run mail2couch Go Implementation every hour -Documentation=https://kode.naiv.no/olemd/mail2couch -Requires=mail2couch-go.service - -[Timer] -# Run every hour at a random minute to spread load -OnCalendar=hourly -# Run 5 minutes after boot if we missed a scheduled run -OnBootSec=5min -# If the system was off, run shortly after startup -Persistent=true -# Add randomization to avoid all users hitting servers simultaneously -RandomizedDelaySec=600 - -[Install] -WantedBy=timers.target \ No newline at end of file diff --git a/systemd/mail2couch-go.service b/systemd/mail2couch-go.service deleted file mode 100644 index fcd8660..0000000 --- a/systemd/mail2couch-go.service +++ /dev/null @@ -1,35 +0,0 @@ -[Unit] -Description=mail2couch Go Implementation - Email backup to CouchDB -Documentation=https://kode.naiv.no/olemd/mail2couch -After=network.target -Wants=network.target - -[Service] -Type=oneshot -User=%i -ExecStart=%h/bin/mail2couch-go -WorkingDirectory=%h/.config/mail2couch - -# Environment -Environment=PATH=%h/bin:/usr/local/bin:/usr/bin:/bin - -# Logging -StandardOutput=journal -StandardError=journal -SyslogIdentifier=mail2couch-go - -# Security settings -NoNewPrivileges=yes -PrivateTmp=yes -ProtectSystem=strict -ProtectHome=read-only -ReadOnlyPaths=/ -ReadWritePaths=%h/.config/mail2couch %h/.local/share/mail2couch - -# Resource limits -MemoryHigh=512M -MemoryMax=1G -CPUQuota=50% - -[Install] -WantedBy=default.target \ No newline at end of file diff --git a/systemd/mail2couch-go.timer b/systemd/mail2couch-go.timer deleted file mode 100644 index d83e127..0000000 --- a/systemd/mail2couch-go.timer +++ /dev/null @@ -1,17 +0,0 @@ -[Unit] -Description=Run mail2couch Go Implementation every 30 minutes -Documentation=https://kode.naiv.no/olemd/mail2couch -Requires=mail2couch-go.service - -[Timer] -# Run every 30 minutes -OnCalendar=*:0/30 -# Run 2 minutes after boot if we missed a scheduled run -OnBootSec=2min -# If the system was off, run shortly after startup -Persistent=true -# Add some randomization to avoid all users hitting servers simultaneously -RandomizedDelaySec=300 - -[Install] -WantedBy=timers.target \ No newline at end of file diff --git a/systemd/mail2couch-rs-daily.timer b/systemd/mail2couch-rs-daily.timer deleted file mode 100644 index 1439f0e..0000000 --- a/systemd/mail2couch-rs-daily.timer +++ /dev/null @@ -1,17 +0,0 @@ -[Unit] -Description=Run mail2couch Rust Implementation daily -Documentation=https://kode.naiv.no/olemd/mail2couch -Requires=mail2couch-rs.service - -[Timer] -# Run daily at 2:30 AM with some randomization -OnCalendar=*-*-* 02:30:00 -# Run 10 minutes after boot if we missed a scheduled run -OnBootSec=10min -# If the system was off, run shortly after startup -Persistent=true -# Add up to 30 minutes randomization to spread load -RandomizedDelaySec=1800 - -[Install] -WantedBy=timers.target \ No newline at end of file diff --git a/systemd/mail2couch-rs-hourly.timer b/systemd/mail2couch-rs-hourly.timer deleted file mode 100644 index 6f48658..0000000 --- a/systemd/mail2couch-rs-hourly.timer +++ /dev/null @@ -1,17 +0,0 @@ -[Unit] -Description=Run mail2couch Rust Implementation every hour -Documentation=https://kode.naiv.no/olemd/mail2couch -Requires=mail2couch-rs.service - -[Timer] -# Run every hour at a random minute to spread load -OnCalendar=hourly -# Run 5 minutes after boot if we missed a scheduled run -OnBootSec=5min -# If the system was off, run shortly after startup -Persistent=true -# Add randomization to avoid all users hitting servers simultaneously -RandomizedDelaySec=600 - -[Install] -WantedBy=timers.target \ No newline at end of file diff --git a/systemd/mail2couch-rs.service b/systemd/mail2couch-rs.service deleted file mode 100644 index 3fa4714..0000000 --- a/systemd/mail2couch-rs.service +++ /dev/null @@ -1,36 +0,0 @@ -[Unit] -Description=mail2couch Rust Implementation - Email backup to CouchDB -Documentation=https://kode.naiv.no/olemd/mail2couch -After=network.target -Wants=network.target - -[Service] -Type=oneshot -User=%i -ExecStart=%h/bin/mail2couch-rs -WorkingDirectory=%h/.config/mail2couch - -# Environment -Environment=PATH=%h/bin:/usr/local/bin:/usr/bin:/bin -Environment=RUST_LOG=info - -# Logging -StandardOutput=journal -StandardError=journal -SyslogIdentifier=mail2couch-rs - -# Security settings -NoNewPrivileges=yes -PrivateTmp=yes -ProtectSystem=strict -ProtectHome=read-only -ReadOnlyPaths=/ -ReadWritePaths=%h/.config/mail2couch %h/.local/share/mail2couch - -# Resource limits -MemoryHigh=512M -MemoryMax=1G -CPUQuota=50% - -[Install] -WantedBy=default.target \ No newline at end of file diff --git a/systemd/mail2couch-rs.timer b/systemd/mail2couch-rs.timer deleted file mode 100644 index 4483fe4..0000000 --- a/systemd/mail2couch-rs.timer +++ /dev/null @@ -1,17 +0,0 @@ -[Unit] -Description=Run mail2couch Rust Implementation every 30 minutes -Documentation=https://kode.naiv.no/olemd/mail2couch -Requires=mail2couch-rs.service - -[Timer] -# Run every 30 minutes -OnCalendar=*:0/30 -# Run 2 minutes after boot if we missed a scheduled run -OnBootSec=2min -# If the system was off, run shortly after startup -Persistent=true -# Add some randomization to avoid all users hitting servers simultaneously -RandomizedDelaySec=300 - -[Install] -WantedBy=timers.target \ No newline at end of file diff --git a/test-both-implementations.sh b/test-both-implementations.sh index 35c8e05..4319a72 100755 --- a/test-both-implementations.sh +++ b/test-both-implementations.sh @@ -36,7 +36,7 @@ build_implementations() { # Build Go implementation echo -e "${BLUE} Building Go implementation...${NC}" cd go - go build -o mail2couch-go . + go build -o mail2couch . cd .. echo -e "${GREEN} ✅ Go implementation built${NC}" @@ -53,7 +53,7 @@ run_go() { echo -e "${BLUE}🦬 Running Go implementation...${NC}" cd go echo -e "${BLUE} Using config: config-test-go.json${NC}" - ./mail2couch-go -c config-test-go.json + ./mail2couch -c config-test-go.json cd .. echo -e "${GREEN}✅ Go implementation completed${NC}" } @@ -63,7 +63,7 @@ run_rust() { echo -e "${BLUE}🦀 Running Rust implementation...${NC}" cd rust echo -e "${BLUE} Using config: config-test-rust.json${NC}" - ./target/release/mail2couch-rs -c config-test-rust.json + ./target/release/mail2couch -c config-test-rust.json cd .. echo -e "${GREEN}✅ Rust implementation completed${NC}" } diff --git a/test-config-go.json b/test-config-go.json deleted file mode 100644 index 1be5cce..0000000 --- a/test-config-go.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "couchDb": { - "url": "http://localhost:5984", - "user": "admin", - "password": "password" - }, - "mailSources": [ - { - "name": "go_test_account", - "enabled": true, - "protocol": "imap", - "host": "localhost", - "port": 3143, - "user": "testuser1", - "password": "password123", - "mode": "archive", - "folderFilter": { - "include": ["INBOX"], - "exclude": [] - }, - "messageFilter": {} - } - ] -} \ No newline at end of file diff --git a/test-config-rust.json b/test-config-rust.json deleted file mode 100644 index 7229196..0000000 --- a/test-config-rust.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "couchDb": { - "url": "http://localhost:5984", - "user": "admin", - "password": "password" - }, - "mailSources": [ - { - "name": "rust_test_account", - "enabled": true, - "protocol": "imap", - "host": "localhost", - "port": 3143, - "user": "testuser1", - "password": "password123", - "mode": "archive", - "folderFilter": { - "include": ["INBOX"], - "exclude": [] - }, - "messageFilter": {} - } - ] -} \ No newline at end of file diff --git a/test-config-shared.json b/test-config-shared.json deleted file mode 100644 index 79fe83e..0000000 --- a/test-config-shared.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "couchDb": { - "url": "http://localhost:5984", - "user": "admin", - "password": "password" - }, - "mailSources": [ - { - "name": "comparison_test_account", - "enabled": true, - "protocol": "imap", - "host": "localhost", - "port": 3143, - "user": "testuser1", - "password": "password123", - "mode": "archive", - "folderFilter": { - "include": ["INBOX"], - "exclude": [] - }, - "messageFilter": {} - } - ] -} \ No newline at end of file diff --git a/test-incremental-config.json b/test-incremental-config.json deleted file mode 100644 index eed0415..0000000 --- a/test-incremental-config.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "couchDb": { - "url": "http://localhost:5984", - "user": "admin", - "password": "password" - }, - "mailSources": [ - { - "name": "incremental_test", - "enabled": true, - "protocol": "imap", - "host": "localhost", - "port": 3143, - "user": "testuser1", - "password": "password123", - "mode": "archive", - "folderFilter": { - "include": ["INBOX"], - "exclude": [] - }, - "messageFilter": {} - } - ] -} \ No newline at end of file