From e34050282e211d3fe070949e811f7e62cfabdc01 Mon Sep 17 00:00:00 2001 From: Leander Beernaert Date: Tue, 11 Jul 2023 16:04:36 +0200 Subject: [PATCH] fix(GODT-2764): Allow perma-delete for messages which still have labels Rather than match the web client behavior (removing labels) when messages are appended to trash, we simply omit the check to see if the message in trash is present in other labels. This will produce the same end result and will resolve the issue of users not being able to fully delete their messages. --- internal/user/imap.go | 65 +------------------ .../imap/message/delete_from_trash.feature | 6 +- 2 files changed, 6 insertions(+), 65 deletions(-) diff --git a/internal/user/imap.go b/internal/user/imap.go index 018d9194..e3e2b7a5 100644 --- a/internal/user/imap.go +++ b/internal/user/imap.go @@ -419,72 +419,13 @@ func (conn *imapConnector) RemoveMessagesFromMailbox(ctx context.Context, messag return connector.ErrOperationNotAllowed } - if err := conn.client.UnlabelMessages(ctx, mapTo[imap.MessageID, string](messageIDs), string(mailboxID)); err != nil { + msgIDs := mapTo[imap.MessageID, string](messageIDs) + if err := conn.client.UnlabelMessages(ctx, msgIDs, string(mailboxID)); err != nil { return err } if mailboxID == proton.TrashLabel || mailboxID == proton.DraftsLabel { - 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) { - metadata, err := conn.client.GetMessageMetadata(ctx, proton.MessageFilter{ - ID: mapTo[imap.MessageID, string](messageIDs), - }) - if err != nil { - return err - } - - 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 - } - - msgToPermaDelete = append(msgToPermaDelete, msgIds...) - } - - logrus.Debugf("Following message(s) will be perma-deleted: %v", msgToPermaDelete) - - if err := conn.client.DeleteMessage(ctx, msgToPermaDelete...); err != nil { + if err := conn.client.DeleteMessage(ctx, msgIDs...); err != nil { return err } } diff --git a/tests/features/imap/message/delete_from_trash.feature b/tests/features/imap/message/delete_from_trash.feature index 15446eed..a8323e91 100644 --- a/tests/features/imap/message/delete_from_trash.feature +++ b/tests/features/imap/message/delete_from_trash.feature @@ -7,7 +7,7 @@ Feature: IMAP remove messages from Trash | label | label | Then it succeeds - Scenario Outline: Message in Trash and some other label is not permanently deleted + Scenario Outline: Message in Trash and some other label is permanently deleted Given the address "[user:user]@[domain]" of account "[user:user]" has the following messages in "Trash": | from | to | subject | body | | john.doe@mail.com | [user:user]@[domain] | foo | hello | @@ -27,8 +27,8 @@ Feature: IMAP remove messages from Trash When IMAP client "1" expunges Then it succeeds And IMAP client "1" eventually sees 1 messages in "Trash" - And IMAP client "1" eventually sees 2 messages in "All Mail" - And IMAP client "1" eventually sees 1 messages in "Labels/label" + And IMAP client "1" eventually sees 1 messages in "All Mail" + And IMAP client "1" eventually sees 0 messages in "Labels/label" Scenario Outline: Message in Trash only is permanently deleted Given the address "[user:user]@[domain]" of account "[user:user]" has the following messages in "Trash":