-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathews-connect.ts
145 lines (129 loc) · 3.8 KB
/
ews-connect.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
import * as ews from "ews-javascript-api";
export function writeError(error: string) {
process.stderr.write(`${error}\n`);
}
export function writeProgress(message: string) {
writeError(message);
}
export async function sleep(
{ ms }: { ms: number } = { ms: 1000 }
): Promise<void> {
new Promise((resolve) => setTimeout(resolve, ms));
}
export function getConfigFromEnvironmentVariable<T>(
name: string
): Readonly<T> | undefined {
const configRaw = process.env[name];
if (configRaw) {
try {
// Schema validation left to receiver
const config: T = JSON.parse(configRaw);
return config;
} catch (e) {}
}
return undefined;
}
export function withEwsConnection(
worker: (service: ews.ExchangeService) => Promise<void | number>
) {
interface ExchangeConfig {
username: string;
password: string;
serviceUrl: string;
}
const service = new ews.ExchangeService(ews.ExchangeVersion.Exchange2016);
const config =
getConfigFromEnvironmentVariable<ExchangeConfig>("EXCHANGE_CONFIG");
if (!config) {
writeError("Error: EXCHANGE_CONFIG environment variable must be set");
process.exit(4);
}
const username = config.username;
const password = config.password;
service.Credentials = new ews.WebCredentials(username, password);
service.TraceEnabled = true;
service.TraceFlags = ews.TraceFlags.All;
service.Url = new ews.Uri(config.serviceUrl);
worker(service).then(
(result) => {
writeProgress("Success!");
return result;
},
(e) => {
writeError(`Error: ${e.message}`);
if (e.faultString) {
writeError(`Fault: ${e.faultString.faultstring}`);
}
if (e.stack) {
writeError(e.stack.toString());
}
}
);
}
export async function findOrCreateContactGroup(
service: ews.ExchangeService,
name: string
) {
const rootFolder = ews.WellKnownFolderName.Contacts;
const filter = new ews.SearchFilter.SearchFilterCollection(
ews.LogicalOperator.And,
[
new ews.SearchFilter.IsEqualTo(ews.ContactGroupSchema.DisplayName, name),
new ews.SearchFilter.IsEqualTo(
ews.ContactGroupSchema.ItemClass,
"IPM.DistList"
),
]
);
const found = await service.FindItems(
rootFolder,
filter,
new ews.ItemView(2)
);
if (found.Items.length > 1) {
writeError(`Found more than one contact group named ${name}`);
return undefined;
} else if (found.Items.length === 1) {
return await ews.ContactGroup.Bind(service, found.Items[0].Id);
}
const createdItem = new ews.ContactGroup(service);
createdItem.DisplayName = name;
writeProgress(`Creating contact group ${name}`);
await createdItem.Save(rootFolder);
return createdItem;
}
export function collectionToArray<T extends ews.ComplexProperty>(
collection: ews.ComplexPropertyCollection<T>
): ReadonlyArray<T> {
const result = Array.from({ length: collection.Count }).map((n, i) =>
collection._getItem(i)
);
return result;
}
export type Identifier = {
id: ews.Folder["Id"];
displayName: ews.Folder["DisplayName"];
};
type IdentifiersFromNamesOptions = {
service: ews.ExchangeService;
displayNames: ReadonlyArray<string>;
};
/**
* Find folders and their ID based on just their display name. Use this to
* identify folders that are not part of {@link ews.WellKnownFolderName}.
*/
export const identifiersFromNames = async ({
service,
displayNames,
}: IdentifiersFromNamesOptions): Promise<Identifier[]> => {
const folderView = new ews.FolderView(1000);
folderView.Traversal = ews.FolderTraversal.Deep;
const results = await service.FindFolders(
ews.WellKnownFolderName.Root,
folderView
);
return results
.GetEnumerator()
.filter((folder) => displayNames.includes(folder.DisplayName))
.map((folder) => ({ id: folder.Id, displayName: folder.DisplayName }));
};