4959173f39
Before copying, EXAMINE every folder to sum the account's total message count and emit a 'plan' event; progress events now carry account_total so the UI shows a real overall bar, percent and ETA (not just per-folder). - imapx.FolderMessageCount: read-only count of a folder - orchestrator: plan pass + grandTotal, plan event, account_total in progress - web: live progress keyed on account total; PLAN log line; overall bar/ETA Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MMHQTtnQtQqL8muAXHr9kd
53 lines
1.4 KiB
Go
53 lines
1.4 KiB
Go
package imapx
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/emersion/go-imap/v2"
|
|
"github.com/emersion/go-imap/v2/imapclient"
|
|
)
|
|
|
|
// FolderMessageCount opens a folder read-only (EXAMINE) and returns how many
|
|
// messages it holds — used to plan an accurate overall progress total before
|
|
// copying begins. It does not fetch any message bodies.
|
|
func FolderMessageCount(c *imapclient.Client, folder string) (int64, error) {
|
|
sel, err := c.Select(folder, &imap.SelectOptions{ReadOnly: true}).Wait()
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return int64(sel.NumMessages), nil
|
|
}
|
|
|
|
// ListFolders returns the mailbox names visible on an already-connected, logged-in client.
|
|
func ListFolders(c *imapclient.Client) ([]string, error) {
|
|
mboxes, err := c.List("", "*", nil).Collect()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
names := make([]string, 0, len(mboxes))
|
|
for _, m := range mboxes {
|
|
names = append(names, m.Mailbox)
|
|
}
|
|
return names, nil
|
|
}
|
|
|
|
func TestLogin(ctx context.Context, ep Endpoint, login, pass string) ([]string, error) {
|
|
c, err := Connect(ctx, ep)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer func() { _ = c.Logout().Wait() }()
|
|
if err := c.Login(login, pass).Wait(); err != nil {
|
|
return nil, err
|
|
}
|
|
mboxes, err := c.List("", "*", nil).Collect()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
names := make([]string, 0, len(mboxes))
|
|
for _, m := range mboxes {
|
|
names = append(names, m.Mailbox)
|
|
}
|
|
return names, nil
|
|
}
|