diff --git a/backend/00-router.go b/backend/00-router.go
index d659dea..ec04817 100644
--- a/backend/00-router.go
+++ b/backend/00-router.go
@@ -1,11 +1,13 @@
package backend
import (
+ "bytes"
"database/sql"
"errors"
"fmt"
"html"
"net/http"
+ "net/mail"
"net/url"
"os"
"path/filepath"
@@ -39,6 +41,8 @@ func RegisterRoutes(mux *http.ServeMux) {
mux.HandleFunc("/transfer", transferHandler)
mux.HandleFunc("/transfer/", transferHandler)
mux.HandleFunc("/boxes/source", emailBoxHandler)
+ mux.HandleFunc("/boxes/source/messages", sourceMailboxMessagesHandler)
+ mux.HandleFunc("/boxes/source/message", sourceMailboxMessageHandler)
mux.HandleFunc("/boxes/target", emailBoxHandler)
mux.HandleFunc("/migrate/run", migrateRunHandler) // TODO Codex: RunMigration im Hintergrund
mux.HandleFunc("/migrate/status", migrateStatusHandler) // TODO Codex: jobs-Fortschritt (HTMX-Poll)
@@ -314,6 +318,63 @@ func emailBoxHandler(w http.ResponseWriter, r *http.Request) {
}
}
+func sourceMailboxMessagesHandler(w http.ResponseWriter, r *http.Request) {
+ accountName := strings.TrimSpace(r.URL.Query().Get("source"))
+ folder := strings.TrimSpace(r.URL.Query().Get("folder"))
+ w.Header().Set("Content-Type", "text/html; charset=utf-8")
+ if accountName == "" || folder == "" {
+ fmt.Fprint(w, `
Nachrichten
Quell-Postfach und Ordner waehlen.
`)
+ return
+ }
+ account, err := GetAccount(accountName)
+ if err != nil {
+ fmt.Fprintf(w, `Nachrichten
%s
`, html.EscapeString(err.Error()))
+ return
+ }
+ messages, err := fetchSourceFolderMessages(account, folder)
+ if err != nil {
+ fmt.Fprintf(w, `Nachrichten
%s
`, html.EscapeString(err.Error()))
+ return
+ }
+ renderSourceMailboxMessageList(w, account, folder, messages)
+}
+
+func sourceMailboxMessageHandler(w http.ResponseWriter, r *http.Request) {
+ accountName := strings.TrimSpace(r.URL.Query().Get("source"))
+ folder := strings.TrimSpace(r.URL.Query().Get("folder"))
+ index, err := strconv.Atoi(r.URL.Query().Get("index"))
+ if err != nil {
+ http.Error(w, "bad index", http.StatusBadRequest)
+ return
+ }
+ account, err := GetAccount(accountName)
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusBadRequest)
+ return
+ }
+ messages, err := fetchSourceFolderMessages(account, folder)
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusBadRequest)
+ return
+ }
+ if index < 0 || index >= len(messages) {
+ http.Error(w, "message index out of range", http.StatusNotFound)
+ return
+ }
+ raw := messages[index].Body
+ msg, err := mail.ReadMessage(bytes.NewReader(raw))
+ if err != nil {
+ renderReadPaneWithSource(w, account.Name, folder, "", index, "(unlesbar)", "", "", string(raw))
+ return
+ }
+ renderReadPaneWithSource(w, account.Name, folder, "", index,
+ decodeHeader(msg.Header.Get("Subject")),
+ decodeHeader(msg.Header.Get("From")),
+ decodeHeader(msg.Header.Get("Date")),
+ messageBody(raw),
+ )
+}
+
func archiveCreateHandler(w http.ResponseWriter, r *http.Request) {
if !requireManager(w, r) {
return
@@ -920,8 +981,50 @@ func renderSourceFolders(b *strings.Builder, account Account) {
return
}
for _, folder := range folders {
- fmt.Fprintf(b, `%s%s
`,
- html.EscapeString(folder.Name), html.EscapeString(strings.Join(folder.Attrs, " ")))
+ fmt.Fprintf(b, `%s%s`,
+ urlEsc(account.Name), urlEsc(folder.Name), html.EscapeString(folder.Name), html.EscapeString(strings.Join(folder.Attrs, " ")))
+ }
+}
+
+func fetchSourceFolderMessages(account Account, folder string) ([]RawMessage, error) {
+ if accountProto(account) == "pop3" {
+ src, err := OpenPOP3Source(account)
+ if err != nil {
+ return nil, err
+ }
+ defer src.Close()
+ return src.Fetch(folder)
+ }
+ src, err := OpenIMAPSource(account)
+ if err != nil {
+ return nil, err
+ }
+ defer src.Close()
+ return src.Fetch(folder)
+}
+
+func renderSourceMailboxMessageList(w http.ResponseWriter, account Account, folder string, messages []RawMessage) {
+ fmt.Fprintf(w, `%s / %s (%d)
`, html.EscapeString(account.SrcUser), html.EscapeString(folder), len(messages))
+ for i, raw := range messages {
+ subject := "(ohne Betreff)"
+ from := "(ohne Absender)"
+ date := ""
+ if msg, err := mail.ReadMessage(bytes.NewReader(raw.Body)); err == nil {
+ if v := decodeHeader(msg.Header.Get("Subject")); v != "" {
+ subject = v
+ }
+ if v := decodeHeader(msg.Header.Get("From")); v != "" {
+ from = v
+ }
+ date = decodeHeader(msg.Header.Get("Date"))
+ }
+ fmt.Fprintf(w, `%s%s%s`,
+ html.EscapeString(account.Name), html.EscapeString(folder), i,
+ urlEsc(account.Name), urlEsc(folder), i,
+ html.EscapeString(from), html.EscapeString(subject), html.EscapeString(date))
+ }
+ if len(messages) == 0 {
+ fmt.Fprint(w, `Keine Nachrichten in diesem Quell-Ordner.
`)
}
}