Skip to content

Commit

Permalink
fix(GODT-2782): Filter all labels when doing perma delete check
Browse files Browse the repository at this point in the history
Previously we were not filtering out labels we ignored from the
perma-delete check. The introduction of new system label types could
break this check leading to user never being able to perma-delete
messages.
  • Loading branch information
LBeernaertProton committed Jul 11, 2023
1 parent 0e9fd46 commit 7997ad2
Showing 1 changed file with 49 additions and 15 deletions.
64 changes: 49 additions & 15 deletions internal/user/imap.go
Original file line number Diff line number Diff line change
Expand Up @@ -418,33 +418,67 @@ func (conn *imapConnector) RemoveMessagesFromMailbox(ctx context.Context, messag
}

if mailboxID == proton.TrashLabel || mailboxID == proton.DraftsLabel {
var metadata []proton.MessageMetadata

var msgToPermaDelete []string
// There's currently no limit on how many IDs we can filter on,
// but to be nice to API, let's chunk it by 150.
for _, messageIDs := range xslices.Chunk(messageIDs, 150) {
m, err := conn.client.GetMessageMetadata(ctx, proton.MessageFilter{
metadata, err := conn.client.GetMessageMetadata(ctx, proton.MessageFilter{
ID: mapTo[imap.MessageID, string](messageIDs),
})
if err != nil {
return err
}

// If a message is not preset in any other label other than AllMail, AllDrafts and AllSent, it can be
// permanently deleted.
m = xslices.Filter(m, func(m proton.MessageMetadata) bool {
labelsThatMatter := xslices.Filter(m.LabelIDs, func(id string) bool {
return id != proton.AllDraftsLabel && id != proton.AllMailLabel && id != proton.AllSentLabel
})
return len(labelsThatMatter) == 0
})
msgIds, err := safe.LockRetErr(func() ([]string, error) {
var msgIds []string

// If a message is not preset in any other label other than AllMail, AllDrafts and AllSent, it can be
// permanently deleted.
for _, m := range metadata {
var remainingLabels []string

for _, id := range m.LabelIDs {
label, ok := conn.apiLabels[id]
if !ok {
// Handle case where this label was newly introduced and we do not yet know about it.
logrus.WithField("labelID", id).Warnf("Unknown label found during expung from Trash, attempting to locate it")
label, err = conn.client.GetLabel(ctx, id, proton.LabelTypeFolder, proton.LabelTypeSystem, proton.LabelTypeSystem)
if err != nil {
if errors.Is(err, proton.ErrNoSuchLabel) {
logrus.WithField("labelID", id).Warn("Label does not exist, ignoring")
continue
}

logrus.WithField("labelID", id).Errorf("Failed to resolve label: %v", err)
return nil, fmt.Errorf("failed to resolve label: %w", err)
}
}
if !wantLabel(label) {
continue
}

if id != proton.AllDraftsLabel && id != proton.AllMailLabel && id != proton.AllSentLabel {
remainingLabels = append(remainingLabels, m.ID)
}
}

if len(remainingLabels) == 0 {
msgIds = append(msgIds, m.ID)
}
}

return msgIds, nil
}, conn.User.apiLabelsLock)
if err != nil {
return err
}

metadata = append(metadata, m...)
msgToPermaDelete = append(msgToPermaDelete, msgIds...)
}

if err := conn.client.DeleteMessage(ctx, xslices.Map(metadata, func(m proton.MessageMetadata) string {
return m.ID
})...); err != nil {
logrus.Debugf("Following message(s) will be perma-deleted: %v", msgToPermaDelete)

if err := conn.client.DeleteMessage(ctx, msgToPermaDelete...); err != nil {
return err
}
}
Expand Down

0 comments on commit 7997ad2

Please sign in to comment.