Skip to content

Commit

Permalink
fix(GODT-1729): Fix header parsing of fields without space
Browse files Browse the repository at this point in the history
Fix the header parsing of fields that do not have a space after the
colon.
  • Loading branch information
LBeernaertProton committed Jul 14, 2022
1 parent 9774748 commit 50db483
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 3 deletions.
14 changes: 11 additions & 3 deletions rfc822/header.go
Original file line number Diff line number Diff line change
Expand Up @@ -270,15 +270,23 @@ func mergeMultiline(line []byte) string {
var res [][]byte

for line := range forLines(bufio.NewReader(bytes.NewReader(line))) {
res = append(res, bytes.TrimSpace(line))
trimmed := bytes.TrimSpace(line)
if trimmed != nil {
res = append(res, trimmed)
}
}

return string(bytes.Join(res, []byte(" ")))
}

// TODO: What if there isn't a space after the colon?
func splitLine(line []byte) [][]byte {
return bytes.SplitN(line, []byte(`: `), 2)
result := bytes.SplitN(line, []byte(`:`), 2)

if len(result) > 1 && len(result[1]) > 0 && result[1][0] == ' ' {
result[1] = result[1][1:]
}

return result
}

// TODO: Don't assume line ending is \r\n. Bad.
Expand Down
6 changes: 6 additions & 0 deletions rfc822/header_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ func TestHeader_Raw(t *testing.T) {
}

func TestHeader_Has(t *testing.T) {
const literal = "To: somebody\r\nFrom: somebody else\r\nSubject: this is\r\n\ta multiline field\r\nFrom: duplicate entry\r\nReferences:\r\n\t <[email protected]>\r\n\r\n"

header := ParseHeader([]byte(literal))

assert.Equal(t, true, header.Has("To"))
Expand All @@ -25,9 +27,12 @@ func TestHeader_Has(t *testing.T) {
assert.Equal(t, true, header.Has("Subject"))
assert.Equal(t, true, header.Has("subject"))
assert.Equal(t, false, header.Has("subjectt"))
assert.Equal(t, true, header.Has("References"))
}

func TestHeader_Get(t *testing.T) {
const literal = "To: somebody\r\nFrom: somebody else\r\nSubject: this is\r\n\ta multiline field\r\nFrom: duplicate entry\r\nReferences:\r\n\t <[email protected]>\r\n\r\n"

header := ParseHeader([]byte(literal))

assert.Equal(t, "somebody", header.Get("To"))
Expand All @@ -36,6 +41,7 @@ func TestHeader_Get(t *testing.T) {
assert.Equal(t, "somebody else", header.Get("from"))
assert.Equal(t, "this is a multiline field", header.Get("Subject"))
assert.Equal(t, "this is a multiline field", header.Get("subject"))
assert.Equal(t, "<[email protected]>", header.Get("References"))
}

func TestHeader_GetRaw(t *testing.T) {
Expand Down
70 changes: 70 additions & 0 deletions tests/fetch_body_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -706,6 +706,76 @@ func TestFetchBodyPeekInvalidSectionNumber(t *testing.T) {
})
}

func TestFetchBody_Dovecot_InvalidMessageHeader(t *testing.T) {
// This tests fails when requesting when fetch BODY.PEEK[HEADER.FIELDS (In-Reply-To In-Reply-To Cc)].
// Instead of only returning In-Reply-To and Cc, it was also returning the References header.
const message = `From [email protected] Mon Apr 7 01:27:38 2003
Received: with ECARTIS (v1.0.0; list dovecot); Mon, 07 Apr 2003 01:27:38 +0300 (EEST)
Return-Path: <[email protected]>
X-Original-To: [email protected]
Delivered-To: [email protected]
Received: from oma.irssi.org (ip213-185-36-189.laajakaista.mtv3.fi [213.185.36.189])
by danu.procontrol.fi (Postfix) with ESMTP id 2A7282387F
for <[email protected]>; Mon, 7 Apr 2003 01:27:38 +0300 (EEST)
Received: by oma.irssi.org (Postfix, from userid 1000)
id 3D1565E01F95; Mon, 7 Apr 2003 01:27:36 +0300 (EEST)
Subject: [dovecot] Re: message order reversed on copying
From: Timo Sirainen <[email protected]>
To: Charlie Brady <[email protected]>
Cc: [email protected]
In-Reply-To: <[email protected]>
References:
<[email protected]>
Content-Type: text/plain
Content-Transfer-Encoding: 7bit
Organization:
Message-Id: <1049668055.22903.405.camel@hurina>
Mime-Version: 1.0
X-Mailer: Ximian Evolution 1.2.3
Date: 07 Apr 2003 01:27:36 +0300
X-archive-position: 516
X-ecartis-version: Ecartis v1.0.0
Sender: [email protected]
Errors-to: [email protected]
X-original-sender: [email protected]
Precedence: bulk
X-list: dovecot
X-UID: 516
Status: O
On Mon, 2003-04-07 at 01:15, Charlie Brady wrote:
> > > + nfiles = scandir (tmp, &names, NULL, maildir_namesort);
> > scandir() isn't portable though.
> No? Which OS doesn't have it?
It's not in any standard -> it's not portable. Maybe it's portable
enough, but I try to avoid those whenever possible.
> > Which changes UIDVALIDITY and forces clients to discard their cache.
>
> Yes, I could have mentioned that. Still, it's the only way I know to
> restore the sorting order once it's jumbled.
How about making your client sort the messages by received-date? :)
`

runOneToOneTestClientWithAuth(t, defaultServerOptions(t), func(client *client.Client, _ *testSession) {
require.NoError(t, doAppendWithClient(client, "INBOX", message, time.Now()))
_, err := client.Select("INBOX", false)
require.NoError(t, err)
newFetchCommand(t, client).withItems("BODY.PEEK[HEADER.FIELDS (In-Reply-To In-Reply-To Cc)]").
fetch("1").forSeqNum(1, func(builder *validatorBuilder) {
builder.ignoreFlags()
builder.wantSection(`BODY[HEADER.FIELDS (In-Reply-To In-Reply-To Cc)]`,
`Cc: [email protected]
In-Reply-To: <[email protected]>
`)
}).check()
})
}

// --- helpers -------------------------------------------------------------------------------------------------------
// NOTE: these helpers create messages with the seen flag to avoid interfering with the go imap client library. Due to
// a timing issue, it is possible that a fetch update for the flag state can be received as a separate message.
Expand Down

0 comments on commit 50db483

Please sign in to comment.