diff --git a/Makefile b/Makefile deleted file mode 100644 index 0415953..0000000 --- a/Makefile +++ /dev/null @@ -1,119 +0,0 @@ -# Makefile for mail2couch project -# Builds both Go and Rust implementations with distinct binary names - -.PHONY: all build build-go build-rust clean test help install - -# Default target -all: 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 /usr/local/bin (requires sudo) -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" - -# 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 - -# Show help -help: - @echo "Available targets:" - @echo " all - Build both implementations (default)" - @echo " build - Build both implementations" - @echo " build-go - Build Go implementation (mail2couch-go)" - @echo " build-rust - Build Rust implementation (mail2couch-rs)" - @echo " build-release - Build optimized release versions" - @echo " install - Install binaries to /usr/local/bin (requires sudo)" - @echo " test - Run tests for both implementations" - @echo " test-go - Run Go tests" - @echo " test-rust - Run Rust tests" - @echo " clean - Clean build artifacts" - @echo " check - Check code formatting and linting" - @echo " fmt - Format code" - @echo " help - Show this help message" - @echo "" - @echo "Output binaries:" - @echo " go/mail2couch-go - Go implementation" - @echo " rust/target/release/mail2couch-rs - Rust implementation" - -# Development convenience targets -dev-go: build-go - ./go/mail2couch-go --help - -dev-rust: build-rust - ./rust/target/release/mail2couch-rs --help \ No newline at end of file diff --git a/go/mail2couch b/go/mail2couch-go similarity index 65% rename from go/mail2couch rename to go/mail2couch-go index cd300c5..07c33c4 100755 Binary files a/go/mail2couch and b/go/mail2couch-go differ diff --git a/justfile b/justfile index 26b3101..4a24fb5 100644 --- a/justfile +++ b/justfile @@ -135,4 +135,95 @@ versions: build @./rust/target/release/mail2couch-rs --version # Clean and rebuild everything -rebuild: clean build \ No newline at end of file +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/src/imap.rs b/rust/src/imap.rs index 6b3d553..0308663 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 mut mail_doc = MailDocument::new( + let mail_doc = MailDocument::new( uid.to_string(), mailbox.to_string(), from, @@ -738,12 +738,6 @@ 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 new file mode 100644 index 0000000..fab6817 --- /dev/null +++ b/systemd/mail2couch-go-daily.timer @@ -0,0 +1,17 @@ +[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 new file mode 100644 index 0000000..bfd159d --- /dev/null +++ b/systemd/mail2couch-go-hourly.timer @@ -0,0 +1,17 @@ +[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 new file mode 100644 index 0000000..fcd8660 --- /dev/null +++ b/systemd/mail2couch-go.service @@ -0,0 +1,35 @@ +[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 new file mode 100644 index 0000000..d83e127 --- /dev/null +++ b/systemd/mail2couch-go.timer @@ -0,0 +1,17 @@ +[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 new file mode 100644 index 0000000..1439f0e --- /dev/null +++ b/systemd/mail2couch-rs-daily.timer @@ -0,0 +1,17 @@ +[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 new file mode 100644 index 0000000..6f48658 --- /dev/null +++ b/systemd/mail2couch-rs-hourly.timer @@ -0,0 +1,17 @@ +[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 new file mode 100644 index 0000000..3fa4714 --- /dev/null +++ b/systemd/mail2couch-rs.service @@ -0,0 +1,36 @@ +[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 new file mode 100644 index 0000000..4483fe4 --- /dev/null +++ b/systemd/mail2couch-rs.timer @@ -0,0 +1,17 @@ +[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