1
0
mirror of https://github.com/jhillyerd/inbucket.git synced 2025-12-18 10:07:02 +00:00

Merge branch 'feature/mime-errors' into develop

This commit is contained in:
James Hillyerd
2018-12-28 11:47:26 -08:00
7 changed files with 152 additions and 31 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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,
})
}

34
pkg/webui/mailbox_json.go Normal file
View File

@@ -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"`
}

View File

@@ -18,6 +18,7 @@ type alias Message =
, text : String
, html : String
, attachments : List Attachment
, errors : List Error
}
@@ -28,6 +29,13 @@ type alias Attachment =
}
type alias Error =
{ name : String
, detail : String
, severe : Bool
}
decoder : Decoder Message
decoder =
succeed Message
@@ -42,6 +50,7 @@ decoder =
|> required "text" string
|> required "html" string
|> required "attachments" (list attachmentDecoder)
|> required "errors" (list errorDecoder)
attachmentDecoder : Decoder Attachment
@@ -50,3 +59,11 @@ attachmentDecoder =
|> required "id" string
|> required "filename" string
|> required "content-type" string
errorDecoder : Decoder Error
errorDecoder =
succeed Error
|> required "name" string
|> required "detail" string
|> required "severe" bool

View File

@@ -590,11 +590,34 @@ viewMessage zone message bodyMode =
, dt [] [ text "Subject:" ]
, dd [] [ text message.subject ]
]
, messageErrors message
, messageBody message bodyMode
, attachments message
]
messageErrors : Message -> Html Msg
messageErrors message =
let
row error =
li []
[ span
[ classList [ ( "warn-severe", error.severe ) ] ]
[ text (error.name ++ ": ") ]
, text error.detail
]
in
case message.errors of
[] ->
text ""
errors ->
div [ class "warn" ]
[ div [] [ h3 [] [ text "MIME problems detected" ] ]
, ul [] (List.map row errors)
]
messageBody : Message -> Body -> Html Msg
messageBody message bodyMode =
let

View File

@@ -141,6 +141,11 @@ h2 {
font-weight: 700;
}
h3 {
font-size: 14px;
font-weight: 700;
}
.error {
background-color: #f58080;
background-image: linear-gradient(to bottom, #e86060 0, #f58080 100%);
@@ -203,6 +208,27 @@ h2 {
padding: 10px !important;
}
.warn {
--light: #f5f580;
--dark: #e8e860;
background-color: var(--light);
background-image: linear-gradient(to bottom, var(--dark) 0, var(--light) 100%);
border: 1px solid var(--dark);
border-radius: 4px;
box-shadow: 0 1px 2px rgba(0,0,0,.05);
padding: 6px 10px;
margin: 20px 0;
}
.warn li {
margin-left: 20px;
padding-left: 0px;
}
.warn-severe {
font-weight: 700;
}
/** NAV BAR */
.navbar,