Add CLI INBOX migration breakthrough
This commit is contained in:
parent
8a6160817b
commit
27206930f0
6 changed files with 713 additions and 43 deletions
|
|
@ -1,25 +1,62 @@
|
|||
package backend
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// mbox ist das lokale Cold-Backup-Format: eine Datei pro IMAP-Ordner, der
|
||||
// Ordnerbaum 1:1 auf der Platte. eM Client / Thunderbird importieren mbox
|
||||
// direkt. (Kein PST -- das laesst sich in Go nicht lean schreiben.)
|
||||
|
||||
// MboxWriter haengt Nachrichten an die mbox-Datei eines Ordners an.
|
||||
type MboxWriter struct {
|
||||
// TODO Codex: root-Verzeichnis des Kontos.
|
||||
root string
|
||||
}
|
||||
|
||||
// NewMboxWriter legt <mboxRoot>/<account>/ an und spiegelt den Ordnerbaum.
|
||||
func NewMboxWriter(dir string) (*MboxWriter, error) {
|
||||
// TODO Codex.
|
||||
return nil, nil
|
||||
if err := os.MkdirAll(dir, 0o700); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &MboxWriter{root: dir}, nil
|
||||
}
|
||||
|
||||
// Append schreibt eine Mail im mbox-Format ("From "-Trennzeile, >From-Quoting)
|
||||
// in <ordner>.mbox.
|
||||
func (w *MboxWriter) Append(folder string, m RawMessage) error {
|
||||
// TODO Codex.
|
||||
return nil
|
||||
path := filepath.Join(w.root, safeMboxName(folder)+".mbox")
|
||||
if err := os.MkdirAll(filepath.Dir(path), 0o700); err != nil {
|
||||
return err
|
||||
}
|
||||
f, err := os.OpenFile(path, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0o600)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
fromDate := m.InternalDate
|
||||
if fromDate.IsZero() {
|
||||
fromDate = time.Now()
|
||||
}
|
||||
if _, err := fmt.Fprintf(f, "From MAILER-DAEMON %s\r\n", fromDate.Format("Mon Jan _2 15:04:05 2006")); err != nil {
|
||||
return err
|
||||
}
|
||||
body := bytes.ReplaceAll(m.Body, []byte("\r\nFrom "), []byte("\r\n>From "))
|
||||
body = bytes.ReplaceAll(body, []byte("\nFrom "), []byte("\n>From "))
|
||||
if _, err := f.Write(body); err != nil {
|
||||
return err
|
||||
}
|
||||
if !bytes.HasSuffix(body, []byte("\n")) {
|
||||
if _, err := f.WriteString("\r\n"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
_, err = f.WriteString("\r\n")
|
||||
return err
|
||||
}
|
||||
|
||||
// --- Viewer-Seite: mbox wieder lesen fuers Browser-Betrachten (08-viewer.go) ---
|
||||
|
|
@ -36,3 +73,14 @@ type MboxEntry struct {
|
|||
// 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 safeMboxName(folder string) string {
|
||||
folder = strings.TrimSpace(folder)
|
||||
folder = strings.ReplaceAll(folder, "\\", "_")
|
||||
folder = strings.ReplaceAll(folder, "/", "_")
|
||||
folder = strings.ReplaceAll(folder, ":", "_")
|
||||
if folder == "" {
|
||||
return "INBOX"
|
||||
}
|
||||
return folder
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue