feat(PROJ-84): fix-subjects CLI-Backfill für kaputte MIME-Header-Betreffs
CLI-Subkommando "archivmail fix-subjects" korrigiert Bestandsmails mit
undekodiertem RFC-2047-Encoded-Word im Betreff (Folge des Fixes in
31d7113). Dry-Run per Default, echte Änderung nur mit --apply.
Original-EML im Storage bleibt unangetastet - nur Postgres emails.subject
wird korrigiert, danach Manticore-Reindex inkl. Erhalt von OCR-Text.
Jeder Lauf erzeugt einen Audit-Log-Eintrag (metadata_backfill).
Verifiziert auf 192.168.1.132: 543 Kandidaten, 541 reparierbar, 2 zu
Recht übersprungen (RFC-2047-Verletzung im Original). --apply noch
nicht ausgeführt.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WapWkrQusDuBMhaN8WyuXB
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
31d71138c9
commit
1dfd8c18ac
+2
-1
@@ -99,7 +99,8 @@
|
||||
| PROJ-81 | Anhang-Online-Vorschau (PDF, Bilder) | In Review | [PROJ-81](PROJ-81-anhang-online-vorschau.md) | 2026-08-06 |
|
||||
| PROJ-82 | Print-Farbparität zwischen Hell- und Dark-Mode-Ausdrucken | Planned | [PROJ-82](PROJ-82-print-farbparitaet-dark-mode.md) | 2026-08-06 |
|
||||
| PROJ-83 | Audit-Logging für Anhang-Abrufe (GoBD/DSGVO-Nachbesserung) | Planned | [PROJ-83](PROJ-83-audit-log-anhang-abrufe.md) | 2026-08-06 |
|
||||
| PROJ-84 | Fix MIME-Header-Charset-Dekodierung + Backfill für Bestandsmails | In Review | [PROJ-84](PROJ-84-fix-mime-header-charset-backfill.md) | 2026-08-06 |
|
||||
|
||||
<!-- Add features above this line -->
|
||||
|
||||
## Next Available ID: PROJ-84
|
||||
## Next Available ID: PROJ-85
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
# PROJ-84: Fix MIME-Header-Charset-Dekodierung + Backfill für Bestandsmails
|
||||
|
||||
## Status: In Review
|
||||
**Created:** 2026-08-06
|
||||
**Last Updated:** 2026-08-06
|
||||
|
||||
## Kontext
|
||||
Betreffzeilen mit MIME-Encoded-Words (RFC 2047) in Charsets außerhalb UTF-8/US-ASCII/ISO-8859-1 (z.B. Windows-1252, ISO-8859-15) wurden nicht dekodiert und roh angezeigt (`=?Windows-1252?Q?ARAG_4_...?=`). Ursache: `decodeMIMEHeader()` in `pkg/mailparser/parser.go` nutzte `mime.WordDecoder` ohne `CharsetReader` — Go unterstützt dort nativ nur die drei genannten Charsets. Der Body-Decoder (`decodeCharset`, genutzt seit PROJ-57) konnte das bereits über `htmlindex`, der Header-Decoder nicht.
|
||||
|
||||
Fix (Commit 31d7113) behebt das für künftige Importe. Bestandsmails behalten den kaputten Betreff, bis sie per Backfill korrigiert werden — dafür dieses Ticket.
|
||||
|
||||
## Dependencies
|
||||
- Baut auf PROJ-57 (UTF-8-Encoding-Fix) auf — nutzt dieselbe `htmlindex`-Charset-Logik
|
||||
- Betrifft PROJ-11/PROJ-48 (Audit-Log) — Backfill-Lauf wird auditiert
|
||||
|
||||
## User Stories
|
||||
- Als User will ich, dass Mail-Betreffs unabhängig vom ursprünglichen Absender-Charset korrekt lesbar sind, sowohl bei neuen als auch bei bereits archivierten Mails.
|
||||
- Als Admin will ich einen nachvollziehbaren, wiederholbaren Weg haben, bestehende Mails mit kaputtem Betreff zu korrigieren, ohne das archivierte Original anzufassen.
|
||||
|
||||
## Acceptance Criteria
|
||||
- [x] `decodeMIMEHeader()` dekodiert Encoded-Words in Windows-1252, ISO-8859-15 und weiteren von `htmlindex` unterstützten Charsets korrekt
|
||||
- [x] CLI-Kommando `archivmail fix-subjects` identifiziert Bestandsmails mit undekodiertem Encoded-Word im Betreff
|
||||
- [x] Dry-Run ist Default, echte Änderung nur mit `--apply`
|
||||
- [x] Korrektur ändert ausschließlich die Postgres-Metadaten-Spalte `emails.subject` — die archivierte Original-EML im Storage-Layer bleibt unverändert
|
||||
- [x] Nach Korrektur wird der Manticore-Suchindex für die betroffene Mail nachgezogen (inkl. Erhalt von vorhandenem OCR-Text)
|
||||
- [x] Jeder Lauf (auch Dry-Run) erzeugt einen Audit-Log-Eintrag (`event_type=metadata_backfill`) mit Zählern
|
||||
- [ ] `--apply`-Lauf auf 132 durchgeführt und stichprobenartig verifiziert
|
||||
- [ ] `--apply`-Lauf auf 131 (Produktiv) durchgeführt, nach Freigabe
|
||||
|
||||
## Edge Cases
|
||||
- Encoded-Word verletzt RFC 2047 selbst (z.B. Leerzeichen im codierten Teil, an Vortext geklebt) → wird übersprungen, mit WARN geloggt, bleibt unverändert (2 von 543 Fällen auf 132)
|
||||
- Mail-Original nicht mehr ladbar/parsebar (z.B. DSGVO-gelöscht) → Index wird nicht angefasst, als `index_skipped` gezählt, DB-Subject bleibt beim Fallback (`DecodeMIMEHeader` auf vorhandenem String)
|
||||
- Mail bereits mit OCR-Text indexiert → Reindex darf `attachment_text` nicht löschen, wird aus bestehendem Index-Dokument übernommen
|
||||
|
||||
## Technical Requirements (optional)
|
||||
- Kein neues Datenbankschema, keine neue Tabelle
|
||||
- CLI-Subkommando statt Wegwerf-Skript, für künftige ähnliche Encoding-Bugs wiederverwendbar
|
||||
- Exit-Code 1 bei Fehlern (cron-/scripttauglich)
|
||||
|
||||
---
|
||||
<!-- Sections below are added by subsequent skills -->
|
||||
|
||||
## Tech Design (Solution Architect)
|
||||
Direkt umgesetzt ohne vorgelagerte Architektur-Phase — kleiner, klar umrissener Bugfix + Backfill-Tool, kein neues UI, kein neues Datenmodell.
|
||||
|
||||
Quelle der Wahrheit ist das archivierte Original: pro Mail wird die verschlüsselte EML lesend geladen und mit `mailparser.Parse()` neu geparst, der neue Betreff kommt aus `pm.Subject`. Fallback auf direktes Redekodieren des gespeicherten Strings, falls Original nicht ladbar. Geschrieben wird ausschließlich `UPDATE emails SET subject=...`.
|
||||
|
||||
## Implementation Notes (Backend, 2026-08-06)
|
||||
|
||||
Neue/geänderte Dateien:
|
||||
- `pkg/mailparser/header_decode.go` (neu) — `DecodeMIMEHeader()` exportierter Wrapper, `HasEncodedWord()` Erkennung
|
||||
- `internal/storage/subject_backfill.go` (neu) — `ListRawEncodedSubjects()`, `UpdateSubjectMetadata()`
|
||||
- `cmd/archivmail/cmd_fix_subjects.go` (neu) — CLI-Kommando inkl. Reindex + Audit
|
||||
- `internal/audit/audit.go` — neue Konstante `EventMetadataBackfill = "metadata_backfill"`
|
||||
- `cmd/archivmail/main.go`, `cmd/archivmail/cmd_import.go` — Dispatch + Hilfetext
|
||||
|
||||
Kommando:
|
||||
```bash
|
||||
archivmail fix-subjects # Dry-Run (Default), alle Mandanten
|
||||
archivmail fix-subjects --tenant 3 --limit 50
|
||||
archivmail fix-subjects --apply
|
||||
archivmail fix-subjects --apply --verbose # + jede Änderung alt->neu loggen
|
||||
```
|
||||
|
||||
Messung auf 192.168.1.132 (Dry-Run, read-only): 543 Kandidaten, 541 reparierbar, 2 nicht dekodierbar (RFC-2047-Verletzung im Original, korrekt übersprungen). Charset-Verteilung: ISO-8859-15 (219), windows-1252 (185), Cp1252 (69), Windows-1252 (38), iso-8859-15 (11), utf8-Varianten (14), windows-1258 (5), ASCII (1).
|
||||
|
||||
Build auf 132 verifiziert (`CGO_ENABLED=0 go build -buildvcs=false ./cmd/archivmail/` → OK), Dry-Run zweimal gegen Live-DB gelaufen, Stichproben korrekt (u.a. mehrteilige Windows-1252-Encoded-Words richtig zusammengesetzt). `--apply` noch nicht ausgeführt.
|
||||
|
||||
## QA Test Results
|
||||
_To be added by /qa_
|
||||
|
||||
## Deployment
|
||||
_To be added by /deploy_
|
||||
Reference in New Issue
Block a user