Skip to content

Commit

Permalink
fix(GODT-1617): correctly parse headers with space lines.
Browse files Browse the repository at this point in the history
  • Loading branch information
cuthix authored and LBeernaertProton committed Sep 12, 2022
1 parent 1f23fac commit 6411b23
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 4 deletions.
2 changes: 1 addition & 1 deletion rfc822/header.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ func ParseHeader(header []byte) *Header {
split := splitLine(line)

switch {
case len(bytes.TrimSpace(line)) == 0:
case len(bytes.Trim(line, "\r\n")) == 0:
lines = append(lines, line)

case quote%2 != 0, rxWhitespace.Match(split[0]), len(split) != 2:
Expand Down
4 changes: 2 additions & 2 deletions rfc822/header_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,10 +180,10 @@ func TestParseHeaderMultilineFilenameWithColonAndNewline(t *testing.T) {
}

func TestParseHeaderMultilineIndent(t *testing.T) {
const header = "Subject: a very\r\n\tlong: line with a colon and indent\r\nFrom: sender\r\n"
const header = "Subject: a very\r\n\tlong: line with a colon and indent\r\n \r\nand space line\r\nFrom: sender\r\n"

assert.Equal(t, [][]byte{
[]byte("Subject: a very\r\n\tlong: line with a colon and indent\r\n"),
[]byte("Subject: a very\r\n\tlong: line with a colon and indent\r\n \r\nand space line\r\n"),
[]byte("From: sender\r\n"),
}, ParseHeader([]byte(header)).lines)
}
Expand Down
2 changes: 1 addition & 1 deletion rfc822/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ func Split(b []byte) ([]byte, []byte, error) {

header = append(header, b...)

if len(bytes.TrimSpace(b)) == 0 {
if len(bytes.Trim(b, "\r\n")) == 0 {
break
}
}
Expand Down
43 changes: 43 additions & 0 deletions rfc822/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,3 +159,46 @@ From me`, string(section.Part(2, 1).Literal()))
This part is also embedded`, string(section.Part(2, 2).Literal()))
}

func TestParseSpaceLineHeaderMessage(t *testing.T) {
const literal = `Content-Type: text/plain
Date: Thu, 03 Sep 2020 16:47:43 +0000 (UTC)
Subject: Sometimes
header fields can be long and contain space line :shrug:
From: Dad <[email protected]>
To: Ships <[email protected]>
Why does the Norway navy have bar codes on the side of their ships?
So when they com back to port they can
Scandinavian
`

section, err := Parse([]byte(literal))
require.NoError(t, err)

assert.Equal(t, literal, string(section.Literal()))

assert.Equal(t, `Content-Type: text/plain
Date: Thu, 03 Sep 2020 16:47:43 +0000 (UTC)
Subject: Sometimes
header fields can be long and contain space line :shrug:
From: Dad <[email protected]>
To: Ships <[email protected]>
`,
string(section.Header()),
)

assert.Equal(t, `Why does the Norway navy have bar codes on the side of their ships?
So when they com back to port they can
Scandinavian
`,
string(section.Body()),
)
}
48 changes: 48 additions & 0 deletions tests/append_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package tests

import (
"bytes"
"os"
"testing"
"time"

Expand Down Expand Up @@ -126,3 +128,49 @@ func TestAppendWhileSelected(t *testing.T) {
require.Equal(t, uint32(1), status.Messages, "Expected message count does not match")
})
}

func TestAppendHeaderWithSpaceLine(t *testing.T) {
r := require.New(t)

const (
mailboxName = "saved-messages"
messagePath = "testdata/space_line_header.eml"
)

// Get full header from file
fullMessage, err := os.ReadFile(messagePath)
r.NoError(err)

endOfHeader := []byte{13, 10, 13, 10}
endOfHeaderKey := bytes.Index(fullMessage, endOfHeader)

r.NotEqual(-1, endOfHeaderKey)
wantHeader := string(fullMessage[0 : endOfHeaderKey+len(endOfHeader)])

runOneToOneTestClientWithAuth(t, defaultServerOptions(t), func(client *client.Client, _ *testSession) {
r.NoError(client.Create(mailboxName))
// Mailbox should have read-write modifier
mailboxStatus, err := client.Select(mailboxName, false)
r.NoError(err)
r.False(mailboxStatus.ReadOnly)

// Add new message
require.NoError(t, doAppendWithClientFromFile(t, client, mailboxName, messagePath, time.Now(), goimap.SeenFlag))
// EXISTS response is assigned to Messages member
require.Equal(t, uint32(1), client.Mailbox().Messages)
// Check if added
status, err := client.Status(mailboxName, []goimap.StatusItem{goimap.StatusMessages})
require.NoError(t, err)
require.Equal(t, uint32(1), status.Messages, "Expected message count does not match")
// Check has full header
newFetchCommand(t, client).
withItems(goimap.FetchRFC822Header).fetch("1").
forSeqNum(1, func(v *validatorBuilder) {
v.ignoreFlags()
v.wantSectionString(goimap.FetchRFC822Header, func(t testing.TB, literal string) {
haveHeader := skipGLUONHeader(literal)
r.Equal(wantHeader, haveHeader)
})
}).check()
})
}
14 changes: 14 additions & 0 deletions tests/testdata/space_line_header.eml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
Content-Type: text/plain
Date: Thu, 03 Sep 2020 16:47:43 +0000 (UTC)
Subject: Sometimes

header fields can be long and contain space line :shrug:
From: Dad <[email protected]>
To: Ships <[email protected]>

Why does the Norway navy have bar codes on the side of their ships?

So when they com back to port they can

Scandinavian

0 comments on commit 6411b23

Please sign in to comment.