(part *multipart.Part, parsed *ParsedEmail, atts *[]parsedAttachment)
| 265 | } |
| 266 | |
| 267 | func processPart(part *multipart.Part, parsed *ParsedEmail, atts *[]parsedAttachment) { |
| 268 | ct := part.Header.Get("Content-Type") |
| 269 | disposition := part.Header.Get("Content-Disposition") |
| 270 | |
| 271 | mediaType, params, _ := mime.ParseMediaType(ct) |
| 272 | |
| 273 | // Recurse into nested multipart. |
| 274 | if strings.HasPrefix(mediaType, "multipart/") { |
| 275 | if boundary := params["boundary"]; boundary != "" { |
| 276 | mr := multipart.NewReader(part, boundary) |
| 277 | for { |
| 278 | subpart, err := mr.NextPart() |
| 279 | if err != nil { |
| 280 | break |
| 281 | } |
| 282 | processPart(subpart, parsed, atts) |
| 283 | } |
| 284 | } |
| 285 | return |
| 286 | } |
| 287 | |
| 288 | // Attachment. |
| 289 | if strings.HasPrefix(disposition, "attachment") || strings.HasPrefix(disposition, "inline") { |
| 290 | content, _ := io.ReadAll(part) |
| 291 | encoding := part.Header.Get("Content-Transfer-Encoding") |
| 292 | if strings.EqualFold(encoding, "base64") { |
| 293 | if decoded, err := base64.StdEncoding.DecodeString(string(content)); err == nil { |
| 294 | content = decoded |
| 295 | } |
| 296 | } |
| 297 | |
| 298 | filename := part.FileName() |
| 299 | if filename == "" { |
| 300 | filename = "unnamed" |
| 301 | } |
| 302 | mimeType := ct |
| 303 | if idx := strings.Index(mimeType, ";"); idx > 0 { |
| 304 | mimeType = strings.TrimSpace(mimeType[:idx]) |
| 305 | } |
| 306 | if mimeType == "" { |
| 307 | mimeType = "application/octet-stream" |
| 308 | } |
| 309 | |
| 310 | contentID := strings.Trim(part.Header.Get("Content-ID"), "<>") |
| 311 | |
| 312 | *atts = append(*atts, parsedAttachment{ |
| 313 | Filename: filename, |
| 314 | Type: mimeType, |
| 315 | ContentID: contentID, |
| 316 | content: content, |
| 317 | }) |
| 318 | return |
| 319 | } |
| 320 | |
| 321 | // Body content. |
| 322 | body, _ := io.ReadAll(part) |
| 323 | decoded := decodeContent(body, part.Header.Get("Content-Transfer-Encoding")) |
| 324 | decoded = convertToUTF8(decoded, params["charset"]) |
no test coverage detected