mirror of
https://github.com/wneessen/go-mail.git
synced 2024-11-22 05:40:50 +01:00
Refactor multipart parsing in eml.go
The code is refactored to improve multipart parsing in EML. The `parseEMLMultipartAlternative` function is updated to `parseEMLMultipart` for more general utilization. This involves iterating through the parts of a multipart message until content disposition is found and appended. A new function `parseMultiPartHeader` is introduced to parse multipart header and handle charset more sensibly.
This commit is contained in:
parent
29305675d6
commit
85c07c22cc
1 changed files with 35 additions and 25 deletions
60
eml.go
60
eml.go
|
@ -184,8 +184,8 @@ func parseEMLBodyParts(parsedMsg *netmail.Message, bodybuf *bytes.Buffer, msg *M
|
||||||
return fmt.Errorf("failed to parse plain body: %w", err)
|
return fmt.Errorf("failed to parse plain body: %w", err)
|
||||||
}
|
}
|
||||||
case strings.EqualFold(mediatype, TypeMultipartAlternative.String()),
|
case strings.EqualFold(mediatype, TypeMultipartAlternative.String()),
|
||||||
strings.EqualFold(mediatype, "multipart/mixed"):
|
strings.EqualFold(mediatype, TypeMultipartMixed.String()):
|
||||||
if err = parseEMLMultipartAlternative(params, bodybuf, msg); err != nil {
|
if err = parseEMLMultipart(params, bodybuf, msg); err != nil {
|
||||||
return fmt.Errorf("failed to parse multipart/alternative body: %w", err)
|
return fmt.Errorf("failed to parse multipart/alternative body: %w", err)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -224,8 +224,8 @@ func parseEMLBodyPlain(mediatype string, parsedMsg *netmail.Message, bodybuf *by
|
||||||
return fmt.Errorf("unsupported Content-Transfer-Encoding")
|
return fmt.Errorf("unsupported Content-Transfer-Encoding")
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseEMLMultipartAlternative parses a multipart/alternative body part of a EML
|
// parseEMLMultipart parses a multipart body part of a EML
|
||||||
func parseEMLMultipartAlternative(params map[string]string, bodybuf *bytes.Buffer, msg *Msg) error {
|
func parseEMLMultipart(params map[string]string, bodybuf *bytes.Buffer, msg *Msg) error {
|
||||||
boundary, ok := params["boundary"]
|
boundary, ok := params["boundary"]
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("no boundary tag found in multipart body")
|
return fmt.Errorf("no boundary tag found in multipart body")
|
||||||
|
@ -236,6 +236,16 @@ func parseEMLMultipartAlternative(params map[string]string, bodybuf *bytes.Buffe
|
||||||
return fmt.Errorf("failed to get next part of multipart message: %w", err)
|
return fmt.Errorf("failed to get next part of multipart message: %w", err)
|
||||||
}
|
}
|
||||||
for err == nil {
|
for err == nil {
|
||||||
|
if contentDisposition, ok := multiPart.Header[HeaderContentDisposition.String()]; ok {
|
||||||
|
cdType, optional := parseMultiPartHeader(contentDisposition[0])
|
||||||
|
fmt.Println("CTD:", cdType)
|
||||||
|
fmt.Printf("optional: %+v\n", optional)
|
||||||
|
if err = msg.AttachReader("", multiPart); err != nil {
|
||||||
|
return fmt.Errorf("failed to attach multipart body: %w", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
multiPartData, mperr := io.ReadAll(multiPart)
|
multiPartData, mperr := io.ReadAll(multiPart)
|
||||||
if mperr != nil {
|
if mperr != nil {
|
||||||
_ = multiPart.Close()
|
_ = multiPart.Close()
|
||||||
|
@ -246,9 +256,11 @@ func parseEMLMultipartAlternative(params map[string]string, bodybuf *bytes.Buffe
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("failed to get content-type from part")
|
return fmt.Errorf("failed to get content-type from part")
|
||||||
}
|
}
|
||||||
contentType, charSet := parseContentType(multiPartContentType[0])
|
contentType, optional := parseMultiPartHeader(multiPartContentType[0])
|
||||||
p := msg.newPart(ContentType(contentType))
|
part := msg.newPart(ContentType(contentType))
|
||||||
p.SetCharset(Charset(charSet))
|
if charset, ok := optional["charset"]; ok {
|
||||||
|
part.SetCharset(Charset(charset))
|
||||||
|
}
|
||||||
|
|
||||||
mutliPartTransferEnc, ok := multiPart.Header[HeaderContentTransferEnc.String()]
|
mutliPartTransferEnc, ok := multiPart.Header[HeaderContentTransferEnc.String()]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -260,16 +272,16 @@ func parseEMLMultipartAlternative(params map[string]string, bodybuf *bytes.Buffe
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case strings.EqualFold(mutliPartTransferEnc[0], EncodingB64.String()):
|
case strings.EqualFold(mutliPartTransferEnc[0], EncodingB64.String()):
|
||||||
if err := handleEMLMultiPartBase64Encoding(multiPartData, p); err != nil {
|
if err := handleEMLMultiPartBase64Encoding(multiPartData, part); err != nil {
|
||||||
return fmt.Errorf("failed to handle multipart base64 transfer-encoding: %w", err)
|
return fmt.Errorf("failed to handle multipart base64 transfer-encoding: %w", err)
|
||||||
}
|
}
|
||||||
case strings.EqualFold(mutliPartTransferEnc[0], EncodingQP.String()):
|
case strings.EqualFold(mutliPartTransferEnc[0], EncodingQP.String()):
|
||||||
p.SetContent(string(multiPartData))
|
part.SetContent(string(multiPartData))
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unsupported Content-Transfer-Encoding")
|
return fmt.Errorf("unsupported Content-Transfer-Encoding")
|
||||||
}
|
}
|
||||||
|
|
||||||
msg.parts = append(msg.parts, p)
|
msg.parts = append(msg.parts, part)
|
||||||
multiPart, err = multipartReader.NextPart()
|
multiPart, err = multipartReader.NextPart()
|
||||||
}
|
}
|
||||||
if !errors.Is(err, io.EOF) {
|
if !errors.Is(err, io.EOF) {
|
||||||
|
@ -296,9 +308,9 @@ func parseEMLEncoding(mailHeader *netmail.Header, msg *Msg) {
|
||||||
// parseEMLContentTypeCharset parses and determines the charset and content type of the message
|
// parseEMLContentTypeCharset parses and determines the charset and content type of the message
|
||||||
func parseEMLContentTypeCharset(mailHeader *netmail.Header, msg *Msg) {
|
func parseEMLContentTypeCharset(mailHeader *netmail.Header, msg *Msg) {
|
||||||
if value := mailHeader.Get(HeaderContentType.String()); value != "" {
|
if value := mailHeader.Get(HeaderContentType.String()); value != "" {
|
||||||
contentType, charSet := parseContentType(value)
|
contentType, optional := parseMultiPartHeader(value)
|
||||||
if charSet != "" {
|
if charset, ok := optional["charset"]; ok {
|
||||||
msg.SetCharset(Charset(charSet))
|
msg.SetCharset(Charset(charset))
|
||||||
}
|
}
|
||||||
msg.setEncoder()
|
msg.setEncoder()
|
||||||
if contentType != "" {
|
if contentType != "" {
|
||||||
|
@ -318,18 +330,16 @@ func handleEMLMultiPartBase64Encoding(multiPartData []byte, part *Part) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseContentType parses the Content-Type header and returns the type and charse as
|
// parseMultiPartHeader parses a multipart header and returns the value and optional parts as
|
||||||
// separate string values
|
// separate map
|
||||||
func parseContentType(contentTypeHeader string) (contentType string, charSet string) {
|
func parseMultiPartHeader(multiPartHeader string) (header string, optional map[string]string) {
|
||||||
contentTypeSplit := strings.SplitN(contentTypeHeader, "; ", 2)
|
optional = make(map[string]string)
|
||||||
if len(contentTypeSplit) != 2 {
|
headerSplit := strings.SplitN(multiPartHeader, "; ", 2)
|
||||||
return
|
header = headerSplit[0]
|
||||||
}
|
if len(headerSplit) == 2 {
|
||||||
contentType = contentTypeSplit[0]
|
optSplit := strings.SplitN(headerSplit[1], "=", 2)
|
||||||
if strings.HasPrefix(strings.ToLower(contentTypeSplit[1]), "charset=") {
|
if len(optSplit) == 2 {
|
||||||
charSetSplit := strings.SplitN(contentTypeSplit[1], "=", 2)
|
optional[optSplit[0]] = optSplit[1]
|
||||||
if len(charSetSplit) == 2 {
|
|
||||||
charSet = charSetSplit[1]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
|
Loading…
Reference in a new issue