diff --git a/etc/swaks-tests/mime-errors.raw b/etc/swaks-tests/mime-errors.raw new file mode 100644 index 0000000..c00fd09 --- /dev/null +++ b/etc/swaks-tests/mime-errors.raw @@ -0,0 +1,31 @@ +Date: %DATE% +To: %TO_ADDRESS% +From: %FROM_ADDRESS% +Subject: MIME Errors +Message-Id: <07B7061D-2676-487E-942E-C341CE4D13DC@makita.skynet> +Content-Type: multipart/alternative; boundary="Enmime-Test-100" + +--Enmime-Test-100 +Content-Transfer-Encoding: 8bit +Content-Type: text/plain; charset=us-ascii + +Using Unicode/UTF-8, you can write in emails and source code things such as + +Mathematics and sciences: + + ∮ E⋅da = Q, n → ∞, ∑ f(i) = ∏ g(i), ⎧⎡⎛┌─────┐⎞⎤⎫ + ⎪⎢⎜│a²+b³ ⎟⎥⎪ + ∀x∈ℝ: ⌈x⌉ = −⌊−x⌋, α ∧ ¬β = ¬(¬α ∨ β), ⎪⎢⎜│───── ⎟⎥⎪ + ⎪⎢⎜⎷ c₈ ⎟⎥⎪ + ℕ ⊆ ℕ₀ ⊂ ℤ ⊂ ℚ ⊂ ℝ ⊂ ℂ, ⎨⎢⎜ ⎟⎥⎬ + ⎪⎢⎜ ∞ ⎟⎥⎪ + ⊥ < a ≠ b ≡ c ≤ d ≪ ⊤ ⇒ (⟦A⟧ ⇔ ⟪B⟫), ⎪⎢⎜ ⎲ ⎟⎥⎪ + ⎪⎢⎜ ⎳aⁱ-bⁱ⎟⎥⎪ + 2H₂ + O₂ ⇌ 2H₂O, R = 4.7 kΩ, ⌀ 200 mm ⎩⎣⎝i=1 ⎠⎦⎭ + +Linguistics and dictionaries: + + ði ıntəˈnæʃənəl fəˈnɛtık əsoʊsiˈeıʃn + Y [ˈʏpsilɔn], Yen [jɛn], Yoga [ˈjoːgɑ] + +--Enmime-Test-100 diff --git a/etc/swaks-tests/run-tests.sh b/etc/swaks-tests/run-tests.sh index c9a93b8..548454b 100755 --- a/etc/swaks-tests/run-tests.sh +++ b/etc/swaks-tests/run-tests.sh @@ -56,3 +56,6 @@ swaks $* --data outlook.raw # Non-mime responsive HTML test swaks $* --data nonmime-html-responsive.raw swaks $* --data nonmime-html-inlined.raw + +# Incorrect charset, malformed final boundary +swaks $* --data mime-errors.raw diff --git a/pkg/webui/mailbox_controller.go b/pkg/webui/mailbox_controller.go index c9423e1..d1fc80c 100644 --- a/pkg/webui/mailbox_controller.go +++ b/pkg/webui/mailbox_controller.go @@ -6,7 +6,6 @@ import ( "io" "net/http" "strconv" - "time" "github.com/jhillyerd/inbucket/pkg/server/web" "github.com/jhillyerd/inbucket/pkg/storage" @@ -15,30 +14,6 @@ import ( "github.com/rs/zerolog/log" ) -// JSONMessage formats message data for the UI. -type JSONMessage struct { - Mailbox string `json:"mailbox"` - ID string `json:"id"` - From string `json:"from"` - To []string `json:"to"` - Subject string `json:"subject"` - Date time.Time `json:"date"` - PosixMillis int64 `json:"posix-millis"` - Size int64 `json:"size"` - Seen bool `json:"seen"` - Header map[string][]string `json:"header"` - Text string `json:"text"` - HTML string `json:"html"` - Attachments []*JSONAttachment `json:"attachments"` -} - -// JSONAttachment formats attachment data for the UI. -type JSONAttachment struct { - ID string `json:"id"` - FileName string `json:"filename"` - ContentType string `json:"content-type"` -} - // MailboxMessage outputs a particular message as JSON for the UI. func MailboxMessage(w http.ResponseWriter, req *http.Request, ctx *web.Context) (err error) { id := ctx.Vars["id"] @@ -54,15 +29,25 @@ func MailboxMessage(w http.ResponseWriter, req *http.Request, ctx *web.Context) http.NotFound(w, req) return nil } - attachParts := msg.Attachments() - attachments := make([]*JSONAttachment, len(attachParts)) - for i, part := range attachParts { - attachments[i] = &JSONAttachment{ + + attachments := make([]*jsonAttachment, 0) + for i, part := range msg.Attachments() { + attachments = append(attachments, &jsonAttachment{ ID: strconv.Itoa(i), FileName: part.FileName, ContentType: part.ContentType, - } + }) } + + mimeErrors := make([]*jsonMIMEError, 0) + for _, e := range msg.MIMEErrors() { + mimeErrors = append(mimeErrors, &jsonMIMEError{ + Name: e.Name, + Detail: e.Detail, + Severe: e.Severe, + }) + } + // Sanitize HTML body. htmlBody := "" if msg.HTML() != "" { @@ -74,8 +59,9 @@ func MailboxMessage(w http.ResponseWriter, req *http.Request, ctx *web.Context) Msg("HTML sanitizer failed") } } + return web.RenderJSON(w, - &JSONMessage{ + &jsonMessage{ Mailbox: name, ID: msg.ID, From: msg.From.String(), @@ -89,6 +75,7 @@ func MailboxMessage(w http.ResponseWriter, req *http.Request, ctx *web.Context) Text: web.TextToHTML(msg.Text()), HTML: htmlBody, Attachments: attachments, + Errors: mimeErrors, }) } diff --git a/pkg/webui/mailbox_json.go b/pkg/webui/mailbox_json.go new file mode 100644 index 0000000..70252c5 --- /dev/null +++ b/pkg/webui/mailbox_json.go @@ -0,0 +1,34 @@ +package webui + +import "time" + +// jsonMessage formats message data for the UI. +type jsonMessage struct { + Mailbox string `json:"mailbox"` + ID string `json:"id"` + From string `json:"from"` + To []string `json:"to"` + Subject string `json:"subject"` + Date time.Time `json:"date"` + PosixMillis int64 `json:"posix-millis"` + Size int64 `json:"size"` + Seen bool `json:"seen"` + Header map[string][]string `json:"header"` + Text string `json:"text"` + HTML string `json:"html"` + Attachments []*jsonAttachment `json:"attachments"` + Errors []*jsonMIMEError `json:"errors"` +} + +// jsonAttachment formats attachment data for the UI. +type jsonAttachment struct { + ID string `json:"id"` + FileName string `json:"filename"` + ContentType string `json:"content-type"` +} + +type jsonMIMEError struct { + Name string `json:"name"` + Detail string `json:"detail"` + Severe bool `json:"severe"` +}