mirror of
https://github.com/mjl-/mox.git
synced 2024-12-26 16:33:47 +03:00
when moving/copying messages in imapserve, also ensure the message keywords make it into the destination mailbox keywords list
This commit is contained in:
parent
f9e261e0fb
commit
2e5376d7eb
2 changed files with 35 additions and 6 deletions
|
@ -60,6 +60,7 @@ import (
|
|||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||
"golang.org/x/exp/slices"
|
||||
"golang.org/x/text/unicode/norm"
|
||||
|
||||
"github.com/mjl-/bstore"
|
||||
|
@ -2083,6 +2084,7 @@ func (c *conn) cmdRename(tag, cmd string, p *parser) {
|
|||
Name: dst,
|
||||
UIDValidity: uidval,
|
||||
UIDNext: 1,
|
||||
Keywords: srcMB.Keywords,
|
||||
}
|
||||
err = tx.Insert(&dstMB)
|
||||
xcheckf(err, "create new destination mailbox")
|
||||
|
@ -3001,8 +3003,6 @@ func (c *conn) cmdxCopy(isUID bool, tag, cmd string, p *parser) {
|
|||
// Reserve the uids in the destination mailbox.
|
||||
uidFirst := mbDst.UIDNext
|
||||
mbDst.UIDNext += store.UID(len(uidargs))
|
||||
err := tx.Update(&mbDst)
|
||||
xcheckf(err, "reserve uid in destination mailbox")
|
||||
|
||||
// Fetch messages from database.
|
||||
q := bstore.QueryTx[store.Message](tx)
|
||||
|
@ -3023,6 +3023,8 @@ func (c *conn) cmdxCopy(isUID bool, tag, cmd string, p *parser) {
|
|||
|
||||
conf, _ := c.account.Conf()
|
||||
|
||||
mbKeywords := map[string]struct{}{}
|
||||
|
||||
// Insert new messages into database.
|
||||
var origMsgIDs, newMsgIDs []int64
|
||||
for i, uid := range uids {
|
||||
|
@ -3051,6 +3053,9 @@ func (c *conn) cmdxCopy(isUID bool, tag, cmd string, p *parser) {
|
|||
newMsgIDs = append(newMsgIDs, m.ID)
|
||||
flags = append(flags, m.Flags)
|
||||
keywords = append(keywords, m.Keywords)
|
||||
for _, kw := range m.Keywords {
|
||||
mbKeywords[kw] = struct{}{}
|
||||
}
|
||||
|
||||
qmr := bstore.QueryTx[store.Recipient](tx)
|
||||
qmr.FilterNonzero(store.Recipient{MessageID: origID})
|
||||
|
@ -3064,6 +3069,16 @@ func (c *conn) cmdxCopy(isUID bool, tag, cmd string, p *parser) {
|
|||
}
|
||||
}
|
||||
|
||||
// Ensure destination mailbox has keywords of the moved messages.
|
||||
for kw := range mbKeywords {
|
||||
if !slices.Contains(mbDst.Keywords, kw) {
|
||||
mbDst.Keywords = append(mbDst.Keywords, kw)
|
||||
}
|
||||
}
|
||||
|
||||
err = tx.Update(&mbDst)
|
||||
xcheckf(err, "updating destination mailbox for uids and keywords")
|
||||
|
||||
// Copy message files to new message ID's.
|
||||
syncDirs := map[string]struct{}{}
|
||||
for i := range origMsgIDs {
|
||||
|
@ -3146,8 +3161,6 @@ func (c *conn) cmdxMove(isUID bool, tag, cmd string, p *parser) {
|
|||
uidFirst := mbDst.UIDNext
|
||||
uidnext := uidFirst
|
||||
mbDst.UIDNext += store.UID(len(uids))
|
||||
err := tx.Update(&mbDst)
|
||||
xcheckf(err, "reserve uids in destination mailbox")
|
||||
|
||||
// Update UID and MailboxID in database for messages.
|
||||
q := bstore.QueryTx[store.Message](tx)
|
||||
|
@ -3161,6 +3174,8 @@ func (c *conn) cmdxMove(isUID bool, tag, cmd string, p *parser) {
|
|||
xserverErrorf("uid and message mismatch")
|
||||
}
|
||||
|
||||
keywords := map[string]struct{}{}
|
||||
|
||||
conf, _ := c.account.Conf()
|
||||
for i := range msgs {
|
||||
m := &msgs[i]
|
||||
|
@ -3178,8 +3193,22 @@ func (c *conn) cmdxMove(isUID bool, tag, cmd string, p *parser) {
|
|||
uidnext++
|
||||
err := tx.Update(m)
|
||||
xcheckf(err, "updating moved message in database")
|
||||
|
||||
for _, kw := range m.Keywords {
|
||||
keywords[kw] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure destination mailbox has keywords of the moved messages.
|
||||
for kw := range keywords {
|
||||
if !slices.Contains(mbDst.Keywords, kw) {
|
||||
mbDst.Keywords = append(mbDst.Keywords, kw)
|
||||
}
|
||||
}
|
||||
|
||||
err = tx.Update(&mbDst)
|
||||
xcheckf(err, "updating destination mailbox for uids and keywords")
|
||||
|
||||
err = c.account.RetrainMessages(context.TODO(), c.log, tx, msgs, false)
|
||||
xcheckf(err, "retraining messages after move")
|
||||
|
||||
|
|
|
@ -292,7 +292,7 @@ type Message struct {
|
|||
|
||||
MessageHash []byte // Hash of message. For rejects delivery, so optional like MessageID.
|
||||
Flags
|
||||
Keywords []string `bstore:"index"` // Non-system or well-known $-flags. Only in "atom" syntax, stored in lower case.
|
||||
Keywords []string `bstore:"index"` // For keywords other than system flags or the basic well-known $-flags. Only in "atom" syntax, stored in lower case.
|
||||
Size int64
|
||||
TrainedJunk *bool // If nil, no training done yet. Otherwise, true is trained as junk, false trained as nonjunk.
|
||||
MsgPrefix []byte // Typically holds received headers and/or header separator.
|
||||
|
@ -1345,7 +1345,7 @@ func RemoveKeywords(l, remove []string) []string {
|
|||
func MergeKeywords(l, add []string) ([]string, bool) {
|
||||
var changed bool
|
||||
for _, k := range add {
|
||||
if slices.Index(l, k) < 0 {
|
||||
if !slices.Contains(l, k) {
|
||||
l = append(l, k)
|
||||
changed = true
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue