fix(GODT-2956): Restore old deletion rules

When unlabeling a message from trash we have to check if this message is
present in another folder before perma-deleting.
This commit is contained in:
Leander Beernaert 2023-09-26 12:47:53 +02:00
parent bfe25e3a46
commit bbe19bf960
3 changed files with 82 additions and 5 deletions

View File

@ -37,6 +37,7 @@ import (
"github.com/ProtonMail/proton-bridge/v3/pkg/message"
"github.com/ProtonMail/proton-bridge/v3/pkg/message/parser"
"github.com/bradenaw/juniper/stream"
"github.com/bradenaw/juniper/xslices"
"github.com/sirupsen/logrus"
"golang.org/x/exp/slices"
)
@ -334,8 +335,69 @@ func (s *Connector) RemoveMessagesFromMailbox(ctx context.Context, _ connector.I
}
if mboxID == proton.TrashLabel || mboxID == proton.DraftsLabel {
if err := s.client.DeleteMessage(ctx, msgIDs...); err != nil {
return err
const ChunkSize = 150
var msgToPermaDelete []string
rdLabels := s.labels.Read()
defer rdLabels.Close()
// 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, ChunkSize) {
metadata, err := s.client.GetMessageMetadataPage(ctx, 0, ChunkSize, proton.MessageFilter{
ID: usertypes.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.
for _, m := range metadata {
var remainingLabels []string
for _, id := range m.LabelIDs {
label, ok := rdLabels.GetLabel(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 = s.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 fmt.Errorf("failed to resolve label: %w", err)
}
}
if !WantLabel(label) {
continue
}
if label.Type == proton.LabelTypeSystem && (id == proton.AllDraftsLabel ||
id == proton.AllMailLabel ||
id == proton.AllSentLabel ||
id == proton.AllScheduledLabel) {
continue
}
remainingLabels = append(remainingLabels, m.ID)
}
if len(remainingLabels) == 0 {
msgToPermaDelete = append(msgToPermaDelete, m.ID)
}
}
}
if len(msgToPermaDelete) != 0 {
logrus.Debugf("Following message(s) will be perma-deleted: %v", msgToPermaDelete)
if err := s.client.DeleteMessage(ctx, msgToPermaDelete...); err != nil {
return err
}
}
}

View File

@ -85,3 +85,18 @@ Feature: IMAP copy messages
| from | to | subject | unread |
| john.doe@mail.com | [user:user]@[domain] | foo | false |
Scenario: Move message to trash then copy to folder does not delete message
When IMAP client "1" moves the message with subject "foo" from "INBOX" to "Trash"
And it succeeds
Then IMAP client "1" eventually sees the following messages in "Trash":
| from | to | subject | unread |
| john.doe@mail.com | [user:user]@[domain] | foo | false |
When IMAP client "1" copies the message with subject "foo" from "Trash" to "Folders/mbox"
And it succeeds
When IMAP client "1" marks the message with subject "foo" as deleted
Then it succeeds
When IMAP client "1" expunges
Then it succeeds
Then IMAP client "1" eventually sees the following messages in "Folders/mbox":
| from | to | subject | unread |
| john.doe@mail.com | [user:user]@[domain] | foo | false |

View File

@ -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 permanently deleted
Scenario Outline: Message in Trash and some other label is not 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 1 messages in "All Mail"
And IMAP client "1" eventually sees 0 messages in "Labels/label"
And IMAP client "1" eventually sees 2 messages in "All Mail"
And IMAP client "1" eventually sees 1 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":