package backend import "strings" // TargetMailbox = das Ziel-Postfach (neuer Host). Der Umzug schreibt hier per // IMAP APPEND hinein -- NICHT per SMTP. APPEND erhaelt Ordner, Flags und // Original-Datum; SMTP wuerde alles als "neu/ungelesen" mit falschem Datum // zustellen und die Ordnerstruktur zerstoeren. type TargetMailbox interface { Folders() ([]TargetFolder, error) // vorhandene Ziel-Ordner (fuer Rollen-Zuordnung) Delim() string // Hierarchie-Trenner des Ziels EnsureFolder(name string) error // anlegen + subscriben, falls fehlt Append(folder string, m RawMessage) error // mit m.Flags und m.InternalDate Close() error } // OpenIMAPTarget verbindet das Ziel per go-imap/v2 (Security wie Quelle, siehe // a.DstSecurity/a.DstInsecure; meist "tls"). func OpenIMAPTarget(a Account) (TargetMailbox, error) { c, err := dialIMAP(a.DstHost, a.DstPort, a.DstSecurity, a.DstInsecure) if err != nil { return nil, err } if err := c.login(a.DstUser, a.DstPass); err != nil { _ = c.Close() return nil, err } return &imapTarget{c: c}, nil } type imapTarget struct { c *simpleIMAP delim string } func (t *imapTarget) Folders() ([]TargetFolder, error) { boxes, err := t.c.listMailboxes() if err != nil { return nil, err } folders := make([]TargetFolder, 0, len(boxes)) for _, box := range boxes { if t.delim == "" && box.Delim != "" { t.delim = box.Delim } if hasIMAPAttr(box.Attrs, `\Noselect`) { continue } folders = append(folders, TargetFolder{Name: box.Name, Attrs: box.Attrs}) } if len(folders) == 0 { folders = append(folders, TargetFolder{Name: "INBOX"}) } return folders, nil } func (t *imapTarget) Delim() string { if t.delim != "" { return t.delim } return "/" } func (t *imapTarget) EnsureFolder(name string) error { if name == "INBOX" { return nil } if err := t.c.simple("CREATE " + imapQuote(name)); err != nil { if !strings.Contains(strings.ToLower(err.Error()), "exist") && !strings.Contains(strings.ToLower(err.Error()), "already") { return err } } _ = t.c.simple("SUBSCRIBE " + imapQuote(name)) return nil } func (t *imapTarget) Append(folder string, m RawMessage) error { return t.c.appendMessage(folder, m) } func (t *imapTarget) Close() error { return t.c.Close() }