Sync all IMAP folders

This commit is contained in:
DonVoo 2026-07-05 23:03:52 +02:00
parent bb2bcb0576
commit 569b274b2c
4 changed files with 228 additions and 32 deletions

View file

@ -86,49 +86,75 @@ func migrateAccount(a Account) error {
return err
}
jobID, _ := startJob(a.ID)
msgs, err := src.Fetch("INBOX")
folders, err := src.Folders()
if err != nil {
_ = finishJob(jobID, 0, 0, 1, "error")
return err
}
if err := dst.EnsureFolder("INBOX"); err != nil {
_ = finishJob(jobID, len(msgs), 0, 1, "error")
targets, err := dst.Folders()
if err != nil {
_ = finishJob(jobID, 0, 0, 1, "error")
return err
}
done, errs := 0, 0
for _, m := range msgs {
already, err := AlreadyCopied(a.ID, "INBOX", m.MessageID)
total, done, errs := 0, 0, 0
for _, folder := range folders {
dstFolder := MapSourceToTarget(folder.Name, folder.Attrs, folder.Delim, dst.Delim(), targets, "")
if dstFolder == "" {
dstFolder = folder.Name
}
msgs, err := src.Fetch(folder.Name)
if err != nil {
errs++
log.Printf("%s INBOX dedup error %s: %v", a.Name, m.MessageID, err)
log.Printf("%s %s fetch error: %v", a.Name, folder.Name, err)
continue
}
if already {
continue
}
if err := dst.Append("INBOX", m); err != nil {
total += len(msgs)
if err := dst.EnsureFolder(dstFolder); err != nil {
errs++
log.Printf("%s INBOX append error %s: %v", a.Name, m.MessageID, err)
log.Printf("%s %s ensure target %s error: %v", a.Name, folder.Name, dstFolder, err)
continue
}
if err := mbox.Append("INBOX", m); err != nil {
errs++
log.Printf("%s INBOX mbox error %s: %v", a.Name, m.MessageID, err)
continue
folderDone, folderErrs := 0, 0
for _, m := range msgs {
already, err := AlreadyCopied(a.ID, folder.Name, m.MessageID)
if err != nil {
errs++
folderErrs++
log.Printf("%s %s dedup error %s: %v", a.Name, folder.Name, m.MessageID, err)
continue
}
if already {
continue
}
if err := dst.Append(dstFolder, m); err != nil {
errs++
folderErrs++
log.Printf("%s %s append to %s error %s: %v", a.Name, folder.Name, dstFolder, m.MessageID, err)
continue
}
if err := mbox.Append(folder.Name, m); err != nil {
errs++
folderErrs++
log.Printf("%s %s mbox error %s: %v", a.Name, folder.Name, m.MessageID, err)
continue
}
if err := MarkCopied(a.ID, folder.Name, m.MessageID); err != nil {
errs++
folderErrs++
log.Printf("%s %s mark error %s: %v", a.Name, folder.Name, m.MessageID, err)
continue
}
done++
folderDone++
}
if err := MarkCopied(a.ID, "INBOX", m.MessageID); err != nil {
errs++
log.Printf("%s INBOX mark error %s: %v", a.Name, m.MessageID, err)
continue
}
done++
log.Printf("migration %s %s -> %s: total=%d copied=%d errors=%d", a.Name, folder.Name, dstFolder, len(msgs), folderDone, folderErrs)
}
state := "success"
if errs > 0 {
state = "partial"
}
_ = finishJob(jobID, len(msgs), done, errs, state)
log.Printf("migration %s INBOX: total=%d copied=%d errors=%d", a.Name, len(msgs), done, errs)
_ = finishJob(jobID, total, done, errs, state)
log.Printf("migration %s all folders: total=%d copied=%d errors=%d", a.Name, total, done, errs)
if errs > 0 {
return fmt.Errorf("migration %s finished with %d errors", a.Name, errs)
}
@ -145,16 +171,25 @@ func CheckAccount(name string) error {
return fmt.Errorf("open source %s: %w", a.Name, err)
}
defer src.Close()
msgs, err := src.Fetch("INBOX")
folders, err := src.Folders()
if err != nil {
return fmt.Errorf("fetch source INBOX %s: %w", a.Name, err)
return fmt.Errorf("list source folders %s: %w", a.Name, err)
}
total := 0
for _, folder := range folders {
msgs, err := src.Fetch(folder.Name)
if err != nil {
return fmt.Errorf("fetch source %s %s: %w", a.Name, folder.Name, err)
}
log.Printf("account %s source folder %s messages=%d", a.Name, folder.Name, len(msgs))
total += len(msgs)
}
dst, err := OpenIMAPTarget(a)
if err != nil {
return fmt.Errorf("open target %s: %w", a.Name, err)
}
defer dst.Close()
log.Printf("account %s ok: source INBOX messages=%d, target login ok", a.Name, len(msgs))
log.Printf("account %s ok: source folders=%d messages=%d, target login ok", a.Name, len(folders), total)
return nil
}