collectAttachments appends attachment leaves found under this part to *out.
(contentType, cte, disposition, partFilename string, body io.Reader, depth int, out *[]Attachment)
| 62 | |
| 63 | // collectAttachments appends attachment leaves found under this part to *out. |
| 64 | func collectAttachments(contentType, cte, disposition, partFilename string, body io.Reader, depth int, out *[]Attachment) { |
| 65 | mediaType, params, err := mime.ParseMediaType(contentType) |
| 66 | if err != nil { |
| 67 | mediaType = "text/plain" // missing/invalid Content-Type → body text, not an attachment |
| 68 | } |
| 69 | |
| 70 | if strings.HasPrefix(mediaType, "multipart/") { |
| 71 | if depth >= maxMIMEDepth { |
| 72 | return |
| 73 | } |
| 74 | boundary := params["boundary"] |
| 75 | if boundary == "" { |
| 76 | return |
| 77 | } |
| 78 | mr := multipart.NewReader(body, boundary) |
| 79 | for { |
| 80 | part, err := mr.NextPart() |
| 81 | if err != nil { |
| 82 | break |
| 83 | } |
| 84 | collectAttachments( |
| 85 | part.Header.Get("Content-Type"), |
| 86 | part.Header.Get("Content-Transfer-Encoding"), |
| 87 | part.Header.Get("Content-Disposition"), |
| 88 | part.FileName(), // decoded by mime/multipart |
| 89 | part, |
| 90 | depth+1, |
| 91 | out, |
| 92 | ) |
| 93 | part.Close() |
| 94 | } |
| 95 | return |
| 96 | } |
| 97 | |
| 98 | // Leaf part. It's an attachment iff it has a filename or is explicitly an |
| 99 | // attachment disposition. |
| 100 | filename := partFilename |
| 101 | if filename == "" { |
| 102 | filename = params["name"] // Content-Type: ...; name="x" (legacy) |
| 103 | if filename != "" { |
| 104 | if dec, derr := (&mime.WordDecoder{}).DecodeHeader(filename); derr == nil { |
| 105 | filename = dec |
| 106 | } |
| 107 | } |
| 108 | } |
| 109 | isAttachmentDisp := strings.HasPrefix(strings.ToLower(strings.TrimSpace(disposition)), "attachment") |
| 110 | if filename == "" && !isAttachmentDisp { |
| 111 | return // body text / unnamed inline part — not a fetchable attachment |
| 112 | } |
| 113 | |
| 114 | *out = append(*out, Attachment{ |
| 115 | Filename: filename, |
| 116 | ContentType: mediaType, |
| 117 | Data: decodeBytes(body, cte), |
| 118 | }) |
| 119 | } |
| 120 | |
| 121 | // decodeBytes reads a body applying its Content-Transfer-Encoding, returning raw |
no test coverage detected