Decode plain text mbox bodies
This commit is contained in:
parent
955c1e0f92
commit
88e82286d8
1 changed files with 61 additions and 1 deletions
|
|
@ -2,9 +2,12 @@ package backend
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io"
|
||||
"mime"
|
||||
"mime/multipart"
|
||||
"mime/quotedprintable"
|
||||
"net/mail"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
|
@ -162,7 +165,64 @@ func messageBody(raw []byte) string {
|
|||
if err != nil {
|
||||
return string(raw)
|
||||
}
|
||||
return string(body)
|
||||
return extractTextBody(msg.Header, body)
|
||||
}
|
||||
|
||||
type headerGetter interface {
|
||||
Get(string) string
|
||||
}
|
||||
|
||||
func extractTextBody(h headerGetter, body []byte) string {
|
||||
mediaType, params, _ := mime.ParseMediaType(h.Get("Content-Type"))
|
||||
decoded := decodeTransfer(body, h.Get("Content-Transfer-Encoding"))
|
||||
if strings.HasPrefix(mediaType, "multipart/") {
|
||||
boundary := params["boundary"]
|
||||
if boundary == "" {
|
||||
return string(decoded)
|
||||
}
|
||||
mr := multipart.NewReader(bytes.NewReader(decoded), boundary)
|
||||
var htmlBody string
|
||||
for {
|
||||
part, err := mr.NextPart()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
partBody, _ := io.ReadAll(part)
|
||||
text := extractTextBody(part.Header, partBody)
|
||||
partType, _, _ := mime.ParseMediaType(part.Header.Get("Content-Type"))
|
||||
if strings.HasPrefix(partType, "text/plain") && strings.TrimSpace(text) != "" {
|
||||
return text
|
||||
}
|
||||
if strings.HasPrefix(partType, "text/html") && htmlBody == "" {
|
||||
htmlBody = text
|
||||
}
|
||||
}
|
||||
if htmlBody != "" {
|
||||
return htmlBody
|
||||
}
|
||||
return ""
|
||||
}
|
||||
return string(decoded)
|
||||
}
|
||||
|
||||
func decodeTransfer(body []byte, enc string) []byte {
|
||||
switch strings.ToLower(strings.TrimSpace(enc)) {
|
||||
case "quoted-printable":
|
||||
b, err := io.ReadAll(quotedprintable.NewReader(bytes.NewReader(body)))
|
||||
if err == nil {
|
||||
return b
|
||||
}
|
||||
case "base64":
|
||||
cleaned := strings.NewReplacer("\r", "", "\n", "", " ", "", "\t", "").Replace(string(body))
|
||||
b, err := base64.StdEncoding.DecodeString(cleaned)
|
||||
if err == nil {
|
||||
return b
|
||||
}
|
||||
}
|
||||
return body
|
||||
}
|
||||
|
||||
func safeMboxName(folder string) string {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue