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

Merge branch 'feature/to-header' into develop

- Messages now store To information
This commit is contained in:
James Hillyerd
2016-09-22 20:12:09 -07:00
14 changed files with 79 additions and 8 deletions

View File

@@ -7,6 +7,9 @@ This project adheres to [Semantic Versioning](http://semver.org/).
[Unreleased] [Unreleased]
------------ ------------
### Added
- Storage of To: header in messages (likely breaks existing datastores)
### Fixed ### Fixed
- We should no longer run out of file handles when dealing with a large number - We should no longer run out of file handles when dealing with a large number
of recipients on a single message. of recipients on a single message.

View File

@@ -103,7 +103,7 @@ main() {
esac esac
# Use jq to pretty-print if installed and we are expecting JSON output # Use jq to pretty-print if installed and we are expecting JSON output
if [ $pretty ] && [ $is_json ] && type -P jq; then if [ $pretty ] && [ $is_json ] && type -P jq >/dev/null; then
curl -s $curl_opts -H "Accept: application/json" --noproxy "$API_HOST" -X "$method" "$url" | jq . curl -s $curl_opts -H "Accept: application/json" --noproxy "$API_HOST" -X "$method" "$url" | jq .
else else
curl -s $curl_opts -H "Accept: application/json" --noproxy "$API_HOST" -X "$method" "$url" curl -s $curl_opts -H "Accept: application/json" --noproxy "$API_HOST" -X "$method" "$url"

View File

@@ -17,6 +17,7 @@ type JSONMessageHeaderV1 struct {
Mailbox string `json:"mailbox"` Mailbox string `json:"mailbox"`
ID string `json:"id"` ID string `json:"id"`
From string `json:"from"` From string `json:"from"`
To []string `json:"to"`
Subject string `json:"subject"` Subject string `json:"subject"`
Date time.Time `json:"date"` Date time.Time `json:"date"`
Size int64 `json:"size"` Size int64 `json:"size"`
@@ -27,6 +28,7 @@ type JSONMessageV1 struct {
Mailbox string `json:"mailbox"` Mailbox string `json:"mailbox"`
ID string `json:"id"` ID string `json:"id"`
From string `json:"from"` From string `json:"from"`
To []string `json:"to"`
Subject string `json:"subject"` Subject string `json:"subject"`
Date time.Time `json:"date"` Date time.Time `json:"date"`
Size int64 `json:"size"` Size int64 `json:"size"`
@@ -65,6 +67,7 @@ func MailboxListV1(w http.ResponseWriter, req *http.Request, ctx *httpd.Context)
Mailbox: name, Mailbox: name,
ID: msg.ID(), ID: msg.ID(),
From: msg.From(), From: msg.From(),
To: msg.To(),
Subject: msg.Subject(), Subject: msg.Subject(),
Date: msg.Date(), Date: msg.Date(),
Size: msg.Size(), Size: msg.Size(),
@@ -109,6 +112,7 @@ func MailboxShowV1(w http.ResponseWriter, req *http.Request, ctx *httpd.Context)
Mailbox: name, Mailbox: name,
ID: msg.ID(), ID: msg.ID(),
From: msg.From(), From: msg.From(),
To: msg.To(),
Subject: msg.Subject(), Subject: msg.Subject(),
Date: msg.Date(), Date: msg.Date(),
Size: msg.Size(), Size: msg.Size(),

View File

@@ -19,6 +19,7 @@ const (
mailboxKey = "mailbox" mailboxKey = "mailbox"
idKey = "id" idKey = "id"
fromKey = "from" fromKey = "from"
toKey = "to"
subjectKey = "subject" subjectKey = "subject"
dateKey = "date" dateKey = "date"
sizeKey = "size" sizeKey = "size"
@@ -94,6 +95,7 @@ func TestRestMailboxList(t *testing.T) {
Mailbox: "good", Mailbox: "good",
ID: "0001", ID: "0001",
From: "from1", From: "from1",
To: []string{"to1"},
Subject: "subject 1", Subject: "subject 1",
Date: time.Date(2012, 2, 1, 10, 11, 12, 253, time.FixedZone("PST", -800)), Date: time.Date(2012, 2, 1, 10, 11, 12, 253, time.FixedZone("PST", -800)),
} }
@@ -101,6 +103,7 @@ func TestRestMailboxList(t *testing.T) {
Mailbox: "good", Mailbox: "good",
ID: "0002", ID: "0002",
From: "from2", From: "from2",
To: []string{"to1"},
Subject: "subject 2", Subject: "subject 2",
Date: time.Date(2012, 7, 1, 10, 11, 12, 253, time.FixedZone("PDT", -700)), Date: time.Date(2012, 7, 1, 10, 11, 12, 253, time.FixedZone("PDT", -700)),
} }

View File

@@ -70,6 +70,11 @@ func (m *MockMessage) From() string {
return args.String(0) return args.String(0)
} }
func (m *MockMessage) To() []string {
args := m.Called()
return args.Get(0).([]string)
}
func (m *MockMessage) Date() time.Time { func (m *MockMessage) Date() time.Time {
args := m.Called() args := m.Called()
return args.Get(0).(time.Time) return args.Get(0).(time.Time)

View File

@@ -17,6 +17,7 @@ import (
type InputMessageData struct { type InputMessageData struct {
Mailbox, ID, From, Subject string Mailbox, ID, From, Subject string
To []string
Date time.Time Date time.Time
Size int Size int
Header mail.Header Header mail.Header
@@ -27,6 +28,7 @@ func (d *InputMessageData) MockMessage() *MockMessage {
msg := &MockMessage{} msg := &MockMessage{}
msg.On("ID").Return(d.ID) msg.On("ID").Return(d.ID)
msg.On("From").Return(d.From) msg.On("From").Return(d.From)
msg.On("To").Return(d.To)
msg.On("Subject").Return(d.Subject) msg.On("Subject").Return(d.Subject)
msg.On("Date").Return(d.Date) msg.On("Date").Return(d.Date)
msg.On("Size").Return(d.Size) msg.On("Size").Return(d.Size)
@@ -79,6 +81,11 @@ func (d *InputMessageData) CompareToJSONHeaderMap(json interface{}) (errors []st
if msg, ok := isJSONStringEqual(fromKey, d.From, m[fromKey]); !ok { if msg, ok := isJSONStringEqual(fromKey, d.From, m[fromKey]); !ok {
errors = append(errors, msg) errors = append(errors, msg)
} }
for i, inputTo := range d.To {
if msg, ok := isJSONStringEqual(toKey, inputTo, m[toKey].([]interface{})[i]); !ok {
errors = append(errors, msg)
}
}
if msg, ok := isJSONStringEqual(subjectKey, d.Subject, m[subjectKey]); !ok { if msg, ok := isJSONStringEqual(subjectKey, d.Subject, m[subjectKey]); !ok {
errors = append(errors, msg) errors = append(errors, msg)
} }

View File

@@ -36,6 +36,7 @@ type Mailbox interface {
type Message interface { type Message interface {
ID() string ID() string
From() string From() string
To() []string
Date() time.Time Date() time.Time
Subject() string Subject() string
RawReader() (reader io.ReadCloser, err error) RawReader() (reader io.ReadCloser, err error)

View File

@@ -295,6 +295,7 @@ type FileMessage struct {
Fid string Fid string
Fdate time.Time Fdate time.Time
Ffrom string Ffrom string
Fto []string
Fsubject string Fsubject string
Fsize int64 Fsize int64
// These are for creating new messages only // These are for creating new messages only
@@ -343,6 +344,11 @@ func (m *FileMessage) From() string {
return m.Ffrom return m.Ffrom
} }
// From returns the value of the Message To header
func (m *FileMessage) To() []string {
return m.Fto
}
// Subject returns the value of the Message Subject header // Subject returns the value of the Message Subject header
func (m *FileMessage) Subject() string { func (m *FileMessage) Subject() string {
return m.Fsubject return m.Fsubject
@@ -484,10 +490,24 @@ func (m *FileMessage) Close() error {
return err return err
} }
// Only public fields are stored in gob // Only public fields are stored in gob, hence starting with capital F
m.Ffrom = body.GetHeader("From") // Parse From address
if address, err := mail.ParseAddress(body.GetHeader("From")); err == nil {
m.Ffrom = address.String()
} else {
m.Ffrom = body.GetHeader("From")
}
m.Fsubject = body.GetHeader("Subject") m.Fsubject = body.GetHeader("Subject")
// Turn the To header into a slice
if addresses, err := body.AddressList("To"); err == nil {
for _, a := range addresses {
m.Fto = append(m.Fto, a.String())
}
} else {
m.Fto = []string{body.GetHeader("To")}
}
// Refresh the index before adding our message // Refresh the index before adding our message
err = m.mailbox.readIndex() err = m.mailbox.readIndex()
if err != nil { if err != nil {

View File

@@ -126,6 +126,11 @@ func (m *MockMessage) From() string {
return args.String(0) return args.String(0)
} }
func (m *MockMessage) To() []string {
args := m.Called()
return args.Get(0).([]string)
}
func (m *MockMessage) Date() time.Time { func (m *MockMessage) Date() time.Time {
args := m.Called() args := m.Called()
return args.Get(0).(time.Time) return args.Get(0).(time.Time)

View File

@@ -3,6 +3,7 @@
# description: Generate test emails for Inbucket # description: Generate test emails for Inbucket
set -eo pipefail set -eo pipefail
[ $TRACE ] && set -x
# We need to be in swaks-tests directory # We need to be in swaks-tests directory
cmdpath="$(dirname "$0")" cmdpath="$(dirname "$0")"
@@ -19,6 +20,7 @@ case "$1" in
;; ;;
*) *)
to="$1" to="$1"
shift
;; ;;
esac esac
@@ -28,6 +30,10 @@ export SWAKS_OPT_to="$to@inbucket.local"
# Basic test # Basic test
swaks $* --h-Subject: "Swaks Plain Text" --body text.txt swaks $* --h-Subject: "Swaks Plain Text" --body text.txt
# Multi-recipient test
swaks $* --to="$to@inbucket.local,Alt User <alternate@inbucket.local>" --h-Subject: "Swaks Multi-Recipient" \
--body text.txt
# HTML test # HTML test
swaks $* --h-Subject: "Swaks HTML" --data mime-html.raw swaks $* --h-Subject: "Swaks HTML" --data mime-html.raw
@@ -35,7 +41,8 @@ swaks $* --h-Subject: "Swaks HTML" --data mime-html.raw
swaks $* --h-Subject: "Swaks Top Level HTML" --data nonmime-html.raw swaks $* --h-Subject: "Swaks Top Level HTML" --data nonmime-html.raw
# Attachment test # Attachment test
swaks $* --h-Subject: "Swaks Attachment" --attach-type image/png --attach favicon.png --body text.txt swaks $* --h-Subject: "Swaks Attachment" --attach-type image/png --attach favicon.png \
--body text.txt
# Encoded subject line test # Encoded subject line test
swaks $* --data utf8-subject.raw swaks $* --data utf8-subject.raw

View File

@@ -52,6 +52,13 @@
<dl class="dl-horizontal"> <dl class="dl-horizontal">
<dt>From:</dt> <dt>From:</dt>
<dd>{{.message.From}}</dd> <dd>{{.message.From}}</dd>
<dt>To:</dt>
<dd>
{{range $i, $addr := .message.To}}
{{- if $i}},{{end}}
{{$addr -}}
{{end}}
</dd>
<dt>Date:</dt> <dt>Date:</dt>
<dd>{{.message.Date}}</dd> <dd>{{.message.Date}}</dd>
<dt>Subject:</dt> <dt>Subject:</dt>

View File

@@ -15,9 +15,9 @@ $(document).ready(function() {
<script type="text/html" id="list-entry-template"> <script type="text/html" id="list-entry-template">
<button data-id="id" type="button" class="message-list-entry list-group-item"> <button data-id="id" type="button" class="message-list-entry list-group-item">
<div class="row"> <div class="row">
<div class="col-sm-4 col-md-12 text-primary" data-content="subject" <div class="col-sm-4 col-md-12 text-primary" data-content-text="subject"
data-format="subject"/> data-format="subject"/>
<div class="col-sm-4 col-md-12 small" data-content="from"/> <div class="col-sm-4 col-md-12 small" data-content-text="from"/>
<div class="col-sm-4 col-md-12 small" data-content="date" data-format="date"/> <div class="col-sm-4 col-md-12 small" data-content="date" data-format="date"/>
</div> </div>
</button> </button>
@@ -34,8 +34,8 @@ $(document).ready(function() {
<div class="col-md-3"> <div class="col-md-3">
<div class="input-group"> <div class="input-group">
<input id="message-search" <input id="message-search"
type="search" type="search"
class="form-control" class="form-control"
placeholder="search" placeholder="search"
data-toggle="tooltip" data-toggle="tooltip"
data-placement="top" data-placement="top"

View File

@@ -13,6 +13,10 @@
<th>From:</th> <th>From:</th>
<td>{{.message.From}}</td> <td>{{.message.From}}</td>
</tr> </tr>
<tr>
<th>To:</th>
<td>{{.message.To}}</td>
</tr>
<tr> <tr>
<th>Date:</th> <th>Date:</th>
<td>{{.message.Date}}</td> <td>{{.message.Date}}</td>

View File

@@ -478,6 +478,11 @@ func (m *MockMessage) From() string {
return args.String(0) return args.String(0)
} }
func (m *MockMessage) To() []string {
args := m.Called()
return args.Get(0).([]string)
}
func (m *MockMessage) Date() time.Time { func (m *MockMessage) Date() time.Time {
args := m.Called() args := m.Called()
return args.Get(0).(time.Time) return args.Get(0).(time.Time)