forked from Silverfish/proton-bridge
Replace old date to not crash Apple Mail
This commit is contained in:
@ -40,6 +40,10 @@ import (
|
||||
openpgperrors "golang.org/x/crypto/openpgp/errors"
|
||||
)
|
||||
|
||||
var (
|
||||
rfc822Birthday = time.Date(1982, 8, 13, 0, 0, 0, 0, time.UTC) //nolint[gochecknoglobals]
|
||||
)
|
||||
|
||||
type doNotCacheError struct{ e error }
|
||||
|
||||
func (dnc *doNotCacheError) Error() string { return dnc.e.Error() }
|
||||
@ -605,7 +609,7 @@ func (im *imapMailbox) buildMessageInner(m *pmapi.Message, kr *crypto.KeyRing) (
|
||||
}
|
||||
|
||||
tmpBuf := &bytes.Buffer{}
|
||||
mainHeader := message.GetHeader(m)
|
||||
mainHeader := buildHeader(m)
|
||||
if err = writeHeader(tmpBuf, mainHeader); err != nil {
|
||||
return
|
||||
}
|
||||
@ -703,3 +707,23 @@ func (im *imapMailbox) buildMessageInner(m *pmapi.Message, kr *crypto.KeyRing) (
|
||||
}
|
||||
return structure, msgBody, err
|
||||
}
|
||||
|
||||
func buildHeader(msg *pmapi.Message) textproto.MIMEHeader {
|
||||
header := message.GetHeader(msg)
|
||||
|
||||
msgTime := time.Unix(msg.Time, 0)
|
||||
|
||||
// Apple Mail crashes fetching messages with date older than 1970.
|
||||
// There is no point having message older than RFC itself, it's not possible.
|
||||
d, err := msg.Header.Date()
|
||||
if err != nil || d.Before(rfc822Birthday) || msgTime.Before(rfc822Birthday) {
|
||||
if err != nil || d.IsZero() {
|
||||
header.Set("X-Original-Date", msgTime.Format(time.RFC1123Z))
|
||||
} else {
|
||||
header.Set("X-Original-Date", d.Format(time.RFC1123Z))
|
||||
}
|
||||
header.Set("Date", rfc822Birthday.Format(time.RFC1123Z))
|
||||
}
|
||||
|
||||
return header
|
||||
}
|
||||
|
||||
@ -20,8 +20,10 @@ package fakeapi
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/mail"
|
||||
"strings"
|
||||
|
||||
messageUtils "github.com/ProtonMail/proton-bridge/pkg/message"
|
||||
"github.com/ProtonMail/proton-bridge/pkg/pmapi"
|
||||
)
|
||||
|
||||
@ -139,6 +141,7 @@ func (ctl *Controller) AddUserMessage(username string, message *pmapi.Message) (
|
||||
}
|
||||
message.ID = ctl.messageIDGenerator.next("")
|
||||
message.LabelIDs = append(message.LabelIDs, pmapi.AllMailLabel)
|
||||
message.Header = mail.Header(messageUtils.GetHeader(message))
|
||||
ctl.messagesByUsername[username] = append(ctl.messagesByUsername[username], message)
|
||||
ctl.resetUsers()
|
||||
return message.ID, nil
|
||||
|
||||
@ -60,3 +60,17 @@ Feature: IMAP fetch messages
|
||||
When IMAP client fetches by UID "1:*"
|
||||
Then IMAP response is "OK"
|
||||
And IMAP response has 2 message
|
||||
|
||||
Scenario: Fetch of very old message sent from the moon succeeds with modified date
|
||||
Given there are messages in mailbox "Folders/mbox" for "user"
|
||||
| from | to | subject | time |
|
||||
| john.doe@mail.com | user@pm.me | foo | 1969-07-20T00:00:00 |
|
||||
And there is IMAP client logged in as "user"
|
||||
And there is IMAP client selected in "Folders/mbox"
|
||||
When IMAP client sends command "FETCH 1:* rfc822"
|
||||
Then IMAP response is "OK"
|
||||
And IMAP response contains "Date: Fri, 13 Aug 1982"
|
||||
And IMAP response contains "X-Original-Date: Sun, 20 Jul 1969"
|
||||
# We had bug to incorectly set empty date, so let's make sure
|
||||
# there is no reference anywhere in the response.
|
||||
And IMAP response does not contain "Date: Thu, 01 Jan 1970"
|
||||
|
||||
@ -32,6 +32,8 @@ func IMAPChecksFeatureContext(s *godog.Suite) {
|
||||
s.Step(`^IMAP response to "([^"]*)" contains "([^"]*)"$`, imapResponseNamedContains)
|
||||
s.Step(`^IMAP response has (\d+) message(?:s)?$`, imapResponseHasNumberOfMessages)
|
||||
s.Step(`^IMAP response to "([^"]*)" has (\d+) message(?:s)?$`, imapResponseNamedHasNumberOfMessages)
|
||||
s.Step(`^IMAP response does not contain "([^"]*)"$`, imapResponseDoesNotContain)
|
||||
s.Step(`^IMAP response to "([^"]*)" does not contain "([^"]*)"$`, imapResponseNamedDoesNotContain)
|
||||
s.Step(`^IMAP client receives update marking message seq "([^"]*)" as read within (\d+) seconds$`, imapClientReceivesUpdateMarkingMessageSeqAsReadWithin)
|
||||
s.Step(`^IMAP client "([^"]*)" receives update marking message seq "([^"]*)" as read within (\d+) seconds$`, imapClientNamedReceivesUpdateMarkingMessageSeqAsReadWithin)
|
||||
s.Step(`^IMAP client receives update marking message seq "([^"]*)" as unread within (\d+) seconds$`, imapClientReceivesUpdateMarkingMessageSeqAsUnreadWithin)
|
||||
@ -73,6 +75,16 @@ func imapResponseNamedHasNumberOfMessages(clientID string, expectedCount int) er
|
||||
return ctx.GetTestingError()
|
||||
}
|
||||
|
||||
func imapResponseDoesNotContain(notExpectedResponse string) error {
|
||||
return imapResponseNamedDoesNotContain("imap", notExpectedResponse)
|
||||
}
|
||||
|
||||
func imapResponseNamedDoesNotContain(clientID, notExpectedResponse string) error {
|
||||
res := ctx.GetIMAPLastResponse(clientID)
|
||||
res.AssertNotSections(notExpectedResponse)
|
||||
return ctx.GetTestingError()
|
||||
}
|
||||
|
||||
func imapClientReceivesUpdateMarkingMessageSeqAsReadWithin(messageSeq string, seconds int) error {
|
||||
return imapClientNamedReceivesUpdateMarkingMessageSeqAsReadWithin("imap", messageSeq, seconds)
|
||||
}
|
||||
|
||||
@ -160,6 +160,16 @@ func (ir *IMAPResponse) AssertSections(wantRegexps ...string) *IMAPResponse {
|
||||
return ir
|
||||
}
|
||||
|
||||
// AssertNotSections is similar to AssertSections but is the opposite.
|
||||
// It means it just tries to find all "regexps" in the response.
|
||||
func (ir *IMAPResponse) AssertNotSections(unwantedRegexps ...string) *IMAPResponse {
|
||||
ir.wait()
|
||||
for _, unwantedRegexp := range unwantedRegexps {
|
||||
a.Error(ir.t, ir.hasSectionRegexp(unwantedRegexp), "regexp %v found\nSections: %v", unwantedRegexp, ir.sections)
|
||||
}
|
||||
return ir
|
||||
}
|
||||
|
||||
// WaitForSections is the same as AssertSections but waits for `timeout` before giving up.
|
||||
func (ir *IMAPResponse) WaitForSections(timeout time.Duration, wantRegexps ...string) {
|
||||
a.Eventually(ir.t, func() bool {
|
||||
|
||||
@ -20,6 +20,7 @@ package tests
|
||||
import (
|
||||
"fmt"
|
||||
"net/mail"
|
||||
"net/textproto"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@ -97,6 +98,7 @@ func thereAreMessagesInMailboxesForAddressOfUser(mailboxNames, bddAddressID, bdd
|
||||
LabelIDs: labelIDs,
|
||||
AddressID: account.AddressID(),
|
||||
}
|
||||
header := make(textproto.MIMEHeader)
|
||||
|
||||
if message.HasLabelID(pmapi.SentLabel) {
|
||||
message.Flags |= pmapi.FlagSent
|
||||
@ -143,12 +145,14 @@ func thereAreMessagesInMailboxesForAddressOfUser(mailboxNames, bddAddressID, bdd
|
||||
return internalError(err, "parsing time")
|
||||
}
|
||||
message.Time = date.Unix()
|
||||
header.Set("Date", date.Format(time.RFC1123Z))
|
||||
case "deleted":
|
||||
hasDeletedFlag = cell.Value == "true"
|
||||
default:
|
||||
return fmt.Errorf("unexpected column name: %s", head[n].Value)
|
||||
}
|
||||
}
|
||||
message.Header = mail.Header(header)
|
||||
lastMessageID, err := ctx.GetPMAPIController().AddUserMessage(account.Username(), message)
|
||||
if err != nil {
|
||||
return internalError(err, "adding message")
|
||||
|
||||
@ -20,3 +20,4 @@ Changelog [format](http://keepachangelog.com/en/1.0.0/)
|
||||
### Fixed
|
||||
* GODT-135 Support parameters in SMTP `FROM MAIL` command, such as `BODY=7BIT`, or empty value `FROM MAIL:<>` used by some clients.
|
||||
* GODT-338 GODT-781 GODT-857 GODT-866 Flaky tests.
|
||||
* GODT-773 Replace old dates with birthday of RFC822 to not crash Apple Mail. Original is available under `X-Original-Date` header.
|
||||
|
||||
Reference in New Issue
Block a user