add Content-Disposition and Filename to the payload of incoming webhooks

for each message part. The ContentDisposition value is the base value without
header key/value parameters. the Filename field is the likely filename of the
part. the different email clients encode filenames differently. there is a
standard mime mechanism from rfc 2231. and there is the q/b-word-encoding from
rfc 2047. instead of letting users of the webhook api deal with those
differences, we provide just the parsed filename.

for issue #258 by morki, thanks for reporting!
This commit is contained in:
Mechiel Lukkien
2024-12-06 14:19:39 +01:00
parent 8804d6b60e
commit 42793834f8
15 changed files with 170 additions and 52 deletions

View File

@ -521,13 +521,11 @@ func handle(apiHandler http.Handler, isForwarded bool, accountPath string, w htt
names := map[string]bool{}
for _, a := range mi.Attachments {
ap := a.Part
name := tryDecodeParam(log, ap.ContentTypeParams["name"])
if name == "" {
// We don't check errors, this is all best-effort.
h, _ := ap.Header()
disposition := h.Get("Content-Disposition")
_, params, _ := mime.ParseMediaType(disposition)
name = tryDecodeParam(log, params["filename"])
_, name, err := ap.DispositionFilename()
if err != nil && errors.Is(err, message.ErrParamEncoding) {
log.Debugx("parsing disposition header for filename", err)
} else {
xcheckf(ctx, err, "reading disposition header")
}
if name != "" {
name = filepath.Base(name)
@ -816,13 +814,11 @@ func handle(apiHandler http.Handler, isForwarded bool, accountPath string, w htt
h.Set("Content-Type", ct)
h.Set("Cache-Control", "no-store, max-age=0")
if t[1] == "download" {
name := tryDecodeParam(log, ap.ContentTypeParams["name"])
if name == "" {
// We don't check errors, this is all best-effort.
h, _ := ap.Header()
disposition := h.Get("Content-Disposition")
_, params, _ := mime.ParseMediaType(disposition)
name = tryDecodeParam(log, params["filename"])
_, name, err := ap.DispositionFilename()
if err != nil && errors.Is(err, message.ErrParamEncoding) {
log.Debugx("parsing disposition/filename", err)
} else {
xcheckf(ctx, err, "reading disposition/filename")
}
if name == "" {
name = "attachment.bin"