Skip to content

Commit 2533a67

Browse files
authored
Merge pull request #441 from wneessen/bug/440_double-quoted-printable-encoding-in-non-ascii-reply-to-addresses
BREAKING CHANGE: Refactor Reply-To header handling.
2 parents b909433 + 3934f40 commit 2533a67

File tree

5 files changed

+31
-13
lines changed

5 files changed

+31
-13
lines changed

header.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,6 @@ const (
7676
// HeaderReferences is the "References" header field.
7777
HeaderReferences Header = "References"
7878

79-
// HeaderReplyTo is the "Reply-To" header field.
80-
HeaderReplyTo Header = "Reply-To"
81-
8279
// HeaderSubject is the "Subject" header field.
8380
HeaderSubject Header = "Subject"
8481

@@ -115,6 +112,9 @@ const (
115112
// HeaderFrom is the "From" header field.
116113
HeaderFrom AddrHeader = "From"
117114

115+
// HeaderReplyTo is the "Reply-To" header field.
116+
HeaderReplyTo AddrHeader = "Reply-To"
117+
118118
// HeaderTo is the "Receipient" header field.
119119
HeaderTo AddrHeader = "To"
120120
)

header_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ var (
3636
{"Header: Precedence", HeaderPrecedence, "Precedence"},
3737
{"Header: Priority", HeaderPriority, "Priority"},
3838
{"Header: References", HeaderReferences, "References"},
39-
{"Header: Reply-To", HeaderReplyTo, "Reply-To"},
4039
{"Header: Subject", HeaderSubject, "Subject"},
4140
{"Header: User-Agent", HeaderUserAgent, "User-Agent"},
4241
{"Header: X-Auto-Response-Suppress", HeaderXAutoResponseSuppress, "X-Auto-Response-Suppress"},
@@ -53,6 +52,7 @@ var (
5352
{"To", HeaderTo, "To"},
5453
{"Cc", HeaderCc, "Cc"},
5554
{"Bcc", HeaderBcc, "Bcc"},
55+
{"Reply-To", HeaderReplyTo, "Reply-To"},
5656
}
5757
)
5858

msg.go

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -988,12 +988,7 @@ func (m *Msg) BccFromString(rcpts string) error {
988988
// References:
989989
// - https://datatracker.ietf.org/doc/html/rfc5322#section-3.6.2
990990
func (m *Msg) ReplyTo(addr string) error {
991-
replyTo, err := mail.ParseAddress(addr)
992-
if err != nil {
993-
return fmt.Errorf("failed to parse reply-to address: %w", err)
994-
}
995-
m.SetGenHeader(HeaderReplyTo, replyTo.String())
996-
return nil
991+
return m.SetAddrHeader(HeaderReplyTo, addr)
997992
}
998993

999994
// ReplyToFormat sets the "Reply-To" address for the Msg using the provided name and email address, specifying

msg_test.go

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1530,7 +1530,7 @@ func TestMsg_ReplyTo(t *testing.T) {
15301530
if err := message.ReplyTo("toni.tester@example.com"); err != nil {
15311531
t.Fatalf("failed to set ReplyTo: %s", err)
15321532
}
1533-
checkGenHeader(t, message, HeaderReplyTo, "ReplyTo", 0, 1, "<toni.tester@example.com>")
1533+
checkAddrHeader(t, message, HeaderReplyTo, "ReplyTo", 0, 1, "toni.tester@example.com", "")
15341534
})
15351535
t.Run("ReplyTo with invalid address", func(t *testing.T) {
15361536
message := NewMsg()
@@ -1578,7 +1578,7 @@ func TestMsg_ReplyToFormat(t *testing.T) {
15781578
if err := message.ReplyToFormat("Tina Tester", "tina.tester@example.com"); err != nil {
15791579
t.Fatalf("failed to set ReplyTo: %s", err)
15801580
}
1581-
checkGenHeader(t, message, HeaderReplyTo, "ReplyToFormat", 0, 1, `"Tina Tester" <tina.tester@example.com>`)
1581+
checkAddrHeader(t, message, HeaderReplyTo, "ReplyToFormat", 0, 1, "tina.tester@example.com", "Tina Tester")
15821582
})
15831583
t.Run("ReplyToFormat with invalid address", func(t *testing.T) {
15841584
message := NewMsg()
@@ -1589,6 +1589,29 @@ func TestMsg_ReplyToFormat(t *testing.T) {
15891589
t.Errorf("ReplyToFormat should fail with invalid address")
15901590
}
15911591
})
1592+
// https://github.com/wneessen/go-mail/issues/440
1593+
t.Run("ReplyToFormat with special characters must not double encode", func(t *testing.T) {
1594+
message := NewMsg()
1595+
if message == nil {
1596+
t.Fatal("message is nil")
1597+
}
1598+
if err := message.ReplyToFormat("Töni Tester", "töni.tester@example.com"); err != nil {
1599+
t.Errorf("failed to set ReplyTo: %s", err)
1600+
}
1601+
buffer := bytes.NewBuffer(nil)
1602+
if _, err := message.WriteTo(buffer); err != nil {
1603+
t.Errorf("failed to write message to buffer: %s", err)
1604+
}
1605+
header := strings.Split(buffer.String(), "Reply-To: ")
1606+
if len(header) != 2 {
1607+
t.Fatalf("could not split message after Reply-To:")
1608+
}
1609+
want := `=?utf-8?q?T=C3=B6ni_Tester?= <töni.tester@example.com>`
1610+
got := strings.TrimSpace(header[1])
1611+
if got != want {
1612+
t.Errorf("Reply-To header does not match: got %q, want %q", got, want)
1613+
}
1614+
})
15921615
}
15931616

15941617
func TestMsg_Subject(t *testing.T) {

msgwriter.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ func (mw *msgWriter) writeMsg(msg *Msg) {
118118
}
119119

120120
// Set the rest of the address headers
121-
for _, to := range []AddrHeader{HeaderTo, HeaderCc} {
121+
for _, to := range []AddrHeader{HeaderTo, HeaderCc, HeaderReplyTo} {
122122
if addresses, ok := msg.addrHeader[to]; ok {
123123
var val []string
124124
for _, addr := range addresses {

0 commit comments

Comments
 (0)