mirror of
https://github.com/jhillyerd/inbucket.git
synced 2025-12-18 18:17:03 +00:00
webui, rest: Render UTF-8 addresses correctly, fixes #117
This commit is contained in:
@@ -1,6 +1,8 @@
|
|||||||
Date: %DATE%
|
Date: %DATE%
|
||||||
To: %TO_ADDRESS%
|
To: %TO_ADDRESS%,
|
||||||
From: %FROM_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?=
|
Subject: =?utf-8?B?VGVzdCBvZiDIh8myyqLIr8ihyarJtMqb?=
|
||||||
Thread-Topic: =?utf-8?B?VGVzdCBvZiDIh8myyqLIr8ihyarJtMqb?=
|
Thread-Topic: =?utf-8?B?VGVzdCBvZiDIh8myyqLIr8ihyarJtMqb?=
|
||||||
Thread-Index: Ac6+4nH7mOymA+1JRQyk2LQPe1bEcw==
|
Thread-Index: Ac6+4nH7mOymA+1JRQyk2LQPe1bEcw==
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ func MailboxListV1(w http.ResponseWriter, req *http.Request, ctx *web.Context) (
|
|||||||
jmessages[i] = &model.JSONMessageHeaderV1{
|
jmessages[i] = &model.JSONMessageHeaderV1{
|
||||||
Mailbox: name,
|
Mailbox: name,
|
||||||
ID: msg.ID,
|
ID: msg.ID,
|
||||||
From: msg.From.String(),
|
From: stringutil.StringAddress(msg.From),
|
||||||
To: stringutil.StringAddressList(msg.To),
|
To: stringutil.StringAddressList(msg.To),
|
||||||
Subject: msg.Subject,
|
Subject: msg.Subject,
|
||||||
Date: msg.Date,
|
Date: msg.Date,
|
||||||
@@ -79,7 +79,7 @@ func MailboxShowV1(w http.ResponseWriter, req *http.Request, ctx *web.Context) (
|
|||||||
&model.JSONMessageV1{
|
&model.JSONMessageV1{
|
||||||
Mailbox: name,
|
Mailbox: name,
|
||||||
ID: msg.ID,
|
ID: msg.ID,
|
||||||
From: msg.From.String(),
|
From: stringutil.StringAddress(msg.From),
|
||||||
To: stringutil.StringAddressList(msg.To),
|
To: stringutil.StringAddressList(msg.To),
|
||||||
Subject: msg.Subject,
|
Subject: msg.Subject,
|
||||||
Date: msg.Date,
|
Date: msg.Date,
|
||||||
|
|||||||
@@ -8,11 +8,13 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/jhillyerd/inbucket/pkg/stringutil"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TemplateFuncs declares functions made available to all templates (including partials)
|
// TemplateFuncs declares functions made available to all templates (including partials)
|
||||||
var TemplateFuncs = template.FuncMap{
|
var TemplateFuncs = template.FuncMap{
|
||||||
|
"address": stringutil.StringAddress,
|
||||||
"friendlyTime": FriendlyTime,
|
"friendlyTime": FriendlyTime,
|
||||||
"reverse": Reverse,
|
"reverse": Reverse,
|
||||||
"stringsJoin": strings.Join,
|
"stringsJoin": strings.Join,
|
||||||
|
|||||||
@@ -19,13 +19,28 @@ func HashMailboxName(mailbox string) string {
|
|||||||
return fmt.Sprintf("%x", h.Sum(nil))
|
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 {
|
func StringAddressList(addrs []*mail.Address) []string {
|
||||||
s := make([]string, len(addrs))
|
s := make([]string, len(addrs))
|
||||||
for i, a := range addrs {
|
for i, a := range addrs {
|
||||||
if a != nil {
|
s[i] = StringAddress(a)
|
||||||
s[i] = a.String()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,10 +17,14 @@ func TestHashMailboxName(t *testing.T) {
|
|||||||
|
|
||||||
func TestStringAddressList(t *testing.T) {
|
func TestStringAddressList(t *testing.T) {
|
||||||
input := []*mail.Address{
|
input := []*mail.Address{
|
||||||
{Name: "Fred B. Fish", Address: "fred@fish.org"},
|
{Name: "Fred ß. Fish", Address: "fred@fish.org"},
|
||||||
{Name: "User", Address: "user@domain.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)
|
output := stringutil.StringAddressList(input)
|
||||||
if len(output) != len(want) {
|
if len(output) != len(want) {
|
||||||
t.Fatalf("Got %v strings, want: %v", len(output), len(want))
|
t.Fatalf("Got %v strings, want: %v", len(output), len(want))
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ func TestSuite(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{"basic", testBasic},
|
{"basic", testBasic},
|
||||||
{"fullname", testFullname},
|
{"fullname", testFullname},
|
||||||
|
{"encodedHeader", testEncodedHeader},
|
||||||
}
|
}
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
t.Run(tc.name, tc.test)
|
t.Run(tc.name, tc.test)
|
||||||
@@ -59,13 +60,13 @@ func testBasic(t *testing.T) {
|
|||||||
to := []string{"recipient@inbucket.org"}
|
to := []string{"recipient@inbucket.org"}
|
||||||
input := readTestData("basic.txt")
|
input := readTestData("basic.txt")
|
||||||
|
|
||||||
// Send mail
|
// Send mail.
|
||||||
err = smtpclient.SendMail(smtpHost, nil, from, to, input)
|
err = smtpclient.SendMail(smtpHost, nil, from, to, input)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Confirm receipt
|
// Confirm receipt.
|
||||||
msg, err := client.GetMessage("recipient", "latest")
|
msg, err := client.GetMessage("recipient", "latest")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -88,13 +89,13 @@ func testFullname(t *testing.T) {
|
|||||||
to := []string{"recipient@inbucket.org"}
|
to := []string{"recipient@inbucket.org"}
|
||||||
input := readTestData("fullname.txt")
|
input := readTestData("fullname.txt")
|
||||||
|
|
||||||
// Send mail
|
// Send mail.
|
||||||
err = smtpclient.SendMail(smtpHost, nil, from, to, input)
|
err = smtpclient.SendMail(smtpHost, nil, from, to, input)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Confirm receipt
|
// Confirm receipt.
|
||||||
msg, err := client.GetMessage("recipient", "latest")
|
msg, err := client.GetMessage("recipient", "latest")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -108,6 +109,35 @@ func testFullname(t *testing.T) {
|
|||||||
goldiff.File(t, got, "testdata", "fullname.golden")
|
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 {
|
func formatMessage(m *client.Message) []byte {
|
||||||
b := &bytes.Buffer{}
|
b := &bytes.Buffer{}
|
||||||
fmt.Fprintf(b, "Mailbox: %v\n", m.Mailbox)
|
fmt.Fprintf(b, "Mailbox: %v\n", m.Mailbox)
|
||||||
|
|||||||
12
pkg/test/testdata/encodedheader.golden
vendored
Normal file
12
pkg/test/testdata/encodedheader.golden
vendored
Normal 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
5
pkg/test/testdata/encodedheader.txt
vendored
Normal 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.
|
||||||
4
pkg/test/testdata/fullname.golden
vendored
4
pkg/test/testdata/fullname.golden
vendored
@@ -1,6 +1,6 @@
|
|||||||
Mailbox: recipient
|
Mailbox: recipient
|
||||||
From: "From User" <fromuser@inbucket.org>
|
From: From User <fromuser@inbucket.org>
|
||||||
To: ["Rec I. Pient" <recipient@inbucket.org>]
|
To: [Rec I. Pient <recipient@inbucket.org>]
|
||||||
Subject: basic subject
|
Subject: basic subject
|
||||||
Size: 246
|
Size: 246
|
||||||
|
|
||||||
|
|||||||
@@ -51,12 +51,12 @@
|
|||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<dl class="dl-horizontal">
|
<dl class="dl-horizontal">
|
||||||
<dt>From:</dt>
|
<dt>From:</dt>
|
||||||
<dd>{{.message.From}}</dd>
|
<dd>{{.message.From | address}}</dd>
|
||||||
<dt>To:</dt>
|
<dt>To:</dt>
|
||||||
<dd>
|
<dd>
|
||||||
{{range $i, $addr := .message.To}}
|
{{range $i, $addr := .message.To}}
|
||||||
{{- if $i}},{{end}}
|
{{- if $i}},{{end}}
|
||||||
{{$addr -}}
|
{{$addr | address -}}
|
||||||
{{end}}
|
{{end}}
|
||||||
</dd>
|
</dd>
|
||||||
<dt>Date:</dt>
|
<dt>Date:</dt>
|
||||||
|
|||||||
Reference in New Issue
Block a user