Updated error handling and encoding comparison in EML parsing

This commit changes the usage of error value and improves the string comparison for encoding types in EML file parsing. It ensures file closure after read operations to avoid memory leaks. Error messages are made dynamic for improved error reporting. Comments on function has also been made more descriptive.
This commit is contained in:
Winni Neessen 2023-10-17 10:41:42 +02:00
parent 54ccb80925
commit 2bba7b902b
Signed by: wneessen
GPG key ID: 385AC9889632126E

24
eml.go
View file

@ -31,10 +31,10 @@ func EMLToMsg(fp string) (*Msg, error) {
return m, fmt.Errorf("failed to parse EML file: %w", err) return m, fmt.Errorf("failed to parse EML file: %w", err)
} }
if err := parseEMLHeaders(&pm.Header, m); err != nil { if err = parseEMLHeaders(&pm.Header, m); err != nil {
return m, fmt.Errorf("failed to parse EML headers: %w", err) return m, fmt.Errorf("failed to parse EML headers: %w", err)
} }
if err := parseEMLBodyParts(pm, mbbuf, m); err != nil { if err = parseEMLBodyParts(pm, mbbuf, m); err != nil {
return m, fmt.Errorf("failed to parse EML body parts: %w", err) return m, fmt.Errorf("failed to parse EML body parts: %w", err)
} }
@ -59,6 +59,10 @@ func readEML(fp string) (*nm.Message, *bytes.Buffer, error) {
if _, err = buf.ReadFrom(pm.Body); err != nil { if _, err = buf.ReadFrom(pm.Body); err != nil {
return nil, nil, err return nil, nil, err
} }
if err = fh.Close(); err != nil {
return nil, nil, fmt.Errorf("failed to close EML file: %w", err)
}
return pm, &buf, nil return pm, &buf, nil
} }
@ -75,7 +79,7 @@ func parseEMLHeaders(mh *nm.Header, m *Msg) error {
// Extract address headers // Extract address headers
if v := mh.Get(HeaderFrom.String()); v != "" { if v := mh.Get(HeaderFrom.String()); v != "" {
if err := m.From(v); err != nil { if err := m.From(v); err != nil {
return fmt.Errorf(`failed to parse "From:" header: %w`, err) return fmt.Errorf(`failed to parse %q header: %w`, HeaderFrom, err)
} }
} }
ahl := map[AddrHeader]func(...string) error{ ahl := map[AddrHeader]func(...string) error{
@ -94,7 +98,7 @@ func parseEMLHeaders(mh *nm.Header, m *Msg) error {
als = append(als, a.String()) als = append(als, a.String())
} }
if err := f(als...); err != nil { if err := f(als...); err != nil {
return fmt.Errorf(`failed to parse "To:" header: %w`, err) return fmt.Errorf(`failed to parse %q header: %w`, HeaderTo, err)
} }
} }
} }
@ -123,7 +127,7 @@ func parseEMLHeaders(mh *nm.Header, m *Msg) error {
return nil return nil
} }
// parseEMLBodyParts ... // parseEMLBodyParts parses the body of a EML based on the different content types and encodings
func parseEMLBodyParts(pm *nm.Message, mbbuf *bytes.Buffer, m *Msg) error { func parseEMLBodyParts(pm *nm.Message, mbbuf *bytes.Buffer, m *Msg) error {
// Extract the transfer encoding of the body // Extract the transfer encoding of the body
mt, par, err := mime.ParseMediaType(pm.Header.Get(HeaderContentType.String())) mt, par, err := mime.ParseMediaType(pm.Header.Get(HeaderContentType.String()))
@ -137,26 +141,26 @@ func parseEMLBodyParts(pm *nm.Message, mbbuf *bytes.Buffer, m *Msg) error {
cte := pm.Header.Get(HeaderContentTransferEnc.String()) cte := pm.Header.Get(HeaderContentTransferEnc.String())
switch strings.ToLower(mt) { switch strings.ToLower(mt) {
case TypeTextPlain.String(): case TypeTextPlain.String():
if cte == NoEncoding.String() { if strings.EqualFold(cte, NoEncoding.String()) {
m.SetEncoding(NoEncoding) m.SetEncoding(NoEncoding)
m.SetBodyString(TypeTextPlain, mbbuf.String()) m.SetBodyString(TypeTextPlain, mbbuf.String())
break break
} }
if cte == EncodingQP.String() { if strings.EqualFold(cte, EncodingQP.String()) {
m.SetEncoding(EncodingQP) m.SetEncoding(EncodingQP)
qpr := quotedprintable.NewReader(mbbuf) qpr := quotedprintable.NewReader(mbbuf)
qpbuf := bytes.Buffer{} qpbuf := bytes.Buffer{}
if _, err := qpbuf.ReadFrom(qpr); err != nil { if _, err = qpbuf.ReadFrom(qpr); err != nil {
return fmt.Errorf("failed to read quoted-printable body: %w", err) return fmt.Errorf("failed to read quoted-printable body: %w", err)
} }
m.SetBodyString(TypeTextPlain, qpbuf.String()) m.SetBodyString(TypeTextPlain, qpbuf.String())
break break
} }
if cte == EncodingB64.String() { if strings.EqualFold(cte, EncodingB64.String()) {
m.SetEncoding(EncodingB64) m.SetEncoding(EncodingB64)
b64d := base64.NewDecoder(base64.StdEncoding, mbbuf) b64d := base64.NewDecoder(base64.StdEncoding, mbbuf)
b64buf := bytes.Buffer{} b64buf := bytes.Buffer{}
if _, err := b64buf.ReadFrom(b64d); err != nil { if _, err = b64buf.ReadFrom(b64d); err != nil {
return fmt.Errorf("failed to read base64 body: %w", err) return fmt.Errorf("failed to read base64 body: %w", err)
} }
m.SetBodyString(TypeTextPlain, b64buf.String()) m.SetBodyString(TypeTextPlain, b64buf.String())