102 lines
3.0 KiB
TypeScript
102 lines
3.0 KiB
TypeScript
export interface Folder {
|
|
name: string;
|
|
id: string;
|
|
totalCount: number;
|
|
unreadCount: number;
|
|
childFolderCount: number;
|
|
}
|
|
|
|
type SoapRequest = (body: string, soapAction: string) => Promise<any>;
|
|
|
|
export async function extractFolders(
|
|
soapRequest: SoapRequest,
|
|
parentFolderId: string,
|
|
recursive: boolean = false,
|
|
): Promise<Folder[]> {
|
|
const DISTINGUISHED_FOLDERS: Record<string, string> = {
|
|
inbox: "inbox",
|
|
"входящие": "inbox",
|
|
sent: "sentitems",
|
|
"отправленные": "sentitems",
|
|
drafts: "drafts",
|
|
"черновики": "drafts",
|
|
deleted: "deleteditems",
|
|
"удаленные": "deleteditems",
|
|
junk: "junkemail",
|
|
"нежелательная почта": "junkemail",
|
|
outbox: "outbox",
|
|
"исходящие": "outbox",
|
|
calendar: "calendar",
|
|
"календарь": "calendar",
|
|
};
|
|
|
|
function buildSoapEnvelope(body: string): string {
|
|
return `<?xml version="1.0" encoding="utf-8"?>
|
|
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"
|
|
xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages"
|
|
xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
|
|
<s:Body>
|
|
${body}
|
|
</s:Body>
|
|
</s:Envelope>`;
|
|
}
|
|
|
|
function extractResponseMessages(data: any): any[] {
|
|
const body = data?.Envelope?.Body;
|
|
if (!body) return [];
|
|
const firstKey = Object.keys(body).find((k) => k.endsWith("Response"));
|
|
if (!firstKey) return [];
|
|
const rm = body[firstKey]?.ResponseMessages;
|
|
if (!rm) return [];
|
|
const msgKey = Object.keys(rm).find((k) => k.endsWith("ResponseMessage"));
|
|
if (!msgKey) return [];
|
|
const msgs = rm[msgKey];
|
|
return Array.isArray(msgs) ? msgs : [msgs];
|
|
}
|
|
|
|
const traversal = recursive ? "Deep" : "Shallow";
|
|
const isDistinguished =
|
|
DISTINGUISHED_FOLDERS[parentFolderId.toLowerCase()] !== undefined
|
|
|| ["msgfolderroot"].includes(parentFolderId.toLowerCase());
|
|
|
|
const folderIdXml = isDistinguished
|
|
? `<t:DistinguishedFolderId Id="${parentFolderId}"/>`
|
|
: `<t:FolderId Id="${parentFolderId}"/>`;
|
|
|
|
const soap = buildSoapEnvelope(`\
|
|
<m:FindFolder Traversal="${traversal}">
|
|
<m:FolderShape>
|
|
<t:BaseShape>Default</t:BaseShape>
|
|
</m:FolderShape>
|
|
<m:ParentFolderIds>
|
|
${folderIdXml}
|
|
</m:ParentFolderIds>
|
|
<m:IndexedPageFolderView MaxEntriesReturned="200" Offset="0" BasePoint="Beginning"/>
|
|
</m:FindFolder>`);
|
|
|
|
const data = await soapRequest(
|
|
soap,
|
|
"http://schemas.microsoft.com/exchange/services/2006/messages/FindFolder",
|
|
);
|
|
|
|
const folders: Folder[] = [];
|
|
|
|
for (const msg of extractResponseMessages(data)) {
|
|
const folderList = msg?.RootFolder?.Folders?.Folder;
|
|
if (!folderList) continue;
|
|
const list = Array.isArray(folderList) ? folderList : [folderList];
|
|
|
|
for (const f of list) {
|
|
folders.push({
|
|
name: f.DisplayName ?? "Unknown",
|
|
id: f.FolderId?.["@_Id"] ?? "",
|
|
totalCount: f.TotalCount ?? 0,
|
|
unreadCount: f.UnreadCount ?? 0,
|
|
childFolderCount: f.ChildFolderCount ?? 0,
|
|
});
|
|
}
|
|
}
|
|
|
|
return folders;
|
|
}
|