sysops
7e4175923f
feat(PROJ-48): Audit-Log Unveränderbarkeit (Trigger, append-only Logfile, Healthcheck)
...
DB-Trigger audit_log_immutable verhindert UPDATE/DELETE auf audit_log,
zusätzliches append-only JSON-Lines-Logfile (audit.log_path) als
tamper-evident Backup, neuer Healthcheck-Prüfpunkt in archivmail status.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-06-13 19:44:07 +02:00
sysops
bc82854165
feat: archivmail status CLI mit Healthcheck für PostgreSQL, Manticore und Storage
...
Prüft DB-Erreichbarkeit + Mail-Statistiken, Manticore-Verbindung/Version
und Storage (Keyfile, Pfad, freier Speicherplatz). --json für maschinenlesbare Ausgabe.
2026-06-13 00:01:40 +02:00
sysops
0ecde0c1ef
feat(cli): archivmail update — Wrapper für update.sh
...
Statt update.sh manuell zu suchen/laden kann jetzt
`archivmail update` (als root) ausgeführt werden. Nutzt
/opt/archivmail/update.sh falls vorhanden, sonst Download von Gitea.
2026-06-12 23:45:15 +02:00
sysops
a3bab16f07
fix(imap): IMAP/POP3-Import in korrekten Tenant-Index schreiben
...
IMAP- und POP3-Importer haben Mails immer nur in emails_global
indexiert (TenantID nie gesetzt, idxMgr.Global() statt
ForTenant(tenantID)). Dadurch fehlten neue Mails ab dem letzten
Server-Neustart im Tenant-Index (Suche zeigte veraltete Ergebnisse).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-06-12 21:15:10 +02:00
sysops
799c828548
feat(PROJ-45): IMAP per-folder UID-tracking, UIDVALIDITY-check + reindex OCR protection
...
- scheduler.go: BUG-1 fix — preserve stored uid_validity when server returns 0
- scheduler.go: BUG-2 fix — replace inline switch with DecideResync() call
- scheduler.go: SetAuditLogger wired; imap_uidvalidity_reset audit event
- cmd_reindex.go: read existing attachment_text before IndexSync to prevent
Manticore REPLACE INTO from wiping OCR text written by the OCR worker
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-11 14:56:28 +02:00
sysops
4151b6f8c5
feat(PROJ-45): IMAP Per-Folder UID-Tracking + UIDVALIDITY-Check
...
- FolderState: GetFolderState, UpsertFolderState, ListFolderStates, DecideResync
- syncFolder nutzt per-folder UID-Tracking statt globalem highest_uid
- UIDVALIDITY-Check loest automatisch Full-Resync aus
- imap_folder_state Tabelle in initSchema (CREATE TABLE IF NOT EXISTS)
- SetAuditLogger in main.go verdrahtet
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-11 10:49:14 +02:00
sysops
032892bc2b
fix(PROJ-44): IMAP+POP3 Live-Import triggert OCR-Worker
...
Bisher haben nur der SMTP-Pfad und der Boot-Backfill ocrWorker.Submit
gerufen. IMAP- und POP3-Importer riefen nur idx.IndexSync auf —
neue Mails blieben dadurch dauerhaft in ocr_status='pending' (auf 132
44 Tage 54 Mails so haengen geblieben).
Fix: Importer-Strukturen bekommen einen optionalen ocrSubmit-Callback,
in main.go via SetOCRSubmit gehookt. Kein Import von internal/ocr in
die Importer-Packages -> kein Risiko von Cycles. Submit ist
non-blocking; bei Mails ohne Attachments markiert der Worker selbst
'skipped'.
2026-05-10 22:23:24 +02:00
sysops
6d835aefac
fix(PROJ-35): OCR Tempdir auf storage_dir umleiten
...
Mit systemd ProtectSystem=strict ist /tmp fuer den Service read-only.
ocr.SetTempDir(storage_path/ocr-tmp) nutzt einen RW-Pfad innerhalb der
ohnehin freigegebenen ReadWritePaths.
2026-05-08 22:19:20 +02:00
sysops
a252ad6f0e
fix(PROJ-35): OCR Boot-Resume drosselt nach Queue-Kapazitaet
2026-05-08 22:15:20 +02:00
sysops
0bda21033e
feat(PROJ-35): OCR & Anhang-Volltext-Indexierung
...
Asynchrone OCR fuer PDF- und Bild-Anhaenge via tesseract + poppler-utils.
Extrahierter Text wird in Manticore (attachment_text) gespeichert und ist
ueber die normale Volltextsuche auffindbar.
- internal/ocr: ExtractText + Worker (queue + drain)
- internal/storage/ocr.go: SetOCRStatus, OCREnabled, GetMailsByOCRStatus
- emails.ocr_status (pending|done|failed|skipped|disabled)
- tenants.ocr_enabled (Default TRUE, opt-out)
- Manticore: attachment_text-Feld + UpdateAttachmentText
- Boot-resume: pending Jobs nach Restart automatisch in die Queue
- CLI: archivmail ocr-reprocess --tenant N --status pending|failed|all
- update.sh: tesseract-ocr + poppler-utils optional installieren
2026-05-08 22:11:17 +02:00
sysops
9298216ce0
feat(PROJ-40,PROJ-41): Prometheus Metriken + Dashboard Zeitreihe
...
- PROJ-40: /api/health mit Version+Uptime, /metrics Prometheus-Format
(mails_last_60min/24h/7d/30d, mails_total, storage_bytes, tenants_total,
users_total, uptime_seconds) — Token-Schutz optional konfigurierbar
- PROJ-41: GET /api/admin/stats/timeseries (30-Tage tagesgenau, Tenant-scoped)
+ SVG-Balkendiagramm im Dashboard (Mail-Eingang letzte 30 Tage)
- storage.DBQueryRow() Helper für Metrics-Queries ohne Pool-Exposition
- config.MetricsConfig (enabled, token) in config.go
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-05 21:10:42 +02:00
sysops
2bab61209c
chore: Modulname github.com/archivmail → archivmail
...
Go-Modul in go.mod und allen 45 Go-Dateien umbenannt.
2026-04-05 20:37:35 +02:00
sysops
eb48081c5e
feat(PROJ-38): rethread — rückwirkendes Mail-Threading
2026-04-05 20:28:50 +02:00
sysops
956b5b6d5f
feat(PROJ-36): archivmail recompress — Nachkomprimierung bestehender Mails
...
Neuer CLI-Subcommand: archivmail recompress [--dry-run]
Komprimiert alle unkomprimierten Dateien im Store atomisch (temp + rename).
Überspringt bereits komprimierte Dateien (Magic-Byte 0x01).
Aktualisiert storage_objects und emails.storage_id in der DB.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-05 01:30:42 +02:00
sysops
27d45f58e8
feat(PROJ-36,PROJ-37): gzip-Kompression + Attachment-Deduplication
...
Sprint 1: Emails werden vor AES-256-GCM optional gzip-komprimiert (compress: true).
Magic-Byte 0x01 als Prefix ermöglicht backward-kompatibles Load() für Legacy-Dateien.
Neue DB-Tabelle storage_objects trackt Kompressions-Metadaten.
Sprint 2: Attachments werden via SHA-256 dedupliziert — gleicher Anhang in N Mails
wird nur einmal gespeichert. Neue Tabellen: attachments, email_attachments.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-05 01:19:51 +02:00
sysops
fdb25cb16a
feat: Labels-Feature vollständig entfernen (PROJ-9)
...
Backend:
- internal/labelstore/ gelöscht (Store, Schema, CRUD)
- internal/api/label_handlers.go gelöscht (alle Label-Routen)
- internal/api/server.go: labels-Feld + SetLabels() entfernt
- internal/api/search_handlers.go: label_id-Filter + Enrichment entfernt
- internal/index/index.go: LabelID aus SearchRequest entfernt
- internal/imapserver/server.go: labels-Feld + labelbasierte Mailboxen entfernt
- cmd/archivmail/main.go: labelstore-Init + SetLabels() entfernt
- cmd/archivmail/version.go: labelstore-Modul entfernt, index-Kommentar korrigiert
Frontend:
- LabelList.tsx, LabelPicker.tsx, LabelsTab.tsx gelöscht
- src/lib/api/system.ts: MailLabel/LabelRule-Typen + alle Label-Funktionen entfernt
- src/lib/api/index.ts: Label-Exports entfernt
- src/app/search/page.tsx: LabelList + selectedLabelId State entfernt
- src/app/mail/[id]/page.tsx: LabelPicker + Labels-State entfernt
- src/app/admin/page.tsx: LabelsTab + alle Label-Handler/State entfernt
Docs:
- features/PROJ-9: Status auf Removed gesetzt
- features/INDEX.md: PROJ-9 auf Removed gesetzt
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-04 21:32:13 +02:00
sysops
bde291901a
fix: Manticore als Standard-Backend, Xapian-Cleanup in update.sh
...
- main.go: Default-Backend von "xapian" auf "manticore" geändert
- index.go: Kommentar und Fehlermeldung aktualisiert
- update.sh: Xapian-Verzeichnis wird nach erfolgreichem Manticore-Reindex
automatisch entfernt
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-04 20:42:58 +02:00
sysops
ecd5ed361b
fix(PROJ-30): cmd import-piler — Manticore-Backend support
2026-04-04 01:38:59 +02:00
sysops
44bff147ba
fix(PROJ-30): cmd import — Manticore-Backend support (wie cmd_reindex)
2026-04-04 01:38:25 +02:00
sysops
4ef5897e68
feat(PROJ-29): Tenant-Quotas & Usage-Limits vollständig implementiert
...
- storage/quota.go: SQL-Bug gefixt (emails.size → size_bytes, email_refs JOIN)
- tenantstore/quota.go: GetUsage nutzt jetzt email_refs JOIN für korrekte Tenant-Isolation
- smtpd: ErrQuotaExceeded → SMTP 452 statt 554 (MTA-retry statt permanent reject)
- admin_handlers: handleCreateUser prüft max_users-Quota → HTTP 402 bei Überschreitung
- quota_handlers: handleGetTenantUsage gibt jetzt warnings-Feld mit soft-limit-Prozenten zurück
- server.go: spec-konforme Alias-Route GET /api/admin/tenants/{id}/usage registriert
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-04 01:27:59 +02:00
sysops
a93a843506
feat(PROJ-30): Xapian → Manticore Search Migration
...
- internal/index/manticore.go: ManticoreTenantManager + manticoreIndex (RT-Indizes, CGO-frei)
- internal/index/index.go: TenantIndexer Interface (Xapian + Manticore)
- internal/index/tenant_worker.go: mgr-Typ auf TenantIndexer Interface
- internal/api/server.go: idxMgr auf TenantIndexer Interface
- config/config.go: IndexConfig.ManticoreDSN Feld
- cmd/archivmail/cmd_reindex.go: reindex Subkommando
- cmd/archivmail/main.go: Manticore-Branch + reindex Case
- go.mod: github.com/go-sql-driver/mysql v1.8.1
- update.sh: Manticore auto-install, CGO_ENABLED=0, config.yml migration, auto-reindex
fix(IMAP): TCP-Deadline-Wrapper für steckengebliebene Imports
fix(auth): Email-Claim in JWT für User-Isolation
fix(search): User-Isolation via sess.Email (fail-safe)
fix(ui): Admin-Login Auth-Cache, Logout-Redirect, IMAP-Polling-Resilienz
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-03 21:19:36 +02:00
sysops
c1a9004720
feat(PROJ-28): SMTP-Out Relay — DB-Konfiguration + Admin-Tab
...
- smtpoutconfig.Store: AES-256-GCM verschlüsseltes Passwort in DB (id=1 Singleton)
- Mailer: Reload() für Runtime-Konfigurationswechsel (sync.RWMutex)
- API: GET/PUT/DELETE /api/admin/smtp-out + POST /api/admin/smtp-out/test
- Admin-Tab: Host, Port, User, Passwort, TLS-Switch, From, Test-Button, Status-Badge
- Startup: Lädt DB-Konfiguration und aktiviert Mailer ohne Restart
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-31 22:36:57 +02:00
sysops
4583262ea4
feat(PROJ-28): Self-Service Onboarding — Signup, Verify, Password Reset, Invites
...
- internal/mailer: SMTP-Out via net/smtp (TLS + STARTTLS), HTML+Text-Templates
- internal/tokenstore: auth_tokens Tabelle, SHA-256-Hash, TTL, einmalig verwendbar
- userstore: CreateInactive(), Activate(), GetByEmail(), SetPassword()
- API: POST /signup, GET /verify, POST /forgot-password, POST /reset-password
- API: POST /admin/invite (domain_admin+), GET /auth/invite?token (check)
- Login-Seite: Links zu "Passwort vergessen" und "Registrieren"
- Frontend: /signup, /verify, /forgot-password, /reset-password Seiten
- server.fqdn nicht konfiguriert → Startup-Warnung, Self-Service deaktiviert
- LDAP-Nutzer: Passwort-Reset abgewiesen
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-31 21:54:11 +02:00
sysops
58bcfb1586
feat: Dashboard-Metriken nach Mailpiler-Vorbild (Uptime, Aktivität, Prognose)
...
- storage_stats.go (neu): MailActivityStats (60min/24h/7d/30d), StorageEstimateStats
- dashboard_handlers.go: Uptime (/proc/uptime), activity + estimate in System-Stats-Response
- DashboardTab: Uptime in API-Kachel, neue Kacheln "Mail-Eingang" + "Speicherprognose"
- Warnung (Badge "Knapp!") wenn Partition in <90 Tagen voll
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-31 10:44:02 +02:00
sysops
5bbf6d0ff3
feat(PROJ-34): Retention-Tab + pro-Mandant Aufbewahrungsfristen
...
- tenantstore: retention_days Spalte, GetRetentionDays/SetRetentionDays
- storage.Save(): per-tenant retention überschreibt globale config
- API: GET /api/admin/retention, PUT /api/admin/tenant/{id}/retention
- Frontend: RetentionTab mit globaler Policy-Anzeige, Mandanten-Tabelle,
Bearbeiten-Dialog und Purge-Button (superadmin only)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-31 10:37:15 +02:00
sysops
27040ffcb1
feat(PROJ-28): FQDN + smtp_out Konfiguration
...
- config: server.fqdn, SMTPOutConfig, smtp_out Abschnitt
- config: IMAPServerConfig.FQDN (runtime-gesetzt)
- main: FQDN-Fallback für SMTP EHLO, FQDN an IMAP-Server
- imapserver: Greeting nutzt server.fqdn (RFC 3501)
- smtpd/imapserver Modulversion 1.3
fix: Superadmin sieht keine Suche/IMAP/POP3 Nav-Links
- Navbar: Suche, IMAP Import, POP3 Import nur für non-superadmin
- Superadmin landet direkt auf Admin-Dashboard
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-31 09:51:41 +02:00
sysops
8d0f685fc9
feat(PROJ-33): IMAP UID-Stabilität + Shared/Personal-Modus
...
Backend:
- storage: uid BIGSERIAL Migration, MailWithUID, GetMailsWithUID, GetMailsByRecipient
- tenantstore: imap_mode Spalte, GetIMAPMode, SetIMAPMode
- imapserver: stable UIDs aus DB, personal/shared Modus, userEmail in session
- api: GET/PUT /api/admin/settings/imap-mode (domain_admin only, double opt-in)
Frontend:
- IMAPSettingsTab: Modus-Anzeige + Toggle mit Double-Opt-In Dialog
- Admin-Panel: IMAP-Tab für domain_admin
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-31 09:46:52 +02:00
sysops
b6856af2eb
feat(PROJ-32): Message-ID-basierte Duplikatserkennung
...
- message_id Spalte + UNIQUE-Index in emails-Tabelle
- Save() prüft Message-ID vor SHA-256-Flow (kein Disk-I/O bei Duplikat)
- lookupByMessageID() als private Hilfsfunktion
- insertMeta() schreibt message_id, gibt error zurück (Race-safe)
- SaveMeta() schreibt message_id idempotent (Backfill)
feat(PROJ-34): Retention-Policy + Löschsperre (GoBD)
- retain_until TIMESTAMPTZ Spalte in emails-Tabelle
- ErrRetentionLock typed error
- Delete() prüft Retention-Frist vor Löschung
- Purge() löscht alle Mails mit abgelaufener Retention
- POST /api/admin/purge Endpunkt (superadmin only)
- config: storage.retention_days
fix: Superadmin-Benutzerübersicht zeigt Mandant-Spalte
- UsersTab: Mandant-Spalte wenn isSuperAdmin
- domain_auditor Rolle im Create-Dialog ergänzt
- storage Modulversion → 1.6
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-31 01:29:25 +02:00
sysops
cb31c48ce8
fix: version → AppVersion in cmd_import.go (Build-Fehler nach 0.9.1-Umbenennung)
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-31 01:14:27 +02:00
sysops
4f7a7d6946
feat: App-Version 0.9.1 + Modulversionsnummern
...
- version.go: AppVersion + Modules-Map (pro Modul interne Versionsnummer)
- GET /api/version: liefert App- und Modulversionen (ohne Auth)
- archivmail version: zeigt App- und Modulversionen in CLI
- version-Konstante aus cmd_import.go entfernt (war falsche Stelle)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-31 01:12:51 +02:00
sysops
fd46f0de9a
fix: superadmin beim ersten Start anlegen + Installer zeigt echte Passwörter
...
- seedDefaultUsers: superadmin (Rolle superadmin) zu Default-Usern hinzugefügt
→ wird beim ersten Backend-Start mit Zufallspasswort angelegt
- Installer: Passwörter werden nach dem Deployment aus dem Journal gelesen
(journalctl -u archivmail) statt falschen Platzhalter 'archivmailrockz'
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-20 01:23:33 +01:00
sysops
19a55a3166
feat(PROJ-26): IMAP-Archive-Server Read-Only Zugriff auf archivierte Mails
...
- Neues Package internal/imapserver: vollständiger IMAP4rev1-Server (~700 Zeilen)
- Auth via bcrypt (userstore.VerifyPassword), Multi-Tenant-Isolation
- INBOX + INBOX/LabelName Ordnerstruktur
- FETCH mit BODY[], ENVELOPE, RFC822.SIZE, INTERNALDATE, FLAGS, UID
- SEARCH: ALL, FROM, TO, SUBJECT, SINCE, BEFORE + UID FETCH/SEARCH
- Read-Only: STORE, DELETE, COPY, MOVE, APPEND → NO [CANNOT]
- \Seen-Flag nicht persistent (GoBD-konform)
- Max 5 gleichzeitige Verbindungen pro User, 30min Idle-Timeout
- Audit-Log: imap_login / imap_login_failed Events
- Config: imap_server.enabled + imap_server.bind (default: 127.0.0.1:1143)
- Externe Ports: 9993 (primär) und 993 (alternativ) via nginx TLS-Terminierung
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-18 11:42:35 +01:00
sysops
5a6289c83d
feat(PROJ-9): implement labels backend - DB schema, labelstore, API handlers, Xapian integration
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-18 08:32:30 +01:00
sysops
2de340573b
fix(security): behebe F-01/F-02/W-03/W-04 aus Security-Audit + PROJ-24 TOTP 2FA
...
F-01: err.Error() wird nicht mehr an HTTP-Clients gesendet.
Stattdessen generische Fehlermeldungen + Server-Log.
Betrifft: handleCreateUser, handleUpdateUser, handleDeleteUser,
handleSyncNow, handleSecurityConfig, handleUpload.
F-02: Login-Audit-Log enthält keinen rohen err.Error() mehr.
Neue classifyLoginError() Funktion: invalid_password / ldap_error /
account_disabled / unknown — schützt vor LDAP-Info-Leak via Audit-API.
W-03: remoteIP() trimmt jetzt Leerzeichen aus X-Forwarded-For.
Vollständige Lösung erfordert Proxy-Konfiguration (W-03 bleibt WARN).
W-04: Attachment-Dateiname wird durch sanitizeFilename() bereinigt.
Nur [a-zA-Z0-9._- ] erlaubt — verhindert Header-Injection.
PROJ-24: TOTP 2FA vollständig implementiert:
- internal/auth/totp.go: GenerateSecret, ValidateTOTP, QRCodeSVG
- internal/api/totp_handlers.go: Setup, Login-Step2, Admin-Reset
- internal/userstore: SetTOTPSecret, EnableTOTP, DisableTOTP, ResetTOTP
- Login-Flow: totp_pending JWT → /api/auth/totp → vollwertiger JWT
- AES-256-GCM verschlüsseltes Secret in users.totp_secret
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-18 00:54:00 +01:00
sysops
78d83d3e98
feat(PROJ-21/23): Pro-Tenant Xapian-Index + Tenant-LDAP Backend
...
PROJ-21 Phase 4:
- internal/index/tenant_manager.go: TenantIndexManager mit lazy-loading Pool
- internal/index/tenant_worker.go: TenantIndexWorker leitet Submit an richtigen Index
- Jeder Mandant bekommt eigenes Xapian-Verzeichnis (tenant-<id>/)
- handleSearch nutzt direkt Tenant-Index statt nachgelagertem Post-Filter
- runBackfill re-indexiert pro Mandant beim Start
PROJ-23 / PROJ-16 Phase B:
- internal/ldapconfig/tenant_store.go: TenantStore mit AES-256-GCM für tenant_ldap
- internal/api/ldap_tenants.go: 8 neue Handler (GET/PUT/DELETE/test für
/api/tenant/ldap und /api/admin/tenants/{id}/ldap)
- internal/auth/auth.go: Login-Fallback prüft tenant_ldap nach globalem LDAP
(Domain-Extraktion → tenant_ldap config → UpsertLDAPUser mit tenant_id)
- internal/api/server.go: SetTenantLDAP(), neue Routen registriert
- internal/tenantstore/store.go: GetByDomain() Interface für auth-Package
- cmd/archivmail/main.go: TenantLDAPStore + TenantIndexManager verdrahtet
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-18 00:18:35 +01:00
sysops
46d7bfe608
fix(security): Kritische Sicherheitslücken beheben (SEC-01/02/03/05/08/17/22/26/28)
...
- SEC-01: Privilege Escalation verhindert — Rollenhierarchie in Create/Update/DeleteUser
- SEC-02: Tenant-Isolation in Update/DeleteUser — domain_admin nur eigene Nutzer
- SEC-03: IMAP/POP3 Owner-Check via auth.HasRole statt direktem String-Vergleich
- SEC-05: Export PDF/ZIP prüft Tenant-Zugehörigkeit vor Dateiausgabe
- SEC-08: HKDF-SHA256 trennt JWT-Secret von AES-Key (archivmail-jwt-v1 / archivmail-aes-v1)
- SEC-17: handleSecurityFix erfordert requireRole(superadmin)
- SEC-22: Mail-ID Regex [0-9a-f]{64} in allen Handlern (Path-Traversal-Schutz)
- SEC-26: SMTP Fail-Closed — leere AllowedIPs blockiert alles statt zu erlauben
- SEC-28: handleGetRaw — Parse-Fehler bricht ab statt Fallthrough zu Dateizugriff
BREAKING: IMAP/POP3/LDAP-Passwörter müssen nach Deploy einmalig neu eingegeben
werden (neuer AES-Key). JWT-Sessions laufen ab (einmaliges Re-Login nötig).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-18 00:05:47 +01:00
sysops
479c27e5a8
feat(PROJ-21): Phase 2+3+5+8 Multi-Tenancy + PROJ-2 EML/MBOX Upload
...
Phase 2a: userstore domain_admin/superadmin Rollen, User.TenantID,
ListByTenant, UpsertLDAPUser mit tenantID
Phase 2b: storage.Save() mit tenantID *int64, email_refs Tabelle,
GetTenantForMail, GetAllIDsByTenant, StatsByTenant
Phase 2c: JWT-Claims tenant_id/tenant_slug, Session.TenantID,
Login Domain-Erkennung via E-Mail-Domain
Phase 3: tenantMiddleware, Handler-Filterung (Users, Mail, Stats)
Phase 5: SMTP Domain-Routing via DomainToTenantFunc Callback,
config smtp.tenant_routing + default_tenant_id
Phase 8: archivmail migrate-tenants Subkommando
PROJ-2: Upload-Seite /admin/upload mit DropZone + Progress-Polling
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-17 21:03:40 +01:00
sysops
ac91dceac2
feat(PROJ-22): LDAP Web-GUI + feat(PROJ-21): Multi-Tenancy Phase 1
...
PROJ-22 – LDAP Web-GUI Konfiguration & Test:
- internal/ldapconfig/store.go: AES-256-GCM Passwortspeicherung, CRUD Upsert (id=1)
- internal/ldapauth/client.go: TestConnection (RootDSE, UserCount) + Authenticate (2-step bind)
- internal/auth/auth.go: LDAP-Fallback in Login(), Gruppen-Rollenzuordnung, issueToken helper
- internal/api/ldap_tenants.go: GET/PUT/DELETE/POST-test /api/admin/ldap mit Audit-Log
- go.mod: github.com/go-ldap/ldap/v3 v3.4.8 hinzugefügt
- Frontend: LDAPConfig/LDAPTestResult Typen, LDAP-Tab mit Gruppen-Mappings + Testergebnis
PROJ-21 Phase 1+6+7 – Multi-Tenancy Grundstruktur:
- internal/tenantstore/store.go: tenants, tenant_domains, tenant_ldap Schema; Migration users/audit_log
- API: 8 Tenant-Routen (CRUD + Domain-Management) via SetTenants()
- cmd/archivmail/main.go: ldapSt + tenantSt initialisiert
- Frontend: Mandanten-Tab mit Tabelle, Domain-Dialog, Deaktivieren/Löschen
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-17 20:27:56 +01:00
sysops
adffff7ee1
feat(PROJ-14): POP3-Import — Client, Store, Importer, API-Routen, Frontend-Seite
2026-03-17 19:48:14 +01:00
sysops
7c29ee88bd
docs: vollständige README, PROJ-2 Web-Upload, PROJ-19 Mailpiler-Migration
...
README.md:
- Vollständige Dokumentation aller implementierten Funktionen
- Konfigurationsreferenz, Installation, Systemd, REST-API-Übersicht
- In-Progress-Features klar gekennzeichnet
PROJ-2 (EML/MBOX Web-Upload):
- POST /api/admin/upload – Multipart-Upload mit Hintergrund-Job
- GET /api/admin/upload/{jobID}/progress – Polling
- Admin-Tab "Import" mit Drag-and-Drop, Fortschrittsbalken, Abschlussbericht
PROJ-19 (Mailpiler Migration):
- archivmail import-piler mit Methoden: pilerexport | direct | auto
- Direct: AES-256-CBC + zlib mit defensiven Fallbacks
- pilerexport: Wrapper um mailpilers Export-Tool
Status-Updates: PROJ-3, PROJ-4, PROJ-6, PROJ-7, PROJ-10, PROJ-11 → Deployed
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-17 09:23:34 +01:00
sysops
988c37d85d
feat(PROJ-8): Automatischer IMAP-Sync (Cron-Scheduler)
...
Backend:
- internal/imap/store.go: 7 neue Felder (sync_interval_min, last_sync_at,
last_sync_count, last_uid, sync_running, sync_status, sync_error_msg)
DB-Migration via ALTER TABLE ADD COLUMN IF NOT EXISTS
Neue Methoden: ListAll, UpdateSyncInterval, SetSyncRunning, UpdateSyncResult
- internal/imap/scheduler.go: Scheduler mit time.Ticker (1 min),
inkrementeller Sync via UID SEARCH UID <lastUID+1>:*,
exponential backoff (3 Versuche: 1s / 60s / 300s),
sync_running-Flag verhindert parallele Syncs
- internal/api/server.go: POST /api/imap/{id}/sync (manueller Trigger),
PATCH /api/imap/{id} (sync_interval_min setzen, 0 oder 5-1440 min)
- cmd/archivmail/main.go: Scheduler gestartet + via SetImap verdrahtet
Frontend:
- src/lib/api.ts: 6 neue ImapAccount-Felder, triggerImapSync, updateImapInterval
- src/app/imap/page.tsx: Intervall-Dropdown, "Sync jetzt"-Button,
Letzter-Sync-Anzeige mit Status-Badge, Polling auch bei sync_running
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-17 02:17:44 +01:00
sysops
bb963a796f
security: Zufallspasswörter beim Erststart, kryptographisch sichere JTI-Generierung
...
- seedDefaultUsers: generiert kryptographisch zufällige Passwörter (crypto/rand)
statt hartkodiertes "archivmailrockz" — Passwörter werden einmalig im Terminal
angezeigt und können danach nicht wiederhergestellt werden
- generateJTI: verwendet crypto/rand (16 Byte, hex) statt time.UnixNano XOR deadbeef
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-17 01:19:24 +01:00
sysops
3c722d0987
feat(PROJ-18): E-Mail Integritätsprüfung (SHA-256 Verifikation)
...
- Storage: VerifyIntegrity, GetAllIDs, GetVerifyStatus + DB-Spalten
- main: Hintergrund-Worker alle 5 Minuten (beim Start sofort: 40/40 OK)
- API: verify_ok + verified_at in GET /api/mails/{id} Antwort
- Frontend: Grüner Haken / graues X / rotes X in Mail-Ansicht
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-14 21:28:40 +01:00
sysops
7e68c7ab02
feat(PROJ-5): AES-256-GCM Verschlüsselung, PostgreSQL Metadaten, Async Index Worker
...
- Storage: AES-256-GCM Verschlüsselung (keyfile, graceful fallback bei fehlendem Key)
- Storage: PostgreSQL emails-Tabelle mit Auto-Migration
- Storage: Save/Delete/Stats/FirstAndLastMail nutzen DB wenn verfügbar
- Index: Async IndexWorker (Go-Channel, Queue 1000, non-blocking Submit)
- SMTP: IndexCallback für async Indexierung nach Mail-Eingang
- main: Backfill beim Start (40 Mails migriert + indexiert)
- Bestehende Mails werden transparent entschlüsselt (Fallback auf Raw)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-14 20:26:50 +01:00
sysops
4f93b9667d
feat(PROJ-15): CLI Import & Export als Subcommands
...
- archivmail import: EML + MBOX, --file/--dir/--recursive/--dry-run/--json
- archivmail export: EML + MBOX, Filter --from/--to/--date-from/--date-to/--query/--force/--json
- archivmail help / version
- MBOX Parser (SplitMbox) in pkg/mailparser/mbox.go
- Subcommand-Router in main.go ohne externe Abhängigkeit
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-14 18:25:21 +01:00
sysops
d360c9a5ba
feat(PROJ-17): Admin Dashboard Systemauslastung immer anzeigen
...
- Systemauslastungs-Sektion wird immer gerendert (nicht nur bei Erfolg)
- Fehlermeldung wenn /api/admin/system/stats nicht erreichbar ist
- Feature-Status auf In Review gesetzt
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-14 11:43:19 +01:00