fix(mailparser): kaputte/truncated Multipart-Mails partiell indexieren statt scheitern
Bei NextPart()-Fehler (EOF, malformed header) wird der bereits geparste Inhalt zurückgegeben statt der gesamte Parse abgebrochen. parseMultipart() gibt keinen Fehler mehr zurück — partieller Text/HTML ist besser als gar kein Index-Eintrag. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
5e7ae6e056
commit
0ccbd5bafb
@@ -180,9 +180,9 @@ func Parse(raw []byte) (*ParsedMail, error) {
|
|||||||
|
|
||||||
if strings.HasPrefix(mediaType, "multipart/") {
|
if strings.HasPrefix(mediaType, "multipart/") {
|
||||||
boundary := params["boundary"]
|
boundary := params["boundary"]
|
||||||
if err := parseMultipart(pm, msg.Body, boundary); err != nil {
|
// Ignore parse errors — return partial content instead of failing completely.
|
||||||
return nil, fmt.Errorf("mailparser: multipart: %w", err)
|
// Malformed/truncated multipart emails still get metadata + whatever parts parsed.
|
||||||
}
|
parseMultipart(pm, msg.Body, boundary) //nolint:errcheck
|
||||||
} else {
|
} else {
|
||||||
body, _ := io.ReadAll(msg.Body)
|
body, _ := io.ReadAll(msg.Body)
|
||||||
decoded := decodeBody(body, msg.Header.Get("Content-Transfer-Encoding"))
|
decoded := decodeBody(body, msg.Header.Get("Content-Transfer-Encoding"))
|
||||||
@@ -198,15 +198,14 @@ func Parse(raw []byte) (*ParsedMail, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// parseMultipart walks MIME parts and fills text, html, and attachments.
|
// parseMultipart walks MIME parts and fills text, html, and attachments.
|
||||||
func parseMultipart(pm *ParsedMail, body io.Reader, boundary string) error {
|
// Truncated or malformed parts are skipped — partial content is better than nothing.
|
||||||
|
func parseMultipart(pm *ParsedMail, body io.Reader, boundary string) {
|
||||||
mr := multipart.NewReader(body, boundary)
|
mr := multipart.NewReader(body, boundary)
|
||||||
for {
|
for {
|
||||||
part, err := mr.NextPart()
|
part, err := mr.NextPart()
|
||||||
if err == io.EOF {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
// io.EOF = normal end; any other error = truncated/malformed — stop here.
|
||||||
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
ct := part.Header.Get("Content-Type")
|
ct := part.Header.Get("Content-Type")
|
||||||
@@ -244,9 +243,7 @@ func parseMultipart(pm *ParsedMail, body io.Reader, boundary string) error {
|
|||||||
|
|
||||||
// Nested multipart
|
// Nested multipart
|
||||||
if strings.HasPrefix(mediaType, "multipart/") {
|
if strings.HasPrefix(mediaType, "multipart/") {
|
||||||
if err := parseMultipart(pm, bytes.NewReader(decoded), params["boundary"]); err != nil {
|
parseMultipart(pm, bytes.NewReader(decoded), params["boundary"])
|
||||||
return err
|
|
||||||
}
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -257,7 +254,6 @@ func parseMultipart(pm *ParsedMail, body io.Reader, boundary string) error {
|
|||||||
pm.HTMLBody += string(decoded)
|
pm.HTMLBody += string(decoded)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// decodeCharset converts data from the declared MIME charset to UTF-8.
|
// decodeCharset converts data from the declared MIME charset to UTF-8.
|
||||||
|
|||||||
Reference in New Issue
Block a user