mirror of
https://github.com/wneessen/go-mail.git
synced 2024-11-22 05:40:50 +01:00
Add support for multipart/related EML parsing
This update expands the EML parser to support multipart/related content types. It also includes relevant error handling and creates a specific routine for parsing multipart/related parts separately. Furthermore, adjustments were made to avoid processing headers unnecessarily when TypeMultipartMixed is used. The diff also shows some refactoring for clearer error messages and cleaner code.
This commit is contained in:
parent
52ef13a5d5
commit
bb33c4a921
1 changed files with 31 additions and 4 deletions
35
eml.go
35
eml.go
|
@ -70,6 +70,7 @@ func EMLToMsgFromFile(filePath string) (*Msg, error) {
|
||||||
if err = parseEMLBodyParts(parsedMsg, bodybuf, msg); err != nil {
|
if err = parseEMLBodyParts(parsedMsg, bodybuf, msg); err != nil {
|
||||||
return msg, fmt.Errorf("failed to parse EML body parts: %w", err)
|
return msg, fmt.Errorf("failed to parse EML body parts: %w", err)
|
||||||
}
|
}
|
||||||
|
//fmt.Printf("FOO: %+v\n", msg)
|
||||||
|
|
||||||
return msg, nil
|
return msg, nil
|
||||||
}
|
}
|
||||||
|
@ -159,6 +160,10 @@ func parseEMLHeaders(mailHeader *netmail.Header, msg *Msg) error {
|
||||||
// Extract common headers
|
// Extract common headers
|
||||||
for _, header := range commonHeaders {
|
for _, header := range commonHeaders {
|
||||||
if value := mailHeader.Get(header.String()); value != "" {
|
if value := mailHeader.Get(header.String()); value != "" {
|
||||||
|
if strings.EqualFold(header.String(), HeaderContentType.String()) &&
|
||||||
|
strings.HasPrefix(value, TypeMultipartMixed.String()) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
msg.SetGenHeader(header, value)
|
msg.SetGenHeader(header, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -184,9 +189,10 @@ 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, TypeMultipartMixed.String()):
|
strings.EqualFold(mediatype, TypeMultipartMixed.String()),
|
||||||
|
strings.EqualFold(mediatype, TypeMultipartRelated.String()):
|
||||||
if err = parseEMLMultipart(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 body: %w", err)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
@ -242,9 +248,27 @@ ReadNextPart:
|
||||||
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 {
|
||||||
|
// Multipart/related parts need to be parsed seperately
|
||||||
|
if contentTypeSlice, ok := multiPart.Header[HeaderContentType.String()]; ok && len(contentTypeSlice) == 1 {
|
||||||
|
contentType, _ := parseMultiPartHeader(contentTypeSlice[0])
|
||||||
|
if strings.EqualFold(contentType, TypeMultipartRelated.String()) {
|
||||||
|
relatedPart := &netmail.Message{
|
||||||
|
Header: netmail.Header(multiPart.Header),
|
||||||
|
Body: multiPart,
|
||||||
|
}
|
||||||
|
relatedBuf := &bytes.Buffer{}
|
||||||
|
if _, err = relatedBuf.ReadFrom(multiPart); err != nil {
|
||||||
|
return fmt.Errorf("failed to read related multipart message to buffer: %w", err)
|
||||||
|
}
|
||||||
|
if err := parseEMLBodyParts(relatedPart, relatedBuf, msg); err != nil {
|
||||||
|
return fmt.Errorf("failed to parse related multipart body: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Content-Disposition header means we have an attachment or embed
|
// Content-Disposition header means we have an attachment or embed
|
||||||
if contentDisposition, ok := multiPart.Header[HeaderContentDisposition.String()]; ok {
|
if contentDisposition, ok := multiPart.Header[HeaderContentDisposition.String()]; ok {
|
||||||
if err := parseEMLAttachmentEmbed(contentDisposition, multiPart, msg); err != nil {
|
if err = parseEMLAttachmentEmbed(contentDisposition, multiPart, msg); err != nil {
|
||||||
return fmt.Errorf("failed to parse attachment/embed: %w", err)
|
return fmt.Errorf("failed to parse attachment/embed: %w", err)
|
||||||
}
|
}
|
||||||
goto ReadNextPart
|
goto ReadNextPart
|
||||||
|
@ -261,6 +285,9 @@ ReadNextPart:
|
||||||
return fmt.Errorf("failed to get content-type from part")
|
return fmt.Errorf("failed to get content-type from part")
|
||||||
}
|
}
|
||||||
contentType, optional := parseMultiPartHeader(multiPartContentType[0])
|
contentType, optional := parseMultiPartHeader(multiPartContentType[0])
|
||||||
|
if strings.EqualFold(contentType, TypeMultipartRelated.String()) {
|
||||||
|
goto ReadNextPart
|
||||||
|
}
|
||||||
part := msg.newPart(ContentType(contentType))
|
part := msg.newPart(ContentType(contentType))
|
||||||
if charset, ok := optional["charset"]; ok {
|
if charset, ok := optional["charset"]; ok {
|
||||||
part.SetCharset(Charset(charset))
|
part.SetCharset(Charset(charset))
|
||||||
|
@ -316,7 +343,7 @@ func parseEMLContentTypeCharset(mailHeader *netmail.Header, msg *Msg) {
|
||||||
msg.SetCharset(Charset(charset))
|
msg.SetCharset(Charset(charset))
|
||||||
}
|
}
|
||||||
msg.setEncoder()
|
msg.setEncoder()
|
||||||
if contentType != "" {
|
if contentType != "" && !strings.EqualFold(contentType, TypeMultipartMixed.String()) {
|
||||||
msg.SetGenHeader(HeaderContentType, contentType)
|
msg.SetGenHeader(HeaderContentType, contentType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue