1
0
mirror of https://github.com/jhillyerd/inbucket.git synced 2025-12-17 17:47:03 +00:00

webui, rest: Render UTF-8 addresses correctly, fixes #117

This commit is contained in:
James Hillyerd
2018-10-22 18:29:03 -07:00
parent fcb4bc20e0
commit 30e3892cb0
10 changed files with 88 additions and 18 deletions

View File

@@ -1,6 +1,8 @@
Date: %DATE%
To: %TO_ADDRESS%
From: %FROM_ADDRESS%
To: %TO_ADDRESS%,
=?utf-8?B?VGVzdCBvZiDIh8myyqLIr8ihyarJtMqb?= <recipient@inbucket.org>
From: =?utf-8?q?X-=C3=A4=C3=A9=C3=9F_Y-=C3=A4=C3=A9=C3=9F?=
<fromuser@inbucket.org>
Subject: =?utf-8?B?VGVzdCBvZiDIh8myyqLIr8ihyarJtMqb?=
Thread-Topic: =?utf-8?B?VGVzdCBvZiDIh8myyqLIr8ihyarJtMqb?=
Thread-Index: Ac6+4nH7mOymA+1JRQyk2LQPe1bEcw==

View File

@@ -33,7 +33,7 @@ func MailboxListV1(w http.ResponseWriter, req *http.Request, ctx *web.Context) (
jmessages[i] = &model.JSONMessageHeaderV1{
Mailbox: name,
ID: msg.ID,
From: msg.From.String(),
From: stringutil.StringAddress(msg.From),
To: stringutil.StringAddressList(msg.To),
Subject: msg.Subject,
Date: msg.Date,
@@ -79,7 +79,7 @@ func MailboxShowV1(w http.ResponseWriter, req *http.Request, ctx *web.Context) (
&model.JSONMessageV1{
Mailbox: name,
ID: msg.ID,
From: msg.From.String(),
From: stringutil.StringAddress(msg.From),
To: stringutil.StringAddressList(msg.To),
Subject: msg.Subject,
Date: msg.Date,

View File

@@ -8,11 +8,13 @@ import (
"strings"
"time"
"github.com/jhillyerd/inbucket/pkg/stringutil"
"github.com/rs/zerolog/log"
)
// TemplateFuncs declares functions made available to all templates (including partials)
var TemplateFuncs = template.FuncMap{
"address": stringutil.StringAddress,
"friendlyTime": FriendlyTime,
"reverse": Reverse,
"stringsJoin": strings.Join,

View File

@@ -19,13 +19,28 @@ func HashMailboxName(mailbox string) string {
return fmt.Sprintf("%x", h.Sum(nil))
}
// StringAddressList converts a list of addresses to a list of strings
// StringAddress converts an Address to a UTF-8 string.
func StringAddress(a *mail.Address) string {
b := &strings.Builder{}
if a != nil {
if a.Name != "" {
b.WriteString(a.Name)
b.WriteRune(' ')
}
if a.Address != "" {
b.WriteRune('<')
b.WriteString(a.Address)
b.WriteRune('>')
}
}
return b.String()
}
// StringAddressList converts a list of addresses to a list of UTF-8 strings.
func StringAddressList(addrs []*mail.Address) []string {
s := make([]string, len(addrs))
for i, a := range addrs {
if a != nil {
s[i] = a.String()
}
s[i] = StringAddress(a)
}
return s
}

View File

@@ -17,10 +17,14 @@ func TestHashMailboxName(t *testing.T) {
func TestStringAddressList(t *testing.T) {
input := []*mail.Address{
{Name: "Fred B. Fish", Address: "fred@fish.org"},
{Name: "Fred ß. Fish", Address: "fred@fish.org"},
{Name: "User", Address: "user@domain.org"},
{Address: "a@b.com"},
}
want := []string{`"Fred B. Fish" <fred@fish.org>`, `"User" <user@domain.org>`}
want := []string{
`Fred ß. Fish <fred@fish.org>`,
`User <user@domain.org>`,
`<a@b.com>`}
output := stringutil.StringAddressList(input)
if len(output) != len(want) {
t.Fatalf("Got %v strings, want: %v", len(output), len(want))

View File

@@ -44,6 +44,7 @@ func TestSuite(t *testing.T) {
}{
{"basic", testBasic},
{"fullname", testFullname},
{"encodedHeader", testEncodedHeader},
}
for _, tc := range testCases {
t.Run(tc.name, tc.test)
@@ -59,13 +60,13 @@ func testBasic(t *testing.T) {
to := []string{"recipient@inbucket.org"}
input := readTestData("basic.txt")
// Send mail
// Send mail.
err = smtpclient.SendMail(smtpHost, nil, from, to, input)
if err != nil {
t.Fatal(err)
}
// Confirm receipt
// Confirm receipt.
msg, err := client.GetMessage("recipient", "latest")
if err != nil {
t.Fatal(err)
@@ -88,13 +89,13 @@ func testFullname(t *testing.T) {
to := []string{"recipient@inbucket.org"}
input := readTestData("fullname.txt")
// Send mail
// Send mail.
err = smtpclient.SendMail(smtpHost, nil, from, to, input)
if err != nil {
t.Fatal(err)
}
// Confirm receipt
// Confirm receipt.
msg, err := client.GetMessage("recipient", "latest")
if err != nil {
t.Fatal(err)
@@ -108,6 +109,35 @@ func testFullname(t *testing.T) {
goldiff.File(t, got, "testdata", "fullname.golden")
}
func testEncodedHeader(t *testing.T) {
client, err := client.New(restBaseURL)
if err != nil {
t.Fatal(err)
}
from := "fromuser@inbucket.org"
to := []string{"recipient@inbucket.org"}
input := readTestData("encodedheader.txt")
// Send mail.
err = smtpclient.SendMail(smtpHost, nil, from, to, input)
if err != nil {
t.Fatal(err)
}
// Confirm receipt.
msg, err := client.GetMessage("recipient", "latest")
if err != nil {
t.Fatal(err)
}
if msg == nil {
t.Errorf("Got nil message, wanted non-nil message.")
}
// Compare to golden.
got := formatMessage(msg)
goldiff.File(t, got, "testdata", "encodedheader.golden")
}
func formatMessage(m *client.Message) []byte {
b := &bytes.Buffer{}
fmt.Fprintf(b, "Mailbox: %v\n", m.Mailbox)

12
pkg/test/testdata/encodedheader.golden vendored Normal file
View File

@@ -0,0 +1,12 @@
Mailbox: recipient
From: X-äéß Y-äéß <fromuser@inbucket.org>
To: [Test of ȇɲʢȯȡɪɴʛ <recipient@inbucket.org>]
Subject: Test of ȇɲʢȯȡɪɴʛ
Size: 351
BODY TEXT:
Basic message.
BODY HTML:

5
pkg/test/testdata/encodedheader.txt vendored Normal file
View File

@@ -0,0 +1,5 @@
From: =?utf-8?q?X-=C3=A4=C3=A9=C3=9F_Y-=C3=A4=C3=A9=C3=9F?= <fromuser@inbucket.org>
To: =?utf-8?B?VGVzdCBvZiDIh8myyqLIr8ihyarJtMqb?= <recipient@inbucket.org>
Subject: =?utf-8?b?VGVzdCBvZiDIh8myyqLIr8ihyarJtMqb?=
Basic message.

View File

@@ -1,6 +1,6 @@
Mailbox: recipient
From: "From User" <fromuser@inbucket.org>
To: ["Rec I. Pient" <recipient@inbucket.org>]
From: From User <fromuser@inbucket.org>
To: [Rec I. Pient <recipient@inbucket.org>]
Subject: basic subject
Size: 246

View File

@@ -51,12 +51,12 @@
<div class="panel-body">
<dl class="dl-horizontal">
<dt>From:</dt>
<dd>{{.message.From}}</dd>
<dd>{{.message.From | address}}</dd>
<dt>To:</dt>
<dd>
{{range $i, $addr := .message.To}}
{{- if $i}},{{end}}
{{$addr -}}
{{$addr | address -}}
{{end}}
</dd>
<dt>Date:</dt>