Files
archivmail/features/PROJ-57-utf8-encoding-fix.md
T
sysopsandClaude Sonnet 4.6 fae274f930 feat(PROJ-58): Indexierung + OCR optional als Cron-Batch statt Dauerbetrieb
Neues config.yml-Feld batch_mode (index/ocr, Default false = unverändertes
Verhalten). Bei batch_mode:true verarbeiten neue Cron-Jobs (index-pending,
ocr-reprocess) die Backlogs in größeren Abständen statt sofort bei jedem
Mail-Import, um Schreiblast auf der Festplatte zu glätten. Zeiten in
/etc/cron.d/archivmail frei anpassbar.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 23:07:17 +02:00

2.6 KiB

PROJ-57: UTF-8-Encoding-Fix für Mails mit Nicht-UTF-8-Charset

Status: Deployed

Created: 2026-06-24 Last Updated: 2026-06-24

Hintergrund (Nutzerwunsch)

Eine archivierte Mail mit Öffnungszeiten zeigte kaputte Umlaute ("fr" statt "für") sowohl in der Mail-Ansicht als auch in der Volltextsuche.

Root Cause

pkg/mailparser/parser.go ignorierte das charset-Parameter aus Content-Type und interpretierte die rohen Bytes immer als UTF-8. Mails mit charset=iso-8859-1/windows-1252 wurden dadurch zu Mojibake. Zusätzlich fehlte das Charset in der Manticore-MySQL-Verbindung (DSN) und im Content-Type-Header der JSON-API-Responses.

Acceptance Criteria

  • mailparser.Parse() konvertiert Text-/HTML-Bodies anhand des deklarierten charset-Parameters nach UTF-8 (Single-Part und Multipart).
  • Unbekannte/fehlende Charsets oder bereits UTF-8/ASCII bleiben unverändert (kein Verhaltensbruch für den Normalfall).
  • Manticore-Verbindung nutzt ?charset=utf8mb4.
  • JSON-API-Responses setzen Content-Type: application/json; charset=utf-8.

Implementation Notes (2026-06-24)

  • pkg/mailparser/parser.go: neue Funktion decodeCharset() (nutzt golang.org/x/text/encoding/htmlindex), aufgerufen nach decodeBody() in Parse() (Single-Part) und parseMultipart().
  • cmd/archivmail/main.go, cmd_import.go, cmd_import_piler.go, cmd_ocr_reprocess.go, cmd_purge.go, cmd_reindex.go, cmd_status.go: Default-Manticore-DSN auf ?charset=utf8mb4 erweitert (war an 7 Stellen dupliziert).
  • config/config.go: Doku-Kommentar zum Default-DSN aktualisiert.
  • internal/api/server.go: writeJSON() setzt jetzt application/json; charset=utf-8.
  • go.mod: golang.org/x/text von indirect zu direct dependency (jetzt direkt importiert).

QA / Verifikation

  • Build auf 192.168.1.132: go mod tidy + CGO_ENABLED=0 go build -buildvcs=false → Exit 0, keine fehlenden go.sum-Einträge.
  • Funktionstest: .eml-Testmail mit Content-Type: text/plain; charset=iso-8859-1 und Umlauten importiert → über store.Load() + mailparser.Parse() (identischer Pfad wie handleGetMail) korrektes UTF-8 ("Öffnungszeiten") bestätigt, keine Mojibake-Zeichen.
  • Storage bleibt bewusst byte-genau im Original-Charset (GoBD-Originalarchiv); Konvertierung passiert erst beim Parsen für Anzeige/Index.

Deployment

  • Test (192.168.1.132): Build + Funktionstest grün, kein Dauerbetrieb-Eingriff (Binary nach Test zurückgesetzt). 2026-06-24.
  • Produktion (192.168.1.131): update.sh (Commit 76655f7), Backend+Frontend aktiv, Health-Check OK, keine Fehler im Log. 2026-06-24.