fix bug with cli import command in case the mbox/maildir had keywords, future delivery to the mailbox would fail with duplicate uid's.

accounts with a mailbox with this problem can be fixed by running the "mox
fixuidmeta <account>" command.

we were resetting the mailbox uidnext after delivering messages when we were
setting new keywords on the mailbox at the end of the import. so in a future
delivery attempt to that mailbox, a uid would be chosen that was already
present.

the fix is to fetch the updated mailbox from the database before setting the
new keywords.

http/import.go doesn't have this bug because it was already fetching the
mailbox before updating keywords (because it can import into many mailboxes,
so different code).

the "mox verifydata" command (recommended with backups) also warns about this
issue (but doesn't fix it)

found while working on new functionality (webmail).
This commit is contained in:
Mechiel Lukkien
2023-07-26 09:24:24 +02:00
parent 700118dbd2
commit e3d0a3a001
3 changed files with 11 additions and 6 deletions

View File

@ -231,20 +231,20 @@ possibly making them potentially no longer readable by the previous version.
checkf(err, dbpath, "missing nextuidvalidity")
}
mailboxUIDNexts := map[int64]store.UID{}
mailboxes := map[int64]store.Mailbox{}
err := bstore.QueryDB[store.Mailbox](ctxbg, db).ForEach(func(mb store.Mailbox) error {
mailboxUIDNexts[mb.ID] = mb.UIDNext
mailboxes[mb.ID] = mb
if mb.UIDValidity >= uidvalidity.Next {
checkf(errors.New(`inconsistent uidvalidity for mailbox/account, see "mox fixuidmeta"`), dbpath, "mailbox id %d has uidvalidity %d >= account nextuidvalidity %d", mb.ID, mb.UIDValidity, uidvalidity.Next)
checkf(errors.New(`inconsistent uidvalidity for mailbox/account, see "mox fixuidmeta"`), dbpath, "mailbox %q (id %d) has uidvalidity %d >= account nextuidvalidity %d", mb.Name, mb.ID, mb.UIDValidity, uidvalidity.Next)
}
return nil
})
checkf(err, dbpath, "reading mailboxes to check uidnext consistency")
err = bstore.QueryDB[store.Message](ctxbg, db).ForEach(func(m store.Message) error {
if uidnext := mailboxUIDNexts[m.MailboxID]; m.UID >= uidnext {
checkf(errors.New(`inconsistent uidnext for message/mailbox, see "mox fixuidmeta"`), dbpath, "message id %d in mailbox id %d has uid %d >= mailbox uidnext %d", m.ID, m.MailboxID, m.UID, uidnext)
if mb := mailboxes[m.MailboxID]; m.UID >= mb.UIDNext {
checkf(errors.New(`inconsistent uidnext for message/mailbox, see "mox fixuidmeta"`), dbpath, "message id %d in mailbox %q (id %d) has uid %d >= mailbox uidnext %d", m.ID, mb.Name, mb.ID, m.UID, mb.UIDNext)
}
if m.Expunged {