n8n-nodes-outlook-subscription 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1145 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OutlookSubscription = void 0;
4
+ const n8n_workflow_1 = require("n8n-workflow");
5
+ const graph_1 = require("../shared/graph");
6
+ class OutlookSubscription {
7
+ constructor() {
8
+ this.description = {
9
+ displayName: "Outlook Subscription",
10
+ name: "outlookSubscription",
11
+ icon: "file:outlookSubscription.svg",
12
+ group: ["transform"],
13
+ version: 1,
14
+ subtitle: '={{$parameter["resource"] + ": " + $parameter["operation"]}}',
15
+ description: "Manage Microsoft Graph Outlook subscriptions, messages, attachments, and users",
16
+ defaults: {
17
+ name: "Outlook Subscription",
18
+ },
19
+ inputs: ["main"],
20
+ outputs: ["main"],
21
+ credentials: [
22
+ {
23
+ name: "microsoftOutlookSubscriptionOAuth2Api",
24
+ required: true,
25
+ },
26
+ ],
27
+ properties: [
28
+ // ── Resource ──
29
+ {
30
+ displayName: "Resource",
31
+ name: "resource",
32
+ type: "options",
33
+ noDataExpression: true,
34
+ default: "subscription",
35
+ options: [
36
+ { name: "Attachment", value: "attachment" },
37
+ { name: "Message", value: "message" },
38
+ { name: "Subscription", value: "subscription" },
39
+ { name: "User", value: "user" },
40
+ ],
41
+ },
42
+ // ── Operations ──
43
+ {
44
+ displayName: "Operation",
45
+ name: "operation",
46
+ type: "options",
47
+ noDataExpression: true,
48
+ default: "create",
49
+ displayOptions: { show: { resource: ["subscription"] } },
50
+ options: [
51
+ { name: "Create", value: "create" },
52
+ { name: "Delete", value: "delete" },
53
+ { name: "List", value: "list" },
54
+ { name: "Renew", value: "renew" },
55
+ ],
56
+ },
57
+ {
58
+ displayName: "Operation",
59
+ name: "operation",
60
+ type: "options",
61
+ noDataExpression: true,
62
+ default: "get",
63
+ displayOptions: { show: { resource: ["message"] } },
64
+ options: [
65
+ { name: "Delete", value: "delete" },
66
+ { name: "Get", value: "get" },
67
+ { name: "List", value: "list" },
68
+ { name: "Move", value: "move" },
69
+ { name: "Reply", value: "reply" },
70
+ { name: "Reply All", value: "replyAll" },
71
+ { name: "Send", value: "send" },
72
+ { name: "Update", value: "update" },
73
+ ],
74
+ },
75
+ {
76
+ displayName: "Operation",
77
+ name: "operation",
78
+ type: "options",
79
+ noDataExpression: true,
80
+ default: "list",
81
+ displayOptions: { show: { resource: ["attachment"] } },
82
+ options: [
83
+ { name: "Download", value: "download" },
84
+ { name: "List", value: "list" },
85
+ ],
86
+ },
87
+ {
88
+ displayName: "Operation",
89
+ name: "operation",
90
+ type: "options",
91
+ noDataExpression: true,
92
+ default: "get",
93
+ displayOptions: { show: { resource: ["user"] } },
94
+ options: [{ name: "Get", value: "get" }],
95
+ },
96
+ // ── Mailbox (subscription create / message / attachment) ──
97
+ {
98
+ displayName: "Mailbox",
99
+ name: "mailboxMode",
100
+ type: "options",
101
+ default: "current",
102
+ displayOptions: { show: { resource: ["message", "attachment"] } },
103
+ options: [
104
+ { name: "Current Mailbox", value: "current" },
105
+ { name: "Other Mailbox", value: "other" },
106
+ ],
107
+ },
108
+ {
109
+ displayName: "Mailbox",
110
+ name: "mailboxMode",
111
+ type: "options",
112
+ default: "current",
113
+ displayOptions: {
114
+ show: { resource: ["subscription"], operation: ["create"] },
115
+ },
116
+ options: [
117
+ { name: "Current Mailbox", value: "current" },
118
+ { name: "Other Mailbox", value: "other" },
119
+ ],
120
+ },
121
+ {
122
+ displayName: "Other Mailbox Email",
123
+ name: "otherMailboxEmail",
124
+ type: "string",
125
+ default: "",
126
+ displayOptions: {
127
+ show: { resource: ["message", "attachment"], mailboxMode: ["other"] },
128
+ },
129
+ placeholder: "shared@example.com",
130
+ },
131
+ {
132
+ displayName: "Other Mailbox Email",
133
+ name: "otherMailboxEmail",
134
+ type: "string",
135
+ default: "",
136
+ displayOptions: {
137
+ show: {
138
+ resource: ["subscription"],
139
+ operation: ["create"],
140
+ mailboxMode: ["other"],
141
+ },
142
+ },
143
+ placeholder: "shared@example.com",
144
+ },
145
+ // ── Subscription Create ──
146
+ {
147
+ displayName: "Entity",
148
+ name: "entity",
149
+ type: "options",
150
+ default: "message",
151
+ displayOptions: {
152
+ show: { resource: ["subscription"], operation: ["create"] },
153
+ },
154
+ options: [
155
+ { name: "Message", value: "message" },
156
+ { name: "Folder", value: "folder" },
157
+ ],
158
+ },
159
+ {
160
+ displayName: "Folder Source",
161
+ name: "folderSource",
162
+ type: "options",
163
+ default: "list",
164
+ displayOptions: {
165
+ show: { resource: ["subscription"], operation: ["create"] },
166
+ },
167
+ options: [
168
+ { name: "Folder Dropdown", value: "list" },
169
+ { name: "Manual Folder ID", value: "manual" },
170
+ ],
171
+ },
172
+ {
173
+ displayName: "Folder",
174
+ name: "folderId",
175
+ type: "options",
176
+ typeOptions: {
177
+ loadOptionsMethod: "getMailFolders",
178
+ },
179
+ default: "",
180
+ displayOptions: {
181
+ show: {
182
+ resource: ["subscription"],
183
+ operation: ["create"],
184
+ folderSource: ["list"],
185
+ },
186
+ },
187
+ description: "Optional folder selection. Leave empty to target the whole mailbox root for the chosen entity",
188
+ },
189
+ {
190
+ displayName: "Manual Folder ID",
191
+ name: "folderIdManual",
192
+ type: "string",
193
+ default: "",
194
+ displayOptions: {
195
+ show: {
196
+ resource: ["subscription"],
197
+ operation: ["create"],
198
+ folderSource: ["manual"],
199
+ },
200
+ },
201
+ placeholder: "AAMkAG...=",
202
+ },
203
+ {
204
+ displayName: "Subscribe Subfolders",
205
+ name: "includeSubfolders",
206
+ type: "boolean",
207
+ default: false,
208
+ displayOptions: {
209
+ show: { resource: ["subscription"], operation: ["create"] },
210
+ },
211
+ description: "Whether to expand the selected folder into one subscription per descendant folder",
212
+ },
213
+ {
214
+ displayName: "Change Types",
215
+ name: "changeTypes",
216
+ type: "multiOptions",
217
+ default: ["created", "updated"],
218
+ displayOptions: {
219
+ show: { resource: ["subscription"], operation: ["create"] },
220
+ },
221
+ options: [
222
+ { name: "Created", value: "created" },
223
+ { name: "Updated", value: "updated" },
224
+ { name: "Deleted", value: "deleted" },
225
+ ],
226
+ },
227
+ {
228
+ displayName: "Notification URL",
229
+ name: "notificationUrl",
230
+ type: "string",
231
+ default: "",
232
+ required: true,
233
+ displayOptions: {
234
+ show: { resource: ["subscription"], operation: ["create"] },
235
+ },
236
+ placeholder: "https://example.com/webhooks/outlook",
237
+ description: "Webhook URL that will receive notifications. Copy this from the Outlook Subscription Trigger node.",
238
+ },
239
+ {
240
+ displayName: "Client State",
241
+ name: "clientState",
242
+ type: "string",
243
+ default: "",
244
+ displayOptions: {
245
+ show: { resource: ["subscription"], operation: ["create"] },
246
+ },
247
+ description: "Optional shared secret used later to verify notifications",
248
+ },
249
+ {
250
+ displayName: "Lifetime Minutes",
251
+ name: "lifetimeMinutes",
252
+ type: "number",
253
+ default: 4230,
254
+ typeOptions: {
255
+ minValue: 45,
256
+ },
257
+ displayOptions: {
258
+ show: {
259
+ resource: ["subscription"],
260
+ operation: ["create", "renew"],
261
+ },
262
+ },
263
+ },
264
+ {
265
+ displayName: "Auto Renew",
266
+ name: "autoRenew",
267
+ type: "boolean",
268
+ default: false,
269
+ displayOptions: {
270
+ show: { resource: ["subscription"], operation: ["create"] },
271
+ },
272
+ description: "Whether to include a lifecycle notification URL so an external receiver can renew the subscription",
273
+ },
274
+ {
275
+ displayName: "Lifecycle Notification URL",
276
+ name: "lifecycleNotificationUrl",
277
+ type: "string",
278
+ default: "",
279
+ displayOptions: {
280
+ show: {
281
+ resource: ["subscription"],
282
+ operation: ["create"],
283
+ autoRenew: [true],
284
+ },
285
+ },
286
+ placeholder: "https://example.com/webhooks/outlook-lifecycle",
287
+ },
288
+ // ── Subscription Delete / Renew ──
289
+ {
290
+ displayName: "Subscription ID",
291
+ name: "subscriptionId",
292
+ type: "string",
293
+ default: "",
294
+ required: true,
295
+ displayOptions: {
296
+ show: {
297
+ resource: ["subscription"],
298
+ operation: ["delete", "renew"],
299
+ },
300
+ },
301
+ },
302
+ // ── Message ID (message / attachment) ──
303
+ // For attachment resource: all operations need the message ID
304
+ {
305
+ displayName: "Message ID",
306
+ name: "messageId",
307
+ type: "string",
308
+ default: "",
309
+ required: true,
310
+ displayOptions: { show: { resource: ["attachment"] } },
311
+ placeholder: "AAMkAG...=",
312
+ },
313
+ // For message resource: only ops that act on a specific message
314
+ {
315
+ displayName: "Message ID",
316
+ name: "messageId",
317
+ type: "string",
318
+ default: "",
319
+ required: true,
320
+ displayOptions: {
321
+ show: {
322
+ resource: ["message"],
323
+ operation: ["delete", "get", "move", "reply", "replyAll", "update"],
324
+ },
325
+ },
326
+ placeholder: "AAMkAG...=",
327
+ },
328
+ // ── Attachment ID (download) ──
329
+ {
330
+ displayName: "Attachment ID",
331
+ name: "attachmentId",
332
+ type: "string",
333
+ default: "",
334
+ required: true,
335
+ displayOptions: {
336
+ show: { resource: ["attachment"], operation: ["download"] },
337
+ },
338
+ placeholder: "AAMkAG...=",
339
+ },
340
+ // ── Message Get: Query Options ──
341
+ {
342
+ displayName: "$expand",
343
+ name: "expand",
344
+ type: "string",
345
+ default: "",
346
+ typeOptions: { rows: 3 },
347
+ displayOptions: {
348
+ show: { resource: ["message"], operation: ["get"] },
349
+ },
350
+ placeholder: "singleValueExtendedProperties($filter=id eq 'String {00020329-0000-0000-C000-000000000046} Name contentCheckSum')",
351
+ description: "Expand related entities (e.g. extended properties)",
352
+ },
353
+ {
354
+ displayName: "$select",
355
+ name: "select",
356
+ type: "multiOptions",
357
+ default: [],
358
+ displayOptions: {
359
+ show: { resource: ["message"], operation: ["get"] },
360
+ },
361
+ options: [
362
+ { name: "BccRecipients", value: "bccRecipients" },
363
+ { name: "Body", value: "body" },
364
+ { name: "BodyPreview", value: "bodyPreview" },
365
+ { name: "Categories", value: "categories" },
366
+ { name: "CcRecipients", value: "ccRecipients" },
367
+ { name: "ChangeKey", value: "changeKey" },
368
+ { name: "ConversationId", value: "conversationId" },
369
+ { name: "CreatedDateTime", value: "createdDateTime" },
370
+ { name: "Flag", value: "flag" },
371
+ { name: "From", value: "from" },
372
+ { name: "HasAttachments", value: "hasAttachments" },
373
+ { name: "ID", value: "id" },
374
+ { name: "Importance", value: "importance" },
375
+ { name: "InternetMessageHeaders", value: "internetMessageHeaders" },
376
+ { name: "InternetMessageId", value: "internetMessageId" },
377
+ {
378
+ name: "IsDeliveryReceiptRequested",
379
+ value: "isDeliveryReceiptRequested",
380
+ },
381
+ { name: "IsDraft", value: "isDraft" },
382
+ { name: "IsRead", value: "isRead" },
383
+ { name: "IsReadReceiptRequested", value: "isReadReceiptRequested" },
384
+ { name: "LastModifiedDateTime", value: "lastModifiedDateTime" },
385
+ { name: "ParentFolderId", value: "parentFolderId" },
386
+ { name: "ReceivedDateTime", value: "receivedDateTime" },
387
+ { name: "ReplyTo", value: "replyTo" },
388
+ { name: "Sender", value: "sender" },
389
+ { name: "SentDateTime", value: "sentDateTime" },
390
+ { name: "Subject", value: "subject" },
391
+ { name: "ToRecipients", value: "toRecipients" },
392
+ { name: "WebLink", value: "webLink" },
393
+ ],
394
+ description: "Fields to return. Leave empty to return all fields. In expression mode, enter field names separated by commas.",
395
+ },
396
+ // ── Message Update: Fields ──
397
+ {
398
+ displayName: "Flag Status",
399
+ name: "flagStatus",
400
+ type: "options",
401
+ default: "none",
402
+ displayOptions: {
403
+ show: { resource: ["message"], operation: ["update"] },
404
+ },
405
+ options: [
406
+ { name: "Don't Change", value: "none" },
407
+ { name: "Flagged", value: "flagged" },
408
+ { name: "Complete", value: "complete" },
409
+ { name: "Not Flagged", value: "notFlagged" },
410
+ ],
411
+ },
412
+ {
413
+ displayName: "Extended Properties",
414
+ name: "extendedProperties",
415
+ type: "fixedCollection",
416
+ typeOptions: { multipleValues: true },
417
+ default: {},
418
+ displayOptions: {
419
+ show: { resource: ["message"], operation: ["update"] },
420
+ },
421
+ options: [
422
+ {
423
+ displayName: "Property",
424
+ name: "property",
425
+ values: [
426
+ {
427
+ displayName: "Property ID",
428
+ name: "id",
429
+ type: "string",
430
+ default: "",
431
+ placeholder: "String {00020329-0000-0000-C000-000000000046} Name contentCheckSum",
432
+ },
433
+ {
434
+ displayName: "Value",
435
+ name: "value",
436
+ type: "string",
437
+ default: "",
438
+ },
439
+ ],
440
+ },
441
+ ],
442
+ description: "Single-value extended properties to set on the message",
443
+ },
444
+ {
445
+ displayName: "If-Match ETag",
446
+ name: "ifMatchETag",
447
+ type: "string",
448
+ default: "",
449
+ displayOptions: {
450
+ show: { resource: ["message"], operation: ["update"] },
451
+ },
452
+ placeholder: 'W/"CQAAABYAAAB..."',
453
+ description: 'Optimistic concurrency: only update if the server-side message state matches. Use the @odata.etag value from the Get response, or format the changeKey as W/"<changeKey>"',
454
+ },
455
+ {
456
+ displayName: "Additional Body (JSON)",
457
+ name: "additionalBody",
458
+ type: "json",
459
+ default: "{}",
460
+ displayOptions: {
461
+ show: { resource: ["message"], operation: ["update"] },
462
+ },
463
+ description: "Additional fields to include in the PATCH body, merged with the fields above",
464
+ },
465
+ // ── Message List ──
466
+ {
467
+ displayName: "Folder ID",
468
+ name: "listFolderId",
469
+ type: "string",
470
+ default: "",
471
+ displayOptions: {
472
+ show: { resource: ["message"], operation: ["list"] },
473
+ },
474
+ placeholder: "AAMkAG...=",
475
+ description: "Restrict results to a specific folder. Leave empty to query all mailbox messages.",
476
+ },
477
+ {
478
+ displayName: "Return All",
479
+ name: "returnAll",
480
+ type: "boolean",
481
+ default: false,
482
+ displayOptions: {
483
+ show: { resource: ["message"], operation: ["list"] },
484
+ },
485
+ description: "Whether to return all pages of results by following @odata.nextLink",
486
+ },
487
+ {
488
+ displayName: "Limit",
489
+ name: "limit",
490
+ type: "number",
491
+ default: 25,
492
+ typeOptions: { minValue: 1, maxValue: 1000 },
493
+ displayOptions: {
494
+ show: {
495
+ resource: ["message"],
496
+ operation: ["list"],
497
+ returnAll: [false],
498
+ },
499
+ },
500
+ description: "Maximum number of messages to return",
501
+ },
502
+ {
503
+ displayName: "Filter",
504
+ name: "filter",
505
+ type: "string",
506
+ default: "",
507
+ displayOptions: {
508
+ show: { resource: ["message"], operation: ["list"] },
509
+ },
510
+ placeholder: "isRead eq false",
511
+ description: "OData $filter expression to restrict results",
512
+ },
513
+ {
514
+ displayName: "Order By",
515
+ name: "orderBy",
516
+ type: "options",
517
+ default: "receivedDateTime desc",
518
+ displayOptions: {
519
+ show: { resource: ["message"], operation: ["list"] },
520
+ },
521
+ options: [
522
+ { name: "Received (Newest First)", value: "receivedDateTime desc" },
523
+ { name: "Received (Oldest First)", value: "receivedDateTime asc" },
524
+ { name: "Sent (Newest First)", value: "sentDateTime desc" },
525
+ {
526
+ name: "Last Modified (Newest First)",
527
+ value: "lastModifiedDateTime desc",
528
+ },
529
+ ],
530
+ },
531
+ {
532
+ displayName: "Select Fields",
533
+ name: "listSelect",
534
+ type: "multiOptions",
535
+ default: [],
536
+ displayOptions: {
537
+ show: { resource: ["message"], operation: ["list"] },
538
+ },
539
+ options: [
540
+ { name: "BccRecipients", value: "bccRecipients" },
541
+ { name: "Body", value: "body" },
542
+ { name: "BodyPreview", value: "bodyPreview" },
543
+ { name: "Categories", value: "categories" },
544
+ { name: "CcRecipients", value: "ccRecipients" },
545
+ { name: "ChangeKey", value: "changeKey" },
546
+ { name: "ConversationId", value: "conversationId" },
547
+ { name: "CreatedDateTime", value: "createdDateTime" },
548
+ { name: "Flag", value: "flag" },
549
+ { name: "From", value: "from" },
550
+ { name: "HasAttachments", value: "hasAttachments" },
551
+ { name: "ID", value: "id" },
552
+ { name: "Importance", value: "importance" },
553
+ { name: "InternetMessageHeaders", value: "internetMessageHeaders" },
554
+ { name: "InternetMessageId", value: "internetMessageId" },
555
+ { name: "IsDraft", value: "isDraft" },
556
+ { name: "IsRead", value: "isRead" },
557
+ { name: "LastModifiedDateTime", value: "lastModifiedDateTime" },
558
+ { name: "ParentFolderId", value: "parentFolderId" },
559
+ { name: "ReceivedDateTime", value: "receivedDateTime" },
560
+ { name: "ReplyTo", value: "replyTo" },
561
+ { name: "Sender", value: "sender" },
562
+ { name: "SentDateTime", value: "sentDateTime" },
563
+ { name: "Subject", value: "subject" },
564
+ { name: "ToRecipients", value: "toRecipients" },
565
+ { name: "WebLink", value: "webLink" },
566
+ ],
567
+ description: "Fields to return. Leave empty to return all default fields.",
568
+ },
569
+ // ── Message Move ──
570
+ {
571
+ displayName: "Specify Destination Folder As",
572
+ name: "destinationFolderSource",
573
+ type: "options",
574
+ default: "list",
575
+ displayOptions: {
576
+ show: { resource: ["message"], operation: ["move"] },
577
+ },
578
+ options: [
579
+ {
580
+ name: "Select from List",
581
+ value: "list",
582
+ description: "Pick a folder from the dropdown",
583
+ },
584
+ {
585
+ name: "Enter Folder ID",
586
+ value: "manual",
587
+ description: "Type the folder ID directly",
588
+ },
589
+ {
590
+ name: "Create New Folder",
591
+ value: "create",
592
+ description: "Create a new folder and move the message into it",
593
+ },
594
+ ],
595
+ },
596
+ {
597
+ displayName: "Destination Folder",
598
+ name: "destinationFolderId",
599
+ type: "options",
600
+ typeOptions: { loadOptionsMethod: "getMailFolders" },
601
+ default: "",
602
+ displayOptions: {
603
+ show: {
604
+ resource: ["message"],
605
+ operation: ["move"],
606
+ destinationFolderSource: ["list"],
607
+ },
608
+ },
609
+ description: "The folder to move the message into",
610
+ },
611
+ {
612
+ displayName: "Destination Folder ID",
613
+ name: "destinationFolderIdManual",
614
+ type: "string",
615
+ default: "",
616
+ displayOptions: {
617
+ show: {
618
+ resource: ["message"],
619
+ operation: ["move"],
620
+ destinationFolderSource: ["manual"],
621
+ },
622
+ },
623
+ placeholder: "AAMkAG...=",
624
+ },
625
+ {
626
+ displayName: "New Folder Name",
627
+ name: "newFolderName",
628
+ type: "string",
629
+ default: "",
630
+ required: true,
631
+ displayOptions: {
632
+ show: {
633
+ resource: ["message"],
634
+ operation: ["move"],
635
+ destinationFolderSource: ["create"],
636
+ },
637
+ },
638
+ placeholder: "Processed Invoices",
639
+ description: "Name of the new top-level mail folder to create",
640
+ },
641
+ // ── Message Send ──
642
+ {
643
+ displayName: "To",
644
+ name: "sendTo",
645
+ type: "string",
646
+ default: "",
647
+ required: true,
648
+ displayOptions: {
649
+ show: { resource: ["message"], operation: ["send"] },
650
+ },
651
+ placeholder: "alice@example.com, bob@example.com",
652
+ description: "Comma-separated list of recipient email addresses",
653
+ },
654
+ {
655
+ displayName: "Subject",
656
+ name: "sendSubject",
657
+ type: "string",
658
+ default: "",
659
+ required: true,
660
+ displayOptions: {
661
+ show: { resource: ["message"], operation: ["send"] },
662
+ },
663
+ },
664
+ {
665
+ displayName: "Body",
666
+ name: "sendBody",
667
+ type: "string",
668
+ default: "",
669
+ required: true,
670
+ typeOptions: { rows: 5 },
671
+ displayOptions: {
672
+ show: { resource: ["message"], operation: ["send"] },
673
+ },
674
+ },
675
+ {
676
+ displayName: "Body Type",
677
+ name: "sendBodyType",
678
+ type: "options",
679
+ default: "html",
680
+ displayOptions: {
681
+ show: { resource: ["message"], operation: ["send"] },
682
+ },
683
+ options: [
684
+ { name: "HTML", value: "html" },
685
+ { name: "Plain Text", value: "text" },
686
+ ],
687
+ },
688
+ {
689
+ displayName: "CC",
690
+ name: "sendCc",
691
+ type: "string",
692
+ default: "",
693
+ displayOptions: {
694
+ show: { resource: ["message"], operation: ["send"] },
695
+ },
696
+ placeholder: "cc@example.com",
697
+ description: "Comma-separated CC recipients",
698
+ },
699
+ {
700
+ displayName: "BCC",
701
+ name: "sendBcc",
702
+ type: "string",
703
+ default: "",
704
+ displayOptions: {
705
+ show: { resource: ["message"], operation: ["send"] },
706
+ },
707
+ placeholder: "bcc@example.com",
708
+ description: "Comma-separated BCC recipients",
709
+ },
710
+ {
711
+ displayName: "Save to Sent Items",
712
+ name: "saveToSentItems",
713
+ type: "boolean",
714
+ default: true,
715
+ displayOptions: {
716
+ show: { resource: ["message"], operation: ["send"] },
717
+ },
718
+ },
719
+ {
720
+ displayName: "Add Attachment",
721
+ name: "addAttachment",
722
+ type: "boolean",
723
+ default: false,
724
+ displayOptions: {
725
+ show: { resource: ["message"], operation: ["send"] },
726
+ },
727
+ description: "Whether to attach a binary file from the incoming item to the email",
728
+ },
729
+ {
730
+ displayName: "Binary Field Name",
731
+ name: "binaryFieldName",
732
+ type: "string",
733
+ default: "data",
734
+ displayOptions: {
735
+ show: {
736
+ resource: ["message"],
737
+ operation: ["send"],
738
+ addAttachment: [true],
739
+ },
740
+ },
741
+ placeholder: "data",
742
+ description: "Name of the binary property on the incoming item that holds the file to attach",
743
+ },
744
+ {
745
+ displayName: "Comment",
746
+ name: "replyComment",
747
+ type: "string",
748
+ default: "",
749
+ required: true,
750
+ typeOptions: { rows: 5 },
751
+ displayOptions: {
752
+ show: { resource: ["message"], operation: ["reply", "replyAll"] },
753
+ },
754
+ description: "The reply body content",
755
+ },
756
+ {
757
+ displayName: "Body Type",
758
+ name: "replyBodyType",
759
+ type: "options",
760
+ default: "html",
761
+ displayOptions: {
762
+ show: { resource: ["message"], operation: ["reply", "replyAll"] },
763
+ },
764
+ options: [
765
+ { name: "HTML", value: "html" },
766
+ { name: "Plain Text", value: "text" },
767
+ ],
768
+ },
769
+ // ── User Get ──
770
+ {
771
+ displayName: "User ID",
772
+ name: "userId",
773
+ type: "string",
774
+ default: "",
775
+ required: true,
776
+ displayOptions: {
777
+ show: { resource: ["user"], operation: ["get"] },
778
+ },
779
+ placeholder: "14e15f65-0b6d-40f8-94e0-89efb0c19654",
780
+ description: "User ID or User Principal Name (UPN)",
781
+ },
782
+ {
783
+ displayName: "Select Fields",
784
+ name: "userSelectFields",
785
+ type: "multiOptions",
786
+ default: [],
787
+ displayOptions: {
788
+ show: { resource: ["user"], operation: ["get"] },
789
+ },
790
+ options: [
791
+ { name: "Account Enabled", value: "accountEnabled" },
792
+ { name: "Business Phones", value: "businessPhones" },
793
+ { name: "City", value: "city" },
794
+ { name: "Company Name", value: "companyName" },
795
+ { name: "Country", value: "country" },
796
+ { name: "Department", value: "department" },
797
+ { name: "Display Name", value: "displayName" },
798
+ { name: "Given Name", value: "givenName" },
799
+ { name: "ID", value: "id" },
800
+ { name: "Job Title", value: "jobTitle" },
801
+ { name: "Mail", value: "mail" },
802
+ { name: "Mail Nickname", value: "mailNickname" },
803
+ { name: "Mobile Phone", value: "mobilePhone" },
804
+ { name: "Office Location", value: "officeLocation" },
805
+ { name: "Preferred Language", value: "preferredLanguage" },
806
+ { name: "Surname", value: "surname" },
807
+ { name: "User Principal Name", value: "userPrincipalName" },
808
+ ],
809
+ description: "Fields to return. Leave empty to return all fields. In expression mode, enter field names separated by commas.",
810
+ },
811
+ ],
812
+ };
813
+ this.methods = {
814
+ loadOptions: {
815
+ async getMailFolders() {
816
+ return await graph_1.loadFolderOptions.call(this);
817
+ },
818
+ },
819
+ };
820
+ }
821
+ async execute() {
822
+ const items = this.getInputData();
823
+ const returnData = [];
824
+ for (let itemIndex = 0; itemIndex < items.length; itemIndex++) {
825
+ try {
826
+ const resource = this.getNodeParameter("resource", itemIndex);
827
+ const operation = this.getNodeParameter("operation", itemIndex);
828
+ // ── SUBSCRIPTION ──
829
+ if (resource === "subscription") {
830
+ if (operation === "list") {
831
+ const subscriptions = await graph_1.listSubscriptions.call(this);
832
+ returnData.push(...this.helpers.returnJsonArray(subscriptions));
833
+ continue;
834
+ }
835
+ if (operation === "delete") {
836
+ const subscriptionId = this.getNodeParameter("subscriptionId", itemIndex);
837
+ await graph_1.deleteSubscription.call(this, subscriptionId);
838
+ returnData.push({
839
+ json: {
840
+ success: true,
841
+ subscriptionId,
842
+ operation: "delete",
843
+ },
844
+ });
845
+ continue;
846
+ }
847
+ if (operation === "renew") {
848
+ const subscriptionId = this.getNodeParameter("subscriptionId", itemIndex);
849
+ const lifetimeMinutes = (0, graph_1.clampLifetimeMinutes)(this.getNodeParameter("lifetimeMinutes", itemIndex));
850
+ const renewed = await graph_1.renewSubscription.call(this, subscriptionId, lifetimeMinutes);
851
+ returnData.push({
852
+ json: {
853
+ operation: "renew",
854
+ subscription: renewed,
855
+ },
856
+ });
857
+ continue;
858
+ }
859
+ // operation === "create"
860
+ const mailboxMode = this.getNodeParameter("mailboxMode", itemIndex);
861
+ const otherMailboxEmail = this.getNodeParameter("otherMailboxEmail", itemIndex, "");
862
+ const entity = this.getNodeParameter("entity", itemIndex);
863
+ const folderSource = this.getNodeParameter("folderSource", itemIndex);
864
+ const folderIdList = this.getNodeParameter("folderId", itemIndex, "");
865
+ const folderIdManual = this.getNodeParameter("folderIdManual", itemIndex, "");
866
+ const folderId = folderSource === "manual" ? folderIdManual : folderIdList;
867
+ const includeSubfolders = this.getNodeParameter("includeSubfolders", itemIndex);
868
+ const notificationUrl = this.getNodeParameter("notificationUrl", itemIndex);
869
+ const changeTypes = this.getNodeParameter("changeTypes", itemIndex);
870
+ const changeType = (0, graph_1.normalizeChangeTypes)(changeTypes);
871
+ const lifetimeMinutes = (0, graph_1.clampLifetimeMinutes)(this.getNodeParameter("lifetimeMinutes", itemIndex));
872
+ const autoRenew = this.getNodeParameter("autoRenew", itemIndex);
873
+ const lifecycleNotificationUrl = this.getNodeParameter("lifecycleNotificationUrl", itemIndex, "");
874
+ const clientState = (0, graph_1.buildClientState)(this.getNodeParameter("clientState", itemIndex, ""));
875
+ const targets = await graph_1.buildSubscriptionTargets.call(this, {
876
+ mailboxMode,
877
+ otherMailboxEmail,
878
+ entity,
879
+ folderId,
880
+ includeSubfolders,
881
+ });
882
+ const existingSubscriptions = await graph_1.listSubscriptions.call(this);
883
+ for (const target of targets) {
884
+ const duplicates = (0, graph_1.findDuplicateSubscriptions)(existingSubscriptions, target, changeType, notificationUrl);
885
+ if (duplicates.length > 0) {
886
+ returnData.push({
887
+ json: {
888
+ operation: "create",
889
+ status: "skipped_duplicate",
890
+ resource: target,
891
+ changeType,
892
+ notificationUrl,
893
+ existing: duplicates,
894
+ autoRenew,
895
+ lifetimeMinutes,
896
+ },
897
+ });
898
+ continue;
899
+ }
900
+ const created = await graph_1.createSubscription.call(this, {
901
+ changeType,
902
+ notificationUrl,
903
+ clientState,
904
+ expirationDateTime: (0, graph_1.buildExpirationDateTime)(lifetimeMinutes),
905
+ resource: target,
906
+ latestSupportedTlsVersion: "v1_2",
907
+ ...(autoRenew && lifecycleNotificationUrl
908
+ ? { lifecycleNotificationUrl }
909
+ : {}),
910
+ });
911
+ returnData.push({
912
+ json: {
913
+ operation: "create",
914
+ status: "created",
915
+ resource: target,
916
+ changeType,
917
+ notificationUrl,
918
+ autoRenew,
919
+ lifetimeMinutes,
920
+ subscription: created,
921
+ },
922
+ });
923
+ }
924
+ continue;
925
+ }
926
+ // ── MESSAGE ──
927
+ if (resource === "message") {
928
+ const mailboxMode = this.getNodeParameter("mailboxMode", itemIndex);
929
+ const otherMailboxEmail = this.getNodeParameter("otherMailboxEmail", itemIndex, "");
930
+ const config = { mailboxMode, otherMailboxEmail };
931
+ // ── list ──
932
+ if (operation === "list") {
933
+ const listFolderId = this.getNodeParameter("listFolderId", itemIndex, "").trim();
934
+ const returnAll = this.getNodeParameter("returnAll", itemIndex);
935
+ const limit = this.getNodeParameter("limit", itemIndex, 25);
936
+ const filter = this.getNodeParameter("filter", itemIndex, "").trim();
937
+ const orderBy = this.getNodeParameter("orderBy", itemIndex, "receivedDateTime desc");
938
+ const listSelectRaw = this.getNodeParameter("listSelect", itemIndex, []);
939
+ const listSelectFields = Array.isArray(listSelectRaw)
940
+ ? listSelectRaw.join(",")
941
+ : listSelectRaw
942
+ .split(",")
943
+ .map((s) => s.trim())
944
+ .filter(Boolean)
945
+ .join(",");
946
+ const qs = { $orderby: orderBy };
947
+ if (!returnAll)
948
+ qs.$top = Math.min(limit, 1000);
949
+ if (filter)
950
+ qs.$filter = filter;
951
+ if (listSelectFields)
952
+ qs.$select = listSelectFields;
953
+ const messages = await graph_1.listMessages.call(this, config, listFolderId || undefined, qs, returnAll);
954
+ returnData.push(...this.helpers.returnJsonArray(messages));
955
+ continue;
956
+ }
957
+ // ── send ──
958
+ if (operation === "send") {
959
+ const sendTo = this.getNodeParameter("sendTo", itemIndex);
960
+ const sendSubject = this.getNodeParameter("sendSubject", itemIndex);
961
+ const sendBody = this.getNodeParameter("sendBody", itemIndex);
962
+ const sendBodyType = this.getNodeParameter("sendBodyType", itemIndex, "html");
963
+ const sendCc = this.getNodeParameter("sendCc", itemIndex, "").trim();
964
+ const sendBcc = this.getNodeParameter("sendBcc", itemIndex, "").trim();
965
+ const saveToSentItems = this.getNodeParameter("saveToSentItems", itemIndex, true);
966
+ const addAttachment = this.getNodeParameter("addAttachment", itemIndex, false);
967
+ const attachments = [];
968
+ if (addAttachment) {
969
+ const binaryFieldName = this.getNodeParameter("binaryFieldName", itemIndex, "data").trim();
970
+ const binaryData = this.helpers.assertBinaryData(itemIndex, binaryFieldName);
971
+ const buffer = await this.helpers.getBinaryDataBuffer(itemIndex, binaryFieldName);
972
+ attachments.push({
973
+ name: binaryData.fileName || binaryFieldName,
974
+ contentType: binaryData.mimeType || "application/octet-stream",
975
+ contentBytes: buffer.toString("base64"),
976
+ });
977
+ }
978
+ await graph_1.sendMail.call(this, config, {
979
+ to: sendTo,
980
+ subject: sendSubject,
981
+ body: sendBody,
982
+ bodyType: sendBodyType,
983
+ cc: sendCc || undefined,
984
+ bcc: sendBcc || undefined,
985
+ saveToSentItems,
986
+ attachments: attachments.length > 0 ? attachments : undefined,
987
+ });
988
+ returnData.push({ json: { success: true, operation: "send" } });
989
+ continue;
990
+ }
991
+ // All remaining message operations require a messageId
992
+ const messageId = this.getNodeParameter("messageId", itemIndex);
993
+ // ── delete ──
994
+ if (operation === "delete") {
995
+ await graph_1.deleteMessage.call(this, config, messageId);
996
+ returnData.push({
997
+ json: { success: true, operation: "delete", messageId },
998
+ });
999
+ continue;
1000
+ }
1001
+ // ── move ──
1002
+ if (operation === "move") {
1003
+ const destinationFolderSource = this.getNodeParameter("destinationFolderSource", itemIndex, "list");
1004
+ let destinationId;
1005
+ if (destinationFolderSource === "create") {
1006
+ const newFolderName = this.getNodeParameter("newFolderName", itemIndex, "").trim();
1007
+ const created = await graph_1.createMailFolder.call(this, config, newFolderName);
1008
+ destinationId = created.id;
1009
+ }
1010
+ else if (destinationFolderSource === "manual") {
1011
+ destinationId = this.getNodeParameter("destinationFolderIdManual", itemIndex, "");
1012
+ }
1013
+ else {
1014
+ destinationId = this.getNodeParameter("destinationFolderId", itemIndex, "");
1015
+ }
1016
+ const moved = await graph_1.moveMessage.call(this, config, messageId, destinationId);
1017
+ returnData.push({ json: moved });
1018
+ continue;
1019
+ }
1020
+ // ── reply / replyAll ──
1021
+ if (operation === "reply" || operation === "replyAll") {
1022
+ const replyComment = this.getNodeParameter("replyComment", itemIndex);
1023
+ const replyBodyType = this.getNodeParameter("replyBodyType", itemIndex, "html");
1024
+ await graph_1.replyToMessage.call(this, config, messageId, replyComment, replyBodyType, operation === "replyAll");
1025
+ returnData.push({
1026
+ json: { success: true, operation, messageId },
1027
+ });
1028
+ continue;
1029
+ }
1030
+ if (operation === "get") {
1031
+ const expand = this.getNodeParameter("expand", itemIndex, "");
1032
+ const selectRaw = this.getNodeParameter("select", itemIndex, []);
1033
+ const selectFields = Array.isArray(selectRaw)
1034
+ ? selectRaw.join(",")
1035
+ : selectRaw
1036
+ .split(",")
1037
+ .map((s) => s.trim())
1038
+ .filter(Boolean)
1039
+ .join(",");
1040
+ const qs = {};
1041
+ if (expand)
1042
+ qs.$expand = expand;
1043
+ if (selectFields)
1044
+ qs.$select = selectFields;
1045
+ const message = await graph_1.getMessage.call(this, config, messageId, Object.keys(qs).length > 0 ? qs : undefined);
1046
+ returnData.push({ json: message });
1047
+ continue;
1048
+ }
1049
+ if (operation === "update") {
1050
+ const body = {};
1051
+ // Flag status
1052
+ const flagStatus = this.getNodeParameter("flagStatus", itemIndex, "none");
1053
+ if (flagStatus && flagStatus !== "none") {
1054
+ body.flag = { flagStatus };
1055
+ }
1056
+ // Extended properties
1057
+ const extProps = this.getNodeParameter("extendedProperties", itemIndex, {});
1058
+ const properties = extProps.property;
1059
+ if (Array.isArray(properties) && properties.length > 0) {
1060
+ body.singleValueExtendedProperties = properties;
1061
+ }
1062
+ // Additional body fields
1063
+ let additionalBody = this.getNodeParameter("additionalBody", itemIndex, "{}");
1064
+ if (typeof additionalBody === "string") {
1065
+ try {
1066
+ additionalBody = JSON.parse(additionalBody);
1067
+ }
1068
+ catch {
1069
+ throw new Error("Invalid JSON in Additional Body (JSON) field");
1070
+ }
1071
+ }
1072
+ if (additionalBody &&
1073
+ typeof additionalBody === "object" &&
1074
+ Object.keys(additionalBody).length > 0) {
1075
+ Object.assign(body, additionalBody);
1076
+ }
1077
+ const etag = this.getNodeParameter("ifMatchETag", itemIndex, "");
1078
+ const updated = await graph_1.updateMessage.call(this, config, messageId, body, etag || undefined);
1079
+ returnData.push({ json: updated });
1080
+ continue;
1081
+ }
1082
+ }
1083
+ // ── ATTACHMENT ──
1084
+ if (resource === "attachment") {
1085
+ const mailboxMode = this.getNodeParameter("mailboxMode", itemIndex);
1086
+ const otherMailboxEmail = this.getNodeParameter("otherMailboxEmail", itemIndex, "");
1087
+ const messageId = this.getNodeParameter("messageId", itemIndex);
1088
+ const config = { mailboxMode, otherMailboxEmail };
1089
+ if (operation === "list") {
1090
+ const attachments = await graph_1.listMessageAttachments.call(this, config, messageId);
1091
+ returnData.push(...this.helpers.returnJsonArray(attachments));
1092
+ continue;
1093
+ }
1094
+ if (operation === "download") {
1095
+ const attachmentId = this.getNodeParameter("attachmentId", itemIndex);
1096
+ const attachment = await graph_1.getAttachment.call(this, config, messageId, attachmentId);
1097
+ const binaryPropertyName = "data";
1098
+ const fileName = String(attachment.name || `attachment_${attachmentId}`);
1099
+ const contentType = String(attachment.contentType || "application/octet-stream");
1100
+ const contentBytes = String(attachment.contentBytes || "");
1101
+ returnData.push({
1102
+ json: attachment,
1103
+ binary: {
1104
+ [binaryPropertyName]: await this.helpers.prepareBinaryData(Buffer.from(contentBytes, "base64"), fileName, contentType),
1105
+ },
1106
+ });
1107
+ continue;
1108
+ }
1109
+ }
1110
+ // ── USER ──
1111
+ if (resource === "user") {
1112
+ if (operation === "get") {
1113
+ const userId = this.getNodeParameter("userId", itemIndex);
1114
+ const userSelectRaw = this.getNodeParameter("userSelectFields", itemIndex, []);
1115
+ const userSelectFields = Array.isArray(userSelectRaw)
1116
+ ? userSelectRaw.join(",")
1117
+ : userSelectRaw
1118
+ .split(",")
1119
+ .map((s) => s.trim())
1120
+ .filter(Boolean)
1121
+ .join(",");
1122
+ const user = await graph_1.getUser.call(this, userId, userSelectFields || undefined);
1123
+ returnData.push({ json: user });
1124
+ continue;
1125
+ }
1126
+ }
1127
+ }
1128
+ catch (error) {
1129
+ if (this.continueOnFail()) {
1130
+ returnData.push({
1131
+ json: { error: error.message },
1132
+ pairedItem: { item: itemIndex },
1133
+ });
1134
+ continue;
1135
+ }
1136
+ throw new n8n_workflow_1.NodeApiError(this.getNode(), error, {
1137
+ itemIndex,
1138
+ });
1139
+ }
1140
+ }
1141
+ return [returnData];
1142
+ }
1143
+ }
1144
+ exports.OutlookSubscription = OutlookSubscription;
1145
+ //# sourceMappingURL=OutlookSubscription.node.js.map