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

Function messageViewFromIdentity

internal/httpapi/messages.go:129–200  ·  view source on GitHub ↗
(m *identity.Message)

Source from the content-addressed store, hash-verified

127}
128
129func messageViewFromIdentity(m *identity.Message) MessageView {
130 v := MessageView{
131 MessageID: m.ID,
132 From: m.Sender,
133 To: orEmptyStrings(m.ToRecipients),
134 CC: orEmptyStrings(m.CC),
135 ReplyTo: orEmptyStrings(m.ReplyTo),
136 Recipient: m.Recipient,
137 Subject: m.Subject,
138 ConversationID: m.ConversationID,
139 Direction: m.Direction,
140 // `status` is the inbox read-state, identical to the summary view (B2);
141 // the outbound delivery rollup lives in `delivery_status`, the HITL
142 // lifecycle in `hitl_status`. (The store resolves m.DeliveryStatus to
143 // inbox_status for inbound and the rollup for outbound, so the detail
144 // view must read InboxStatus to agree with the summary.)
145 Status: m.InboxStatus,
146 Labels: orEmptyStrings(m.Labels),
147 CreatedAt: m.CreatedAt.UTC().Format(time.RFC3339),
148 AuthHeaders: m.AuthHeaders,
149 Auth: authVerdict(m.Auth),
150 RawMessage: m.RawMessage,
151 Flagged: m.Flagged,
152 FlagReason: m.FlagReason,
153 }
154 // Webhook delivery context + raw size — apply to both directions so the
155 // detail view stays a superset of the summary view (omitempty hides empties).
156 v.WebhookStatus = m.WebhookStatus
157 v.WebhookError = m.WebhookError
158 v.SizeBytes = m.SizeBytes
159 // Outbound delivery feedback (migration 031). On outbound rows
160 // identity.Message.DeliveryStatus carries the delivery rollup; on
161 // inbound rows it carries inbox_status, so these stay empty there.
162 if m.Direction == "outbound" {
163 v.DeliveryStatus = m.DeliveryStatus
164 v.DeliveryDetail = m.DeliveryDetail
165 v.SentAs = m.SentAs
166 // HITL lifecycle (status column) — outbound only, mirroring the summary
167 // view; on inbound rows `status` is not the HITL value (review F1).
168 v.HITLStatus = m.Status
169 }
170 // Parsed view (decision 9): derived from the raw message — any direction
171 // that carries one (inbound + sent outbound, whose draft body columns were
172 // scrubbed in favor of the sent MIME). Held outbound drafts have no
173 // raw_message and surface their body via `body` below instead.
174 if len(m.RawMessage) > 0 {
175 pv := mailparse.Parse(m.RawMessage, mailparse.DefaultMaxBytes)
176 v.Parsed = &MessageParsedView{Text: pv.Text, Truncated: pv.Truncated, HTML: pv.HTML}
177 }
178 // Attachment metadata (§6a #5): parsed from raw_message for ANY direction
179 // that has one (inbound + sent outbound). Always an array; the bytes are
180 // fetched via the attachment endpoint, never inlined here.
181 v.Attachments = []AttachmentMetaView{}
182 if len(m.RawMessage) > 0 {
183 for i, a := range mailparse.Attachments(m.RawMessage) {
184 v.Attachments = append(v.Attachments, AttachmentMetaView{
185 Index: i,
186 Filename: a.Filename,

Calls 4

ParseFunction · 0.92
AttachmentsFunction · 0.92
orEmptyStringsFunction · 0.85
authVerdictFunction · 0.85