MCPcopy Create free account
hub / github.com/Mnexa-AI/e2a / walkParts

Function walkParts

internal/mailparse/parse.go:128–184  ·  view source on GitHub ↗

walkParts returns the first text/plain, the first text/html rendered to text, and the first text/html decoded as-is (htmlRaw) found anywhere in the (possibly nested multipart) body.

(contentType, cte string, body io.Reader, depth int)

Source from the content-addressed store, hash-verified

126// and the first text/html decoded as-is (htmlRaw) found anywhere in the
127// (possibly nested multipart) body.
128func walkParts(contentType, cte string, body io.Reader, depth int) (plain, htmlText, htmlRaw string) {
129 mediaType, params, err := mime.ParseMediaType(contentType)
130 if err != nil {
131 // No/!invalid Content-Type → treat as text/plain.
132 return decode(body, cte), "", ""
133 }
134 switch {
135 case strings.HasPrefix(mediaType, "multipart/"):
136 if depth >= maxMIMEDepth {
137 return "", "", "" // bail on pathological nesting (see maxMIMEDepth)
138 }
139 boundary := params["boundary"]
140 if boundary == "" {
141 return "", "", ""
142 }
143 mr := multipart.NewReader(body, boundary)
144 for {
145 part, err := mr.NextPart()
146 if err != nil {
147 break
148 }
149 // Skip parts the sender flagged as attachments — they're files
150 // (fetched via the attachment endpoint), not the displayable body.
151 // Without this an attached .html file would surface as parsed.html.
152 if disp, _, derr := mime.ParseMediaType(part.Header.Get("Content-Disposition")); derr == nil && disp == "attachment" {
153 part.Close()
154 continue
155 }
156 p, h, hr := walkParts(part.Header.Get("Content-Type"), part.Header.Get("Content-Transfer-Encoding"), part, depth+1)
157 if plain == "" && p != "" {
158 plain = p
159 }
160 if htmlText == "" && h != "" {
161 htmlText = h
162 }
163 if htmlRaw == "" && hr != "" {
164 htmlRaw = hr
165 }
166 part.Close()
167 // Stop once both representations are in hand. Unlike the old
168 // text-only walk we can't stop at text/plain alone — the text/html
169 // sibling (typically later in a multipart/alternative) is the
170 // display body we still need.
171 if plain != "" && htmlRaw != "" {
172 break
173 }
174 }
175 return plain, htmlText, htmlRaw
176 case mediaType == "text/plain":
177 return decode(body, cte), "", ""
178 case mediaType == "text/html":
179 decoded := decode(body, cte)
180 return "", htmlToText(decoded), decoded
181 default:
182 return "", "", ""
183 }
184}
185

Callers 1

extractTextFunction · 0.85

Calls 4

decodeFunction · 0.85
htmlToTextFunction · 0.85
GetMethod · 0.65
CloseMethod · 0.45

Tested by

no test coverage detected