Skip to content

Commit 4223e73

Browse files
authored
Merge pull request #1353 from lol2x/main
fix: encode email subject headers according to RFC 2047
2 parents de083b0 + 773c49d commit 4223e73

File tree

5 files changed

+84
-3
lines changed

5 files changed

+84
-3
lines changed

app/services/email/awsses/awsses.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ func sendMail(ctx context.Context, c *cmd.SendMail) {
110110
},
111111
Subject: &ses.Content{
112112
Charset: aws.String("UTF-8"),
113-
Data: aws.String(message.Subject),
113+
Data: aws.String(email.EncodeSubject(message.Subject)),
114114
},
115115
},
116116
},

app/services/email/mailgun/sendmail.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ func sendMail(ctx context.Context, c *cmd.SendMail) {
5050
form := url.Values{}
5151
form.Add("from", c.From.String())
5252
form.Add("h:Reply-To", c.From.Address)
53-
form.Add("subject", message.Subject)
53+
form.Add("subject", email.EncodeSubject(message.Subject))
5454
form.Add("html", message.Body)
5555
form.Add("o:tag", fmt.Sprintf("template:%s", c.TemplateName))
5656

app/services/email/message.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ package email
33
import (
44
"bytes"
55
"context"
6+
"mime"
67
"strings"
8+
"unicode"
79

810
"github.com/getfider/fider/app/models/dto"
911
"github.com/getfider/fider/app/pkg/tpl"
@@ -15,6 +17,26 @@ type Message struct {
1517
Body string
1618
}
1719

20+
// EncodeSubject encodes the subject header according to RFC 2047 if it contains non-ASCII characters
21+
func EncodeSubject(subject string) string {
22+
// Check if the subject contains non-ASCII characters
23+
hasNonASCII := false
24+
for _, r := range subject {
25+
if r > unicode.MaxASCII {
26+
hasNonASCII = true
27+
break
28+
}
29+
}
30+
31+
// If it's pure ASCII, no encoding is needed
32+
if !hasNonASCII {
33+
return subject
34+
}
35+
36+
// Use Go's built-in MIME header encoding which implements RFC 2047
37+
return mime.QEncoding.Encode("utf-8", subject)
38+
}
39+
1840
// RenderMessage returns the HTML of an email based on template and params
1941
func RenderMessage(ctx context.Context, templateName string, fromAddress string, params dto.Props) *Message {
2042
noreply := false

app/services/email/message_test.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package email_test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/getfider/fider/app/services/email"
7+
. "github.com/getfider/fider/app/pkg/assert"
8+
)
9+
10+
func TestEncodeSubject_ASCIIOnly(t *testing.T) {
11+
RegisterT(t)
12+
13+
subject := "Hello World"
14+
encoded := email.EncodeSubject(subject)
15+
16+
Expect(encoded).Equals("Hello World")
17+
}
18+
19+
func TestEncodeSubject_WithNonASCII(t *testing.T) {
20+
RegisterT(t)
21+
22+
subject := "Test ä ö ü"
23+
encoded := email.EncodeSubject(subject)
24+
25+
// The encoded result should be in RFC 2047 format
26+
Expect(encoded).ContainsSubstring("=?utf-8?q?")
27+
Expect(encoded).ContainsSubstring("?=")
28+
}
29+
30+
func TestEncodeSubject_WithEmoji(t *testing.T) {
31+
RegisterT(t)
32+
33+
subject := "Hello 👋 World 🌍"
34+
encoded := email.EncodeSubject(subject)
35+
36+
// The encoded result should be in RFC 2047 format
37+
Expect(encoded).ContainsSubstring("=?utf-8?q?")
38+
Expect(encoded).ContainsSubstring("?=")
39+
}
40+
41+
func TestEncodeSubject_Empty(t *testing.T) {
42+
RegisterT(t)
43+
44+
subject := ""
45+
encoded := email.EncodeSubject(subject)
46+
47+
Expect(encoded).Equals("")
48+
}
49+
50+
func TestEncodeSubject_WithUmlautsAndSpecialChars(t *testing.T) {
51+
RegisterT(t)
52+
53+
subject := "Öffentliche Ankündigung - Größere Änderungen"
54+
encoded := email.EncodeSubject(subject)
55+
56+
// The encoded result should be in RFC 2047 format
57+
Expect(encoded).ContainsSubstring("=?utf-8?q?")
58+
Expect(encoded).ContainsSubstring("?=")
59+
}

app/services/email/smtp/smtp.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ func sendMail(ctx context.Context, c *cmd.SendMail) {
9090
b.Set("From", c.From.String())
9191
b.Set("Reply-To", c.From.Address)
9292
b.Set("To", to.String())
93-
b.Set("Subject", message.Subject)
93+
b.Set("Subject", email.EncodeSubject(message.Subject))
9494
b.Set("MIME-version", "1.0")
9595
b.Set("Content-Type", "text/html; charset=\"UTF-8\"")
9696
b.Set("Date", time.Now().Format(time.RFC1123Z))

0 commit comments

Comments
 (0)