import { htmlToText } from "./html_to_text.ts"; export interface Attachment { name: string; size: number; contentType: string; attachmentId: string; isInline: boolean; } export interface Email { subject: string; from: string; fromName: string; date: string; isRead: boolean; hasAttachments: boolean; hasLinks: boolean; itemId: string; size: number; isMeeting: boolean; itemType: string; to: string[]; cc: string[]; body: string; bodyType: string; attachments: Attachment[]; preview: string; location?: string; start?: string; end?: string; requiredAttendees?: string[]; optionalAttendees?: string[]; } export function extractEmail(item: any): Email { const itemType = item["@_xsi_type"] ?? item.__type ?? ""; const isMeeting = /MeetingRequest|MeetingResponse|MeetingCancellation|CalendarItem/i.test( itemType, ); const fromMailbox = item.From?.Mailbox ?? item.Organizer?.Mailbox ?? item.Sender?.Mailbox ?? {}; const email: Email = { subject: item.Subject ?? "(No subject)", from: fromMailbox.EmailAddress ?? "", fromName: fromMailbox.Name ?? "", date: item.DateTimeSent ?? item.DateTimeReceived ?? item.DateTimeCreated ?? "", isRead: item.IsRead === "true" || item.IsRead === true, hasAttachments: item.HasAttachments === "true" || item.HasAttachments === true, hasLinks: false, itemId: item.ItemId?.["@_Id"] ?? "", size: item.Size ? Number(item.Size) : 0, isMeeting, itemType: itemType || "Message", to: [], cc: [], body: "", bodyType: "Text", attachments: [], preview: item.Preview ?? "", }; if (item.DisplayTo) { email.to = item.DisplayTo.split(";").map((t: string) => t.trim()).filter( Boolean, ); } if (item.DisplayCc) { email.cc = item.DisplayCc.split(";").map((c: string) => c.trim()).filter( Boolean, ); } if (isMeeting) { email.location = item.Location ?? ""; email.start = item.Start ?? item.StartWallClock ?? item.ReminderDueBy ?? ""; email.end = item.End ?? item.EndWallClock ?? ""; } const bodyVal = item.Body?.Value ?? item.Body?.["#text"] ?? ""; const bodyType = item.Body?.["@_BodyType"] ?? item.Body?.BodyType ?? "Text"; if (bodyType === "HTML") { email.hasLinks = / { const name = r.Name ?? ""; const addr = r.EmailAddress ?? ""; return name && addr ? `${name} <${addr}>` : addr; }) .filter(Boolean); const ccRecipients = item.CcRecipients?.Mailbox ?? []; email.cc = (Array.isArray(ccRecipients) ? ccRecipients : [ccRecipients]) .map((r: any) => { const name = r.Name ?? ""; const addr = r.EmailAddress ?? ""; return name && addr ? `${name} <${addr}>` : addr; }) .filter(Boolean); const attachments = item.Attachments?.FileAttachment ?? []; const attList = Array.isArray(attachments) ? attachments : [attachments]; email.attachments = attList .filter((a: any) => a) .map((a: any) => ({ name: a.Name ?? "", size: a.Size ? Number(a.Size) : 0, contentType: a.ContentType ?? "", attachmentId: a.AttachmentId?.["@_Id"] ?? "", isInline: a.IsInline === "true" || a.IsInline === true, })); if (isMeeting) { email.location = item.Location ?? item.EnhancedLocation?.DisplayName ?? ""; email.start = item.Start ?? ""; email.end = item.End ?? ""; const reqAtt = item.RequiredAttendees?.Attendee ?? []; email.requiredAttendees = (Array.isArray(reqAtt) ? reqAtt : [reqAtt]) .map((a: any) => { const mb = a.Mailbox ?? {}; const name = mb.Name ?? ""; const addr = mb.EmailAddress ?? ""; return name && addr ? `${name} <${addr}>` : addr; }) .filter(Boolean); const optAtt = item.OptionalAttendees?.Attendee ?? []; email.optionalAttendees = (Array.isArray(optAtt) ? optAtt : [optAtt]) .map((a: any) => { const mb = a.Mailbox ?? {}; const name = mb.Name ?? ""; const addr = mb.EmailAddress ?? ""; return name && addr ? `${name} <${addr}>` : addr; }) .filter(Boolean); } return email; }