func parseMultiPartBody(root *Part, e *Envelope) error {
	// Parse top-level multipart
	ctype := root.Header.Get(hnContentType)
	mediatype, params, _, err := parseMediaType(ctype)
	if err != nil {
		return fmt.Errorf("Unable to parse media type: %v", err)
	}
	if !strings.HasPrefix(mediatype, ctMultipartPrefix) {
		return fmt.Errorf("Unknown mediatype: %v", mediatype)
	}
	boundary := params[hpBoundary]
	if boundary == "" {
		return fmt.Errorf("Unable to locate boundary param in Content-Type header")
	}

	// Locate text body
	if mediatype == ctMultipartAltern {
		p := root.BreadthMatchFirst(func(p *Part) bool {
			return p.ContentType == ctTextPlain && p.Disposition != cdAttachment
		})
		if p != nil {
			e.Text = string(p.Content)
		}
	} else {
		// multipart is of a mixed type
		parts := root.DepthMatchAll(func(p *Part) bool {
			return p.ContentType == ctTextPlain && p.Disposition != cdAttachment
		})
		for i, p := range parts {
			if i > 0 {
				e.Text += "\n--\n"
			}
			e.Text += string(p.Content)
		}
	}

	// Locate HTML body
	p := root.BreadthMatchFirst(matchHTMLBodyPart)
	if p != nil {
		e.HTML += string(p.Content)
	}

	// Locate attachments
	e.Attachments = root.BreadthMatchAll(func(p *Part) bool {
		return p.Disposition == cdAttachment || p.ContentType == ctAppOctetStream
	})

	// Locate inlines
	e.Inlines = root.BreadthMatchAll(func(p *Part) bool {
		return p.Disposition == cdInline && !strings.HasPrefix(p.ContentType, ctMultipartPrefix)
	})

	// Locate others parts not considered in attachments or inlines
	e.OtherParts = root.BreadthMatchAll(func(p *Part) bool {
		if strings.HasPrefix(p.ContentType, ctMultipartPrefix) {
			return false
		}
		if p.Disposition != "" {
			return false
		}
		if p.ContentType == ctAppOctetStream {
			return false
		}
		return p.ContentType != ctTextPlain && p.ContentType != ctTextHTML
	})

	return nil
}
func parseMultiPartBody(root *Part, e *Envelope) error {
	
	ctype := root.Header.Get(hnContentType)
	mediatype, params, _, err := parseMediaType(ctype)
	if err != nil {
		return fmt.Errorf("Unable to parse media type: %v", err)
	}
	if !strings.HasPrefix(mediatype, ctMultipartPrefix) {
		return fmt.Errorf("Unknown mediatype: %v", mediatype)
	}
	boundary := params[hpBoundary]
	if boundary == "" {
		return fmt.Errorf("Unable to locate boundary param in Content-Type header")
	}

	
	if mediatype == ctMultipartAltern {
		p := root.BreadthMatchFirst(func(p *Part) bool {
			return p.ContentType == ctTextPlain && p.Disposition != cdAttachment
		})
		if p != nil {
			e.Text = string(p.Content)
		}
	} else {
		
		parts := root.DepthMatchAll(func(p *Part) bool {
			return p.ContentType == ctTextPlain && p.Disposition != cdAttachment
		})
		for i, p := range parts {
			if i > 0 {
				e.Text += "\n--\n"
			}
			e.Text += string(p.Content)
		}
	}

	
	p := root.BreadthMatchFirst(matchHTMLBodyPart)
	if p != nil {
		e.HTML += string(p.Content)
	}

	
	e.Attachments = root.BreadthMatchAll(func(p *Part) bool {
		return p.Disposition == cdAttachment || p.ContentType == ctAppOctetStream
	})

	
	e.Inlines = root.BreadthMatchAll(func(p *Part) bool {
		return p.Disposition == cdInline && !strings.HasPrefix(p.ContentType, ctMultipartPrefix)
	})

	
	e.OtherParts = root.BreadthMatchAll(func(p *Part) bool {
		if strings.HasPrefix(p.ContentType, ctMultipartPrefix) {
			return false
		}
		if p.Disposition != "" {
			return false
		}
		if p.ContentType == ctAppOctetStream {
			return false
		}
		return p.ContentType != ctTextPlain && p.ContentType != ctTextHTML
	})

	return nil
}
func parseMultiPartBody ( root * Part , e * Envelope ) error { // Parse top-level multipart ctype := root . Header . Get ( hnContentType ) mediatype , params , _ , err := parseMediaType ( ctype ) if err != nil { return fmt . Errorf ( " " , err ) } if ! strings . HasPrefix ( mediatype , ctMultipartPrefix ) { return fmt . Errorf ( " " , mediatype ) } boundary := params [ hpBoundary ] if boundary == " " { return fmt . Errorf ( " " ) } // Locate text body if mediatype == ctMultipartAltern { p := root . BreadthMatchFirst ( func ( p * Part ) bool { return p . ContentType == ctTextPlain && p . Disposition != cdAttachment } ) if p != nil { e . Text = string ( p . Content ) } } else { // multipart is of a mixed type parts := root . DepthMatchAll ( func ( p * Part ) bool { return p . ContentType == ctTextPlain && p . Disposition != cdAttachment } ) for i , p := range parts { if i > 0 { e . Text += " \n \n " } e . Text += string ( p . Content ) } } // Locate HTML body p := root . BreadthMatchFirst ( matchHTMLBodyPart ) if p != nil { e . HTML += string ( p . Content ) } // Locate attachments e . Attachments = root . BreadthMatchAll ( func ( p * Part ) bool { return p . Disposition == cdAttachment || p . ContentType == ctAppOctetStream } ) // Locate inlines e . Inlines = root . BreadthMatchAll ( func ( p * Part ) bool { return p . Disposition == cdInline && ! strings . HasPrefix ( p . ContentType , ctMultipartPrefix ) } ) // Locate others parts not considered in attachments or inlines e . OtherParts = root . BreadthMatchAll ( func ( p * Part ) bool { if strings . HasPrefix ( p . ContentType , ctMultipartPrefix ) { return false } if p . Disposition != " " { return false } if p . ContentType == ctAppOctetStream { return false } return p . ContentType != ctTextPlain && p . ContentType != ctTextHTML } ) return nil }
// parseMultiPartBody parses a multipart message in root.  The result is placed in e.
parseMultiPartBody parses a multipart message in root . The result is placed in e .