Skip to content

Commit fee642d

Browse files
dvalteremersion
authored andcommitted
Fix incorrect line folding of RFC2047-encoded strings
Use only whitespace characters as a separator to fold lines according to the section 2.2.3 of RFC5322. It may increase number of cases where hard limit fallback is used, but it should prevent damaging encoded subjects.
1 parent 9c4415e commit fee642d

File tree

2 files changed

+10
-24
lines changed

2 files changed

+10
-24
lines changed

textproto/header.go

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import (
66
"fmt"
77
"io"
88
"net/textproto"
9-
"regexp"
109
"strings"
1110
)
1211

@@ -494,9 +493,6 @@ func ReadHeader(r *bufio.Reader) (Header, error) {
494493
}
495494
}
496495

497-
// Regexp that detects Quoted Printable (QP) characters
498-
var qpReg = regexp.MustCompile("(=[0-9A-Z]{2,2})+")
499-
500496
func foldLine(v string, maxlen int) (line, next string, ok bool) {
501497
ok = true
502498

@@ -512,24 +508,8 @@ func foldLine(v string, maxlen int) (line, next string, ok bool) {
512508
folding = "\r\n"
513509
}
514510
} else {
515-
// Find the last QP character before limit
516-
foldAtQP := qpReg.FindAllStringIndex(v[:foldBefore], -1)
517511
// Find the closest whitespace before maxlen
518-
foldAtEOL := strings.LastIndexAny(v[:foldBefore], " \t\n")
519-
520-
// Fold at the latest whitespace by default
521-
foldAt = foldAtEOL
522-
523-
// if there are QP characters in the string
524-
if len(foldAtQP) > 0 {
525-
// Get the start index of the last QP character
526-
foldAtQPLastIndex := foldAtQP[len(foldAtQP)-1][0]
527-
if foldAtQPLastIndex > foldAt {
528-
// Fold at the latest QP character if there are no whitespaces
529-
// after it and before line length limit
530-
foldAt = foldAtQPLastIndex
531-
}
532-
}
512+
foldAt = strings.LastIndexAny(v[:foldBefore], " \t\n")
533513

534514
if foldAt == 0 {
535515
// The whitespace we found was the previous folding WSP
@@ -551,7 +531,7 @@ func foldLine(v string, maxlen int) (line, next string, ok bool) {
551531
// extra space in the string, so this should be avoided if
552532
// possible.
553533
folding = "\r\n "
554-
ok = len(foldAtQP) > 0
534+
ok = false
555535
}
556536
}
557537

textproto/header_test.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -404,18 +404,24 @@ var formatHeaderFieldTests = []struct {
404404
{
405405
k: "Subject",
406406
v: "=?utf-8?q?=E2=80=9CDeveloper_reads_customer_requested_change.=E2=80=9D=0A?= =?utf-8?q?=0ACaravaggio=0A=0AOil_on...?=",
407-
formatted: "Subject: =?utf-8?q?=E2=80=9CDeveloper_reads_customer_requested_change.\r\n =E2=80=9D=0A?= =?utf-8?q?=0ACaravaggio=0A=0AOil_on...?=\r\n",
407+
formatted: "Subject: =?utf-8?q?=E2=80=9CDeveloper_reads_customer_requested_change.=E2=80=9D=0A?= =?utf-8?q?=0ACaravaggio=0A=0AOil_on...?=\r\n",
408408
},
409+
// Spaces should not appear in RFC2047-encoded string but it should be fine in case they do
409410
{
410411
k: "Subject",
411412
v: "=?utf-8?q?=E2=80=9CShort subject=E2=80=9D=0A?= =?utf-8?q?=0AAuthor=0A=0AOil_on...?=",
412-
formatted: "Subject: =?utf-8?q?=E2=80=9CShort subject=E2=80=9D=0A?= =?utf-8?q?\r\n =0AAuthor=0A=0AOil_on...?=\r\n",
413+
formatted: "Subject: =?utf-8?q?=E2=80=9CShort subject=E2=80=9D=0A?=\r\n =?utf-8?q?=0AAuthor=0A=0AOil_on...?=\r\n",
413414
},
414415
{
415416
k: "Subject",
416417
v: "=?utf-8?q?=E2=80=9CVery long subject very long subject very long subject very long subject=E2=80=9D=0A?= =?utf-8?q?=0ALong second part of subject long second part of subject long second part of subject long subject=0A=0AOil_on...?=",
417418
formatted: "Subject: =?utf-8?q?=E2=80=9CVery long subject very long subject very long\r\n subject very long subject=E2=80=9D=0A?= =?utf-8?q?=0ALong second part of\r\n subject long second part of subject long second part of subject long\r\n subject=0A=0AOil_on...?=\r\n",
418419
},
420+
{
421+
k: "Subject",
422+
v: "InCaseOfVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongStringWeStillShouldComplyToTheHardLimitOf998Symbols",
423+
formatted: "Subject: InCaseOfVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongStringWeStillSho\r\n uldComplyToTheHardLimitOf998Symbols\r\n",
424+
},
419425
{
420426
k: "DKIM-Signature",
421427
v: "v=1;\r\n h=From:To:Reply-To:Subject:Message-ID:References:In-Reply-To:MIME-Version;\r\n d=example.org\r\n",

0 commit comments

Comments
 (0)