GODT-967 Append external message to All Mail should be APPEND to Archive instead

This commit is contained in:
Xavier Michelon
2021-09-21 15:30:16 +02:00
committed by Jakub Cuth
parent 6b7e706100
commit 0cf1b38c2b
2 changed files with 52 additions and 19 deletions

View File

@ -20,6 +20,7 @@ package imap
import ( import (
"bufio" "bufio"
"bytes" "bytes"
"fmt"
"io/ioutil" "io/ioutil"
"net/mail" "net/mail"
"strings" "strings"
@ -145,6 +146,16 @@ func (im *imapMailbox) createDraftMessage(kr *crypto.KeyRing, email string, body
return uidplus.AppendResponse(im.storeMailbox.UIDValidity(), im.storeMailbox.GetUIDList([]string{draft.ID})) return uidplus.AppendResponse(im.storeMailbox.UIDValidity(), im.storeMailbox.GetUIDList([]string{draft.ID}))
} }
func findMailboxForAddress(address storeAddressProvider, labelID string) (storeMailboxProvider, error) {
for _, mailBox := range address.ListMailboxes() {
if mailBox.LabelID() == labelID {
return mailBox, nil
}
}
return nil, fmt.Errorf("could not find %v label in mailbox for user %v", labelID,
address.AddressString())
}
func (im *imapMailbox) labelExistingMessage(msg storeMessageProvider) error { //nolint[funlen] func (im *imapMailbox) labelExistingMessage(msg storeMessageProvider) error { //nolint[funlen]
im.log.Info("Labelling existing message") im.log.Info("Labelling existing message")
@ -161,29 +172,20 @@ func (im *imapMailbox) labelExistingMessage(msg storeMessageProvider) error { //
} }
} }
storeMBox := im.storeMailbox
// Outlook Uses APPEND instead of COPY. There is no need to copy to All Mail because messages are already there. // Outlook Uses APPEND instead of COPY. There is no need to copy to All Mail because messages are already there.
// If the message is copied from Spam or Trash, it must be moved otherwise we will have data loss. // If the message is copied from Spam or Trash, it must be moved otherwise we will have data loss.
// If the message is moved from any folder, the moment when expunge happens on source we will move message trash unless we move it to archive. // If the message is moved from any folder, the moment when expunge happens on source we will move message trash unless we move it to archive.
// If the message is already in Archive we should not call API at all. // If the message is already in Archive we should not call API at all.
// Otherwise the message is already in All mail, Return OK. // Otherwise the message is already in All mail, Return OK.
var storeMBox = im.storeMailbox
if pmapi.AllMailLabel == storeMBox.LabelID() { if pmapi.AllMailLabel == storeMBox.LabelID() {
if msg.Message().HasLabelID(pmapi.ArchiveLabel) { if msg.Message().HasLabelID(pmapi.ArchiveLabel) {
return uidplus.AppendResponse(im.storeMailbox.UIDValidity(), im.storeMailbox.GetUIDList([]string{msg.ID()})) return uidplus.AppendResponse(storeMBox.UIDValidity(), storeMBox.GetUIDList([]string{msg.ID()}))
} }
var err error
foundArchive := false storeMBox, err = findMailboxForAddress(im.storeAddress, pmapi.ArchiveLabel)
for _, mBox := range im.storeAddress.ListMailboxes() { if err != nil {
if mBox.LabelID() == pmapi.ArchiveLabel { return err
foundArchive = true
storeMBox = mBox
break
}
}
if !foundArchive {
return errors.New("could not find Archive folder")
} }
} }
@ -194,7 +196,7 @@ func (im *imapMailbox) labelExistingMessage(msg storeMessageProvider) error { //
return uidplus.AppendResponse(im.storeMailbox.UIDValidity(), im.storeMailbox.GetUIDList([]string{msg.ID()})) return uidplus.AppendResponse(im.storeMailbox.UIDValidity(), im.storeMailbox.GetUIDList([]string{msg.ID()}))
} }
func (im *imapMailbox) importMessage(kr *crypto.KeyRing, hdr textproto.Header, body []byte, imapFlags []string, date time.Time) error { func (im *imapMailbox) importMessage(kr *crypto.KeyRing, hdr textproto.Header, body []byte, imapFlags []string, date time.Time) error { //nolint[funlen]
im.log.Info("Importing external message") im.log.Info("Importing external message")
var ( var (
@ -236,18 +238,29 @@ func (im *imapMailbox) importMessage(kr *crypto.KeyRing, hdr textproto.Header, b
return err return err
} }
messageID, err := im.storeMailbox.ImportMessage(enc, seen, labelIDs, flags, time) var targetMailbox = im.storeMailbox
if targetMailbox.LabelID() == pmapi.AllMailLabel {
// Importing mail in directly into All Mail is not allowed. Instead we redirect the import to Archive
// The mail will automatically appear in All mail. The appends response still reports that the mail was
// successfully APPEND to All Mail.
targetMailbox, err = findMailboxForAddress(im.storeAddress, pmapi.ArchiveLabel)
if err != nil {
return err
}
}
messageID, err := targetMailbox.ImportMessage(enc, seen, labelIDs, flags, time)
if err != nil { if err != nil {
return err return err
} }
msg, err := im.storeMailbox.GetMessage(messageID) msg, err := targetMailbox.GetMessage(messageID)
if err != nil { if err != nil {
return err return err
} }
if msg.IsMarkedDeleted() { if msg.IsMarkedDeleted() {
if err := im.storeMailbox.MarkMessagesUndeleted([]string{messageID}); err != nil { if err := targetMailbox.MarkMessagesUndeleted([]string{messageID}); err != nil {
log.WithError(err).Error("Failed to undelete re-imported message") log.WithError(err).Error("Failed to undelete re-imported message")
} }
} }

View File

@ -198,3 +198,23 @@ Feature: IMAP import messages
""" """
Then IMAP response is "OK \[APPENDUID \d 1\] APPEND completed" Then IMAP response is "OK \[APPENDUID \d 1\] APPEND completed"
Scenario: Import message to All Mail
When IMAP client imports message to "All Mail"
"""
From: Foo <from1@pm.me>
To: Bridge Test <to1@pm.me>
Subject: subj1
Received: by 2002:0:0:0:0:0:0:0 with SMTP id 0123456789abcdef; Wed, 30 Dec 2020 01:23:45 0000
body1
"""
Then IMAP response is "OK \[APPENDUID \d 1\] APPEND completed"
Then mailbox "Archive" for "user" has messages
| from | to | subject | body
| from1@pm.me | to1@pm.me | subj1 | body1
And API mailbox "Archive" for "user" has 1 message
And mailbox "All Mail" for "user" has messages
| from | to | subject | body
| from1@pm.me | to1@pm.me | subj1 | body1
And API mailbox "All Mail" for "user" has 1 message