Add mbox viewer panes

This commit is contained in:
DonVoo 2026-07-05 21:45:15 +02:00
parent 4e51aee1a9
commit 955c1e0f92
3 changed files with 246 additions and 7 deletions

View file

@ -3,6 +3,9 @@ package backend
import (
"bytes"
"fmt"
"io"
"mime"
"net/mail"
"os"
"path/filepath"
"strings"
@ -71,8 +74,96 @@ type MboxEntry struct {
// ReadMboxList parst die Kopfzeilen aller Mails einer mbox-Datei (fuer die
// Nachrichtenliste). ReadMboxMessage liefert eine einzelne Mail als Rohtext.
func ReadMboxList(path string) ([]MboxEntry, error) { return nil, nil } // TODO Codex
func ReadMboxMessage(path string, index int) ([]byte, error) { return nil, nil } // TODO Codex
func ReadMboxList(path string) ([]MboxEntry, error) {
msgs, err := readMboxMessages(path)
if err != nil {
return nil, err
}
out := make([]MboxEntry, 0, len(msgs))
for i, raw := range msgs {
msg, err := mail.ReadMessage(bytes.NewReader(raw))
if err != nil {
out = append(out, MboxEntry{Index: i, From: "(unlesbar)", Subject: "Unlesbare Nachricht"})
continue
}
out = append(out, MboxEntry{
Index: i,
From: decodeHeader(msg.Header.Get("From")),
Subject: decodeHeader(msg.Header.Get("Subject")),
Date: decodeHeader(msg.Header.Get("Date")),
})
}
return out, nil
}
func ReadMboxMessage(path string, index int) ([]byte, error) {
msgs, err := readMboxMessages(path)
if err != nil {
return nil, err
}
if index < 0 || index >= len(msgs) {
return nil, fmt.Errorf("message index out of range")
}
return msgs[index], nil
}
func readMboxMessages(path string) ([][]byte, error) {
b, err := os.ReadFile(path)
if err != nil {
return nil, err
}
b = bytes.ReplaceAll(b, []byte("\r\n"), []byte("\n"))
lines := bytes.Split(b, []byte("\n"))
var msgs [][]byte
var cur bytes.Buffer
inMsg := false
for _, line := range lines {
if bytes.HasPrefix(line, []byte("From ")) {
if inMsg && cur.Len() > 0 {
msgs = append(msgs, bytes.TrimRight(cur.Bytes(), "\n"))
cur.Reset()
}
inMsg = true
continue
}
if !inMsg {
continue
}
if bytes.HasPrefix(line, []byte(">From ")) {
line = line[1:]
}
_, _ = cur.Write(line)
_ = cur.WriteByte('\n')
}
if inMsg && cur.Len() > 0 {
msgs = append(msgs, bytes.TrimRight(cur.Bytes(), "\n"))
}
return msgs, nil
}
func decodeHeader(v string) string {
v = strings.TrimSpace(v)
if v == "" {
return ""
}
decoded, err := new(mime.WordDecoder).DecodeHeader(v)
if err != nil {
return v
}
return decoded
}
func messageBody(raw []byte) string {
msg, err := mail.ReadMessage(bytes.NewReader(raw))
if err != nil {
return string(raw)
}
body, err := io.ReadAll(msg.Body)
if err != nil {
return string(raw)
}
return string(body)
}
func safeMboxName(folder string) string {
folder = strings.TrimSpace(folder)