mirror of
https://github.com/ProtonMail/proton-bridge.git
synced 2025-12-16 07:06:45 +00:00
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"
|
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 }
|
type doNotCacheError struct{ e error }
|
||||||
|
|
||||||
func (dnc *doNotCacheError) Error() string { return dnc.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{}
|
tmpBuf := &bytes.Buffer{}
|
||||||
mainHeader := message.GetHeader(m)
|
mainHeader := buildHeader(m)
|
||||||
if err = writeHeader(tmpBuf, mainHeader); err != nil {
|
if err = writeHeader(tmpBuf, mainHeader); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -703,3 +707,23 @@ func (im *imapMailbox) buildMessageInner(m *pmapi.Message, kr *crypto.KeyRing) (
|
|||||||
}
|
}
|
||||||
return structure, msgBody, err
|
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 (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/mail"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
messageUtils "github.com/ProtonMail/proton-bridge/pkg/message"
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/pmapi"
|
"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.ID = ctl.messageIDGenerator.next("")
|
||||||
message.LabelIDs = append(message.LabelIDs, pmapi.AllMailLabel)
|
message.LabelIDs = append(message.LabelIDs, pmapi.AllMailLabel)
|
||||||
|
message.Header = mail.Header(messageUtils.GetHeader(message))
|
||||||
ctl.messagesByUsername[username] = append(ctl.messagesByUsername[username], message)
|
ctl.messagesByUsername[username] = append(ctl.messagesByUsername[username], message)
|
||||||
ctl.resetUsers()
|
ctl.resetUsers()
|
||||||
return message.ID, nil
|
return message.ID, nil
|
||||||
|
|||||||
@ -60,3 +60,17 @@ Feature: IMAP fetch messages
|
|||||||
When IMAP client fetches by UID "1:*"
|
When IMAP client fetches by UID "1:*"
|
||||||
Then IMAP response is "OK"
|
Then IMAP response is "OK"
|
||||||
And IMAP response has 2 message
|
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 to "([^"]*)" contains "([^"]*)"$`, imapResponseNamedContains)
|
||||||
s.Step(`^IMAP response has (\d+) message(?:s)?$`, imapResponseHasNumberOfMessages)
|
s.Step(`^IMAP response has (\d+) message(?:s)?$`, imapResponseHasNumberOfMessages)
|
||||||
s.Step(`^IMAP response to "([^"]*)" has (\d+) message(?:s)?$`, imapResponseNamedHasNumberOfMessages)
|
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$`, 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 read within (\d+) seconds$`, imapClientNamedReceivesUpdateMarkingMessageSeqAsReadWithin)
|
||||||
s.Step(`^IMAP client receives update marking message seq "([^"]*)" as unread within (\d+) seconds$`, imapClientReceivesUpdateMarkingMessageSeqAsUnreadWithin)
|
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()
|
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 {
|
func imapClientReceivesUpdateMarkingMessageSeqAsReadWithin(messageSeq string, seconds int) error {
|
||||||
return imapClientNamedReceivesUpdateMarkingMessageSeqAsReadWithin("imap", messageSeq, seconds)
|
return imapClientNamedReceivesUpdateMarkingMessageSeqAsReadWithin("imap", messageSeq, seconds)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -160,6 +160,16 @@ func (ir *IMAPResponse) AssertSections(wantRegexps ...string) *IMAPResponse {
|
|||||||
return ir
|
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.
|
// WaitForSections is the same as AssertSections but waits for `timeout` before giving up.
|
||||||
func (ir *IMAPResponse) WaitForSections(timeout time.Duration, wantRegexps ...string) {
|
func (ir *IMAPResponse) WaitForSections(timeout time.Duration, wantRegexps ...string) {
|
||||||
a.Eventually(ir.t, func() bool {
|
a.Eventually(ir.t, func() bool {
|
||||||
|
|||||||
@ -20,6 +20,7 @@ package tests
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/mail"
|
"net/mail"
|
||||||
|
"net/textproto"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@ -97,6 +98,7 @@ func thereAreMessagesInMailboxesForAddressOfUser(mailboxNames, bddAddressID, bdd
|
|||||||
LabelIDs: labelIDs,
|
LabelIDs: labelIDs,
|
||||||
AddressID: account.AddressID(),
|
AddressID: account.AddressID(),
|
||||||
}
|
}
|
||||||
|
header := make(textproto.MIMEHeader)
|
||||||
|
|
||||||
if message.HasLabelID(pmapi.SentLabel) {
|
if message.HasLabelID(pmapi.SentLabel) {
|
||||||
message.Flags |= pmapi.FlagSent
|
message.Flags |= pmapi.FlagSent
|
||||||
@ -143,12 +145,14 @@ func thereAreMessagesInMailboxesForAddressOfUser(mailboxNames, bddAddressID, bdd
|
|||||||
return internalError(err, "parsing time")
|
return internalError(err, "parsing time")
|
||||||
}
|
}
|
||||||
message.Time = date.Unix()
|
message.Time = date.Unix()
|
||||||
|
header.Set("Date", date.Format(time.RFC1123Z))
|
||||||
case "deleted":
|
case "deleted":
|
||||||
hasDeletedFlag = cell.Value == "true"
|
hasDeletedFlag = cell.Value == "true"
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unexpected column name: %s", head[n].Value)
|
return fmt.Errorf("unexpected column name: %s", head[n].Value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
message.Header = mail.Header(header)
|
||||||
lastMessageID, err := ctx.GetPMAPIController().AddUserMessage(account.Username(), message)
|
lastMessageID, err := ctx.GetPMAPIController().AddUserMessage(account.Username(), message)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return internalError(err, "adding message")
|
return internalError(err, "adding message")
|
||||||
|
|||||||
@ -20,3 +20,4 @@ Changelog [format](http://keepachangelog.com/en/1.0.0/)
|
|||||||
### Fixed
|
### Fixed
|
||||||
* GODT-135 Support parameters in SMTP `FROM MAIL` command, such as `BODY=7BIT`, or empty value `FROM MAIL:<>` used by some clients.
|
* 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-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