n8n-nodes-outlook-subscription 0.1.6 → 0.1.7

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.
@@ -311,25 +311,29 @@ class OutlookSubscription {
311
311
  },
312
312
  options: [
313
313
  {
314
- displayName: "$expand",
315
- name: "expand",
314
+ displayName: "Extended Property Names",
315
+ name: "extendedPropertyNames",
316
316
  type: "string",
317
317
  default: "",
318
- typeOptions: { rows: 3 },
319
- placeholder: "singleValueExtendedProperties($filter=id eq 'String {00020329-0000-0000-C000-000000000046} Name contentCheckSum')",
320
- description: "OData $expand expression. Use to include extended or multi-value properties.",
318
+ placeholder: "replyId, replyToId",
319
+ description: "Comma-separated custom extended property names. If set, Graph extended properties are expanded using exact ID filters. Leave empty to ignore extended properties.",
321
320
  },
322
321
  {
323
- displayName: "$filter",
322
+ displayName: "Filter",
324
323
  name: "filter",
325
- type: "string",
326
- default: "",
327
- typeOptions: { rows: 3 },
328
- placeholder: "isDraft eq true and isRead eq false",
329
- description: "OData $filter expression to restrict results",
324
+ type: "filter",
325
+ default: {},
326
+ typeOptions: {
327
+ filter: {
328
+ version: 2,
329
+ caseSensitive: false,
330
+ typeValidation: "loose",
331
+ },
332
+ },
333
+ description: "Filter drafts by field values using dot-notation paths (e.g. subject, isRead, hasAttachments). Applied client-side after fetching.",
330
334
  },
331
335
  {
332
- displayName: "$orderby",
336
+ displayName: "Order By",
333
337
  name: "orderBy",
334
338
  type: "options",
335
339
  default: "lastModifiedDateTime desc",
@@ -353,7 +357,7 @@ class OutlookSubscription {
353
357
  ],
354
358
  },
355
359
  {
356
- displayName: "$select",
360
+ displayName: "Select Fields",
357
361
  name: "select",
358
362
  type: "multiOptions",
359
363
  default: [],
@@ -381,7 +385,7 @@ class OutlookSubscription {
381
385
  description: "Fields to return. Leave empty to return all fields.",
382
386
  },
383
387
  {
384
- displayName: "$top",
388
+ displayName: "Limit",
385
389
  name: "limit",
386
390
  type: "number",
387
391
  default: 25,
@@ -395,6 +399,20 @@ class OutlookSubscription {
395
399
  default: false,
396
400
  description: "Whether to convert the HTML body content to Markdown.",
397
401
  },
402
+ {
403
+ displayName: "List Attachments",
404
+ name: "listAttachments",
405
+ type: "boolean",
406
+ default: false,
407
+ description: "Whether to fetch attachment metadata and include it as an array on the draft object",
408
+ },
409
+ {
410
+ displayName: "Download Attachments",
411
+ name: "downloadAttachments",
412
+ type: "boolean",
413
+ default: false,
414
+ description: "Whether to download file attachment content as binary data (data_0, data_1, …). Automatically includes attachment metadata.",
415
+ },
398
416
  ],
399
417
  },
400
418
  // ── Draft Update ──
@@ -759,25 +777,29 @@ class OutlookSubscription {
759
777
  },
760
778
  options: [
761
779
  {
762
- displayName: "$expand",
763
- name: "expand",
780
+ displayName: "Extended Property Names",
781
+ name: "extendedPropertyNames",
764
782
  type: "string",
765
783
  default: "",
766
- typeOptions: { rows: 3 },
767
- placeholder: "singleValueExtendedProperties($filter=id eq 'String {00020329-0000-0000-C000-000000000046} Name contentCheckSum')",
768
- description: "OData $expand expression for related entities or extended properties",
784
+ placeholder: "replyId, replyToId",
785
+ description: "Comma-separated custom extended property names. If set, Graph extended properties are expanded using exact ID filters. Leave empty to ignore extended properties.",
769
786
  },
770
787
  {
771
- displayName: "$filter",
788
+ displayName: "Filter",
772
789
  name: "filter",
773
- type: "string",
774
- default: "",
775
- typeOptions: { rows: 3 },
776
- placeholder: "isRead eq false",
777
- description: "OData $filter expression to restrict results",
790
+ type: "filter",
791
+ default: {},
792
+ typeOptions: {
793
+ filter: {
794
+ version: 2,
795
+ caseSensitive: false,
796
+ typeValidation: "loose",
797
+ },
798
+ },
799
+ description: "Filter messages by field values using dot-notation paths (e.g. subject, from.emailAddress.address, isRead, hasAttachments). Applied client-side after fetching.",
778
800
  },
779
801
  {
780
- displayName: "$orderby",
802
+ displayName: "Order By",
781
803
  name: "orderBy",
782
804
  type: "options",
783
805
  default: "receivedDateTime desc",
@@ -796,9 +818,10 @@ class OutlookSubscription {
796
818
  value: "lastModifiedDateTime desc",
797
819
  },
798
820
  ],
821
+ description: "Sort order for results when listing messages (no Message ID given)",
799
822
  },
800
823
  {
801
- displayName: "$select",
824
+ displayName: "Select Fields",
802
825
  name: "select",
803
826
  type: "multiOptions",
804
827
  default: [],
@@ -844,15 +867,32 @@ class OutlookSubscription {
844
867
  description: "Fields to return. Leave empty to return all fields.",
845
868
  },
846
869
  {
847
- displayName: "Folder ID",
870
+ displayName: "Folder",
848
871
  name: "folderId",
849
- type: "string",
850
- default: "",
851
- placeholder: "AAMkAG...=",
872
+ type: "resourceLocator",
873
+ default: { mode: "list", value: "" },
874
+ modes: [
875
+ {
876
+ displayName: "From List",
877
+ name: "list",
878
+ type: "list",
879
+ typeOptions: {
880
+ searchListMethod: "searchMailFolders",
881
+ searchable: true,
882
+ },
883
+ },
884
+ {
885
+ displayName: "By ID",
886
+ name: "id",
887
+ type: "string",
888
+ placeholder: "AAMkAG...=",
889
+ hint: "Enter the folder ID directly",
890
+ },
891
+ ],
852
892
  description: "Restrict results to a specific folder. Only applies when listing (no Message ID). Leave empty to query all mailbox messages.",
853
893
  },
854
894
  {
855
- displayName: "$top",
895
+ displayName: "Limit",
856
896
  name: "limit",
857
897
  type: "number",
858
898
  default: 25,
@@ -866,6 +906,20 @@ class OutlookSubscription {
866
906
  default: false,
867
907
  description: "Whether to convert the HTML body content to Markdown. Only applied when the body field is returned and its contentType is html.",
868
908
  },
909
+ {
910
+ displayName: "List Attachments",
911
+ name: "listAttachments",
912
+ type: "boolean",
913
+ default: false,
914
+ description: "Whether to fetch attachment metadata and include it as an array on the message object",
915
+ },
916
+ {
917
+ displayName: "Download Attachments",
918
+ name: "downloadAttachments",
919
+ type: "boolean",
920
+ default: false,
921
+ description: "Whether to download file attachment content as binary data (data_0, data_1, …). Automatically includes attachment metadata.",
922
+ },
869
923
  ],
870
924
  },
871
925
  // ── Sent Item Operation ──
@@ -902,25 +956,38 @@ class OutlookSubscription {
902
956
  },
903
957
  options: [
904
958
  {
905
- displayName: "$expand",
906
- name: "expand",
959
+ displayName: "Extended Property Names",
960
+ name: "extendedPropertyNames",
907
961
  type: "string",
908
962
  default: "",
909
- typeOptions: { rows: 3 },
910
- placeholder: "singleValueExtendedProperties($filter=id eq 'String {00020329-0000-0000-C000-000000000046} Name approvedBy' or id eq 'String {00020329-0000-0000-C000-000000000046} Name approvedAt')",
911
- description: "OData $expand expression. Use to include extended properties or related entities.",
963
+ placeholder: "replyId, replyToId",
964
+ description: "Comma-separated custom extended property names. If set, Graph extended properties are expanded using exact ID filters. Leave empty to ignore extended properties.",
912
965
  },
913
966
  {
914
- displayName: "$filter",
915
- name: "filter",
967
+ displayName: "OData Filter",
968
+ name: "odataFilter",
916
969
  type: "string",
917
970
  default: "",
918
- typeOptions: { rows: 3 },
919
- placeholder: "singleValueExtendedProperties/any(ep: ep/id eq 'String {guid} Name replyId' and ep/value eq 'abc')",
920
- description: "OData $filter expression to restrict results",
971
+ placeholder: "subject eq 'Hello' and isRead eq false",
972
+ description: "Raw OData $filter expression sent directly to Microsoft Graph. Takes priority over the Filter option below. Use this for advanced filters, e.g. extended-property filters: <code>singleValueExtendedProperties/any(ep: ep/id eq 'String {} Name replyId' and ep/value eq 'abc123')</code>",
973
+ hint: "Leave empty to use the visual Filter builder below instead.",
974
+ },
975
+ {
976
+ displayName: "Filter",
977
+ name: "filter",
978
+ type: "filter",
979
+ default: {},
980
+ typeOptions: {
981
+ filter: {
982
+ version: 2,
983
+ caseSensitive: false,
984
+ typeValidation: "loose",
985
+ },
986
+ },
987
+ description: "Filter sent items by field values. Automatically converted to a server-side OData $filter sent to Microsoft Graph. Ignored when OData Filter is set.",
921
988
  },
922
989
  {
923
- displayName: "$orderby",
990
+ displayName: "Order By",
924
991
  name: "orderBy",
925
992
  type: "options",
926
993
  default: "receivedDateTime desc",
@@ -942,7 +1009,7 @@ class OutlookSubscription {
942
1009
  ],
943
1010
  },
944
1011
  {
945
- displayName: "$select",
1012
+ displayName: "Select Fields",
946
1013
  name: "select",
947
1014
  type: "multiOptions",
948
1015
  default: [],
@@ -980,7 +1047,7 @@ class OutlookSubscription {
980
1047
  description: "Fields to return. Leave empty to return all fields.",
981
1048
  },
982
1049
  {
983
- displayName: "$top",
1050
+ displayName: "Limit",
984
1051
  name: "limit",
985
1052
  type: "number",
986
1053
  default: 25,
@@ -994,6 +1061,20 @@ class OutlookSubscription {
994
1061
  default: false,
995
1062
  description: "Whether to convert the HTML body content to Markdown.",
996
1063
  },
1064
+ {
1065
+ displayName: "List Attachments",
1066
+ name: "listAttachments",
1067
+ type: "boolean",
1068
+ default: false,
1069
+ description: "Whether to fetch attachment metadata and include it as an array on the sent item object",
1070
+ },
1071
+ {
1072
+ displayName: "Download Attachments",
1073
+ name: "downloadAttachments",
1074
+ type: "boolean",
1075
+ default: false,
1076
+ description: "Whether to download file attachment content as binary data (data_0, data_1, …). Automatically includes attachment metadata.",
1077
+ },
997
1078
  ],
998
1079
  },
999
1080
  // ── Message Update: Fields ──
@@ -1111,17 +1192,29 @@ class OutlookSubscription {
1111
1192
  name: "property",
1112
1193
  values: [
1113
1194
  {
1114
- displayName: "Property ID",
1195
+ displayName: "Type",
1196
+ name: "type",
1197
+ type: "options",
1198
+ default: "single",
1199
+ options: [
1200
+ { name: "Single Value", value: "single" },
1201
+ { name: "Multi Value", value: "multi" },
1202
+ ],
1203
+ },
1204
+ {
1205
+ displayName: "Property Name",
1115
1206
  name: "id",
1116
1207
  type: "string",
1117
1208
  default: "",
1118
- placeholder: "String {00020329-0000-0000-C000-000000000046} Name contentCheckSum",
1209
+ placeholder: "contentCheckSum",
1210
+ description: 'The property name. The prefix "String {00020329-0000-0000-C000-000000000046} Name " is added automatically.',
1119
1211
  },
1120
1212
  {
1121
1213
  displayName: "Value",
1122
1214
  name: "value",
1123
1215
  type: "string",
1124
1216
  default: "",
1217
+ description: 'For Single Value: plain text. For Multi Value: comma-separated quoted strings, e.g. "a","b","c"',
1125
1218
  },
1126
1219
  ],
1127
1220
  },
@@ -1591,12 +1684,66 @@ class OutlookSubscription {
1591
1684
  return await graph_1.loadFolderOptions.call(this);
1592
1685
  },
1593
1686
  },
1687
+ listSearch: {
1688
+ async searchMailFolders(filter) {
1689
+ const options = await graph_1.loadFolderOptions.call(this);
1690
+ const lower = (filter || "").toLowerCase();
1691
+ const filtered = lower
1692
+ ? options.filter((o) => o.name.toLowerCase().includes(lower))
1693
+ : options;
1694
+ return {
1695
+ results: filtered.map((o) => ({
1696
+ name: o.name,
1697
+ value: o.value,
1698
+ })),
1699
+ };
1700
+ },
1701
+ },
1594
1702
  };
1595
1703
  }
1596
1704
  async execute() {
1597
- var _a, _b, _c, _d, _e, _f, _g, _h;
1705
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
1598
1706
  const items = this.getInputData();
1599
1707
  const returnData = [];
1708
+ const EXTENDED_PROP_PREFIX = "String {00020329-0000-0000-C000-000000000046} Name ";
1709
+ const buildExtendedExpand = (enabled, rawNames) => {
1710
+ if (!enabled)
1711
+ return "";
1712
+ const names = String(rawNames !== null && rawNames !== void 0 ? rawNames : "")
1713
+ .split(",")
1714
+ .map((s) => s.trim())
1715
+ .filter(Boolean);
1716
+ if (names.length === 0)
1717
+ return "";
1718
+ const predicates = names
1719
+ .map((name) => `${EXTENDED_PROP_PREFIX}${name}`.replace(/'/g, "''"))
1720
+ .map((id) => `id eq '${id}'`)
1721
+ .join(" or ");
1722
+ return (`singleValueExtendedProperties($filter=${predicates}),` +
1723
+ `multiValueExtendedProperties($filter=${predicates})`);
1724
+ };
1725
+ const dedupeExtendedProperties = (message) => {
1726
+ const out = { ...message };
1727
+ for (const key of [
1728
+ "singleValueExtendedProperties",
1729
+ "multiValueExtendedProperties",
1730
+ ]) {
1731
+ const raw = out[key];
1732
+ if (!Array.isArray(raw))
1733
+ continue;
1734
+ const seen = new Set();
1735
+ out[key] = raw.filter((entry) => {
1736
+ var _a, _b;
1737
+ const obj = entry;
1738
+ const signature = `${String((_a = obj.id) !== null && _a !== void 0 ? _a : "")}|${JSON.stringify((_b = obj.value) !== null && _b !== void 0 ? _b : null)}`;
1739
+ if (seen.has(signature))
1740
+ return false;
1741
+ seen.add(signature);
1742
+ return true;
1743
+ });
1744
+ }
1745
+ return out;
1746
+ };
1600
1747
  for (let itemIndex = 0; itemIndex < items.length; itemIndex++) {
1601
1748
  try {
1602
1749
  const resource = this.getNodeParameter("resource", itemIndex);
@@ -1787,8 +1934,8 @@ class OutlookSubscription {
1787
1934
  // ── get ──
1788
1935
  if (operation === "get") {
1789
1936
  const opts = this.getNodeParameter("messageGetOptions", itemIndex, {});
1790
- const expand = (opts.expand || "").trim();
1791
- const filter = (opts.filter || "").trim();
1937
+ const expand = buildExtendedExpand(Boolean(opts.extendedPropertyNames), opts.extendedPropertyNames);
1938
+ const messageFilter = opts.filter || {};
1792
1939
  const orderBy = opts.orderBy || "receivedDateTime desc";
1793
1940
  const selectRaw = opts.select;
1794
1941
  const selectFields = Array.isArray(selectRaw)
@@ -1801,6 +1948,8 @@ class OutlookSubscription {
1801
1948
  .join(",")
1802
1949
  : "";
1803
1950
  const bodyToMarkdown = (_c = opts.bodyToMarkdown) !== null && _c !== void 0 ? _c : false;
1951
+ const listAttachments = Boolean(opts.listAttachments);
1952
+ const downloadAttachments = Boolean(opts.downloadAttachments);
1804
1953
  const msgId = this.getNodeParameter("messageId", itemIndex, "").trim();
1805
1954
  if (msgId) {
1806
1955
  const qs = {};
@@ -1809,19 +1958,47 @@ class OutlookSubscription {
1809
1958
  if (selectFields)
1810
1959
  qs.$select = selectFields;
1811
1960
  const message = await graph_1.getMessage.call(this, config, msgId, Object.keys(qs).length > 0 ? qs : undefined);
1812
- returnData.push({
1813
- json: bodyToMarkdown ? (0, graph_1.convertBodyToMarkdown)(message) : message,
1814
- });
1961
+ const resolved = dedupeExtendedProperties(bodyToMarkdown ? (0, graph_1.convertBodyToMarkdown)(message) : message);
1962
+ if (!(0, graph_1.evaluateMessageFilter)(messageFilter, resolved))
1963
+ continue;
1964
+ if (listAttachments || downloadAttachments) {
1965
+ const rawAttachments = await graph_1.listMessageAttachments.call(this, config, msgId);
1966
+ const binaryData = {};
1967
+ const attachmentsMeta = [];
1968
+ let binaryIndex = 0;
1969
+ for (const attachment of rawAttachments) {
1970
+ if (downloadAttachments &&
1971
+ attachment["@odata.type"] ===
1972
+ "#microsoft.graph.fileAttachment" &&
1973
+ attachment.contentBytes) {
1974
+ const binaryItem = await this.helpers.prepareBinaryData(Buffer.from(attachment.contentBytes, "base64"), attachment.name || "attachment", attachment.contentType ||
1975
+ "application/octet-stream");
1976
+ binaryData[`data_${binaryIndex++}`] = binaryItem;
1977
+ const { contentBytes: _stripped, ...meta } = attachment;
1978
+ attachmentsMeta.push(meta);
1979
+ }
1980
+ else {
1981
+ attachmentsMeta.push(attachment);
1982
+ }
1983
+ }
1984
+ resolved.attachments = attachmentsMeta;
1985
+ returnData.push({
1986
+ json: resolved,
1987
+ binary: Object.keys(binaryData).length > 0 ? binaryData : undefined,
1988
+ });
1989
+ }
1990
+ else {
1991
+ returnData.push({ json: resolved });
1992
+ }
1815
1993
  }
1816
1994
  else {
1817
1995
  const limit = typeof opts.limit === "number" ? opts.limit : 25;
1818
- const folderIdOpt = (opts.folderId || "").trim();
1996
+ const folderLocator = opts.folderId || {};
1997
+ const folderIdOpt = (folderLocator.value || "").trim();
1819
1998
  const qs = {
1820
1999
  $orderby: orderBy,
1821
2000
  $top: Math.min(limit, 1000),
1822
2001
  };
1823
- if (filter)
1824
- qs.$filter = filter;
1825
2002
  if (expand)
1826
2003
  qs.$expand = expand;
1827
2004
  if (selectFields)
@@ -1830,7 +2007,8 @@ class OutlookSubscription {
1830
2007
  const mapped = bodyToMarkdown
1831
2008
  ? messages.map(graph_1.convertBodyToMarkdown)
1832
2009
  : messages;
1833
- returnData.push(...this.helpers.returnJsonArray(mapped));
2010
+ const filtered = mapped.filter((m) => (0, graph_1.evaluateMessageFilter)(messageFilter, m));
2011
+ returnData.push(...this.helpers.returnJsonArray(filtered.map(dedupeExtendedProperties)));
1834
2012
  }
1835
2013
  continue;
1836
2014
  }
@@ -1941,8 +2119,28 @@ class OutlookSubscription {
1941
2119
  // Extended properties
1942
2120
  const extProps = this.getNodeParameter("extendedProperties", itemIndex, {});
1943
2121
  const properties = extProps.property;
2122
+ const extendedPropertyIds = [];
1944
2123
  if (Array.isArray(properties) && properties.length > 0) {
1945
- body.singleValueExtendedProperties = properties;
2124
+ const EXTENDED_PROP_PREFIX = "String {00020329-0000-0000-C000-000000000046} Name ";
2125
+ const singleProps = [];
2126
+ const multiProps = [];
2127
+ for (const p of properties) {
2128
+ const fullId = `${EXTENDED_PROP_PREFIX}${p.id}`;
2129
+ extendedPropertyIds.push(fullId);
2130
+ if (p.type === "multi") {
2131
+ // Parse comma-separated quoted strings: "a","b","c"
2132
+ const raw = (_e = p.value) !== null && _e !== void 0 ? _e : "";
2133
+ const values = Array.from(raw.matchAll(/"((?:[^"\\]|\\.)*)"/g), (m) => m[1]);
2134
+ multiProps.push({ id: fullId, value: values });
2135
+ }
2136
+ else {
2137
+ singleProps.push({ id: fullId, value: p.value });
2138
+ }
2139
+ }
2140
+ if (singleProps.length > 0)
2141
+ body.singleValueExtendedProperties = singleProps;
2142
+ if (multiProps.length > 0)
2143
+ body.multiValueExtendedProperties = multiProps;
1946
2144
  }
1947
2145
  // Additional body fields
1948
2146
  let additionalBody = this.getNodeParameter("additionalBody", itemIndex, "{}");
@@ -1961,7 +2159,23 @@ class OutlookSubscription {
1961
2159
  }
1962
2160
  const etag = this.getNodeParameter("ifMatchETag", itemIndex, "");
1963
2161
  const updated = await graph_1.updateMessage.call(this, config, messageId, body, etag || undefined);
1964
- returnData.push({ json: updated });
2162
+ if (extendedPropertyIds.length > 0) {
2163
+ const quotedIds = extendedPropertyIds
2164
+ .map((id) => id.replace(/'/g, "''"))
2165
+ .map((id) => `id eq '${id}'`)
2166
+ .join(" or ");
2167
+ const qs = {
2168
+ $expand: `singleValueExtendedProperties($filter=${quotedIds}),` +
2169
+ `multiValueExtendedProperties($filter=${quotedIds})`,
2170
+ };
2171
+ const updatedWithExtended = await graph_1.getMessage.call(this, config, messageId, qs);
2172
+ returnData.push({
2173
+ json: dedupeExtendedProperties(updatedWithExtended),
2174
+ });
2175
+ }
2176
+ else {
2177
+ returnData.push({ json: dedupeExtendedProperties(updated) });
2178
+ }
1965
2179
  continue;
1966
2180
  }
1967
2181
  }
@@ -1989,7 +2203,7 @@ class OutlookSubscription {
1989
2203
  });
1990
2204
  }
1991
2205
  const draftInlineImagesCollection = this.getNodeParameter("draftInlineImages", itemIndex, {});
1992
- const draftInlineImageEntries = (_e = draftInlineImagesCollection.image) !== null && _e !== void 0 ? _e : [];
2206
+ const draftInlineImageEntries = (_f = draftInlineImagesCollection.image) !== null && _f !== void 0 ? _f : [];
1993
2207
  const inlineImages = [];
1994
2208
  for (const entry of draftInlineImageEntries) {
1995
2209
  const imgField = entry.binaryFieldName.trim() || "data";
@@ -2025,8 +2239,8 @@ class OutlookSubscription {
2025
2239
  }
2026
2240
  if (operation === "get") {
2027
2241
  const opts = this.getNodeParameter("draftGetOptions", itemIndex, {});
2028
- const expand = (opts.expand || "").trim();
2029
- const filter = (opts.filter || "").trim();
2242
+ const expand = buildExtendedExpand(Boolean(opts.extendedPropertyNames), opts.extendedPropertyNames);
2243
+ const messageFilter = opts.filter || {};
2030
2244
  const orderBy = opts.orderBy || "lastModifiedDateTime desc";
2031
2245
  const selectRaw = opts.select;
2032
2246
  const selectFields = Array.isArray(selectRaw)
@@ -2038,7 +2252,9 @@ class OutlookSubscription {
2038
2252
  .filter(Boolean)
2039
2253
  .join(",")
2040
2254
  : "";
2041
- const bodyToMarkdown = (_f = opts.bodyToMarkdown) !== null && _f !== void 0 ? _f : false;
2255
+ const bodyToMarkdown = (_g = opts.bodyToMarkdown) !== null && _g !== void 0 ? _g : false;
2256
+ const listAttachments = Boolean(opts.listAttachments);
2257
+ const downloadAttachments = Boolean(opts.downloadAttachments);
2042
2258
  const draftGetId = this.getNodeParameter("draftId", itemIndex, "").trim();
2043
2259
  if (draftGetId) {
2044
2260
  const qs = {};
@@ -2047,9 +2263,38 @@ class OutlookSubscription {
2047
2263
  if (selectFields)
2048
2264
  qs.$select = selectFields;
2049
2265
  const message = await graph_1.getMessage.call(this, config, draftGetId, Object.keys(qs).length > 0 ? qs : undefined);
2050
- returnData.push({
2051
- json: bodyToMarkdown ? (0, graph_1.convertBodyToMarkdown)(message) : message,
2052
- });
2266
+ const resolved = dedupeExtendedProperties(bodyToMarkdown ? (0, graph_1.convertBodyToMarkdown)(message) : message);
2267
+ if (!(0, graph_1.evaluateMessageFilter)(messageFilter, resolved))
2268
+ continue;
2269
+ if (listAttachments || downloadAttachments) {
2270
+ const rawAttachments = await graph_1.listMessageAttachments.call(this, config, draftGetId);
2271
+ const binaryData = {};
2272
+ const attachmentsMeta = [];
2273
+ let binaryIndex = 0;
2274
+ for (const attachment of rawAttachments) {
2275
+ if (downloadAttachments &&
2276
+ attachment["@odata.type"] ===
2277
+ "#microsoft.graph.fileAttachment" &&
2278
+ attachment.contentBytes) {
2279
+ const binaryItem = await this.helpers.prepareBinaryData(Buffer.from(attachment.contentBytes, "base64"), attachment.name || "attachment", attachment.contentType ||
2280
+ "application/octet-stream");
2281
+ binaryData[`data_${binaryIndex++}`] = binaryItem;
2282
+ const { contentBytes: _stripped, ...meta } = attachment;
2283
+ attachmentsMeta.push(meta);
2284
+ }
2285
+ else {
2286
+ attachmentsMeta.push(attachment);
2287
+ }
2288
+ }
2289
+ resolved.attachments = attachmentsMeta;
2290
+ returnData.push({
2291
+ json: resolved,
2292
+ binary: Object.keys(binaryData).length > 0 ? binaryData : undefined,
2293
+ });
2294
+ }
2295
+ else {
2296
+ returnData.push({ json: resolved });
2297
+ }
2053
2298
  }
2054
2299
  else {
2055
2300
  const limit = typeof opts.limit === "number" ? opts.limit : 25;
@@ -2057,8 +2302,6 @@ class OutlookSubscription {
2057
2302
  $orderby: orderBy,
2058
2303
  $top: Math.min(limit, 1000),
2059
2304
  };
2060
- if (filter)
2061
- qs.$filter = filter;
2062
2305
  if (expand)
2063
2306
  qs.$expand = expand;
2064
2307
  if (selectFields)
@@ -2067,7 +2310,8 @@ class OutlookSubscription {
2067
2310
  const mapped = bodyToMarkdown
2068
2311
  ? messages.map(graph_1.convertBodyToMarkdown)
2069
2312
  : messages;
2070
- returnData.push(...this.helpers.returnJsonArray(mapped));
2313
+ const filtered = mapped.filter((m) => (0, graph_1.evaluateMessageFilter)(messageFilter, m));
2314
+ returnData.push(...this.helpers.returnJsonArray(filtered.map(dedupeExtendedProperties)));
2071
2315
  }
2072
2316
  continue;
2073
2317
  }
@@ -2120,7 +2364,7 @@ class OutlookSubscription {
2120
2364
  }
2121
2365
  if (f.importance)
2122
2366
  body.importance = f.importance;
2123
- let additionalBody = (_g = f.additionalBody) !== null && _g !== void 0 ? _g : "{}";
2367
+ let additionalBody = (_h = f.additionalBody) !== null && _h !== void 0 ? _h : "{}";
2124
2368
  if (typeof additionalBody === "string") {
2125
2369
  try {
2126
2370
  additionalBody = JSON.parse(additionalBody);
@@ -2145,8 +2389,9 @@ class OutlookSubscription {
2145
2389
  const config = { mailboxMode: "current" };
2146
2390
  if (operation === "get") {
2147
2391
  const opts = this.getNodeParameter("sentItemOptions", itemIndex, {});
2148
- const expand = (opts.expand || "").trim();
2149
- const filter = (opts.filter || "").trim();
2392
+ const expand = buildExtendedExpand(Boolean(opts.extendedPropertyNames), opts.extendedPropertyNames);
2393
+ const messageFilter = opts.filter || {};
2394
+ const rawOdataFilter = (opts.odataFilter || "").trim();
2150
2395
  const orderBy = opts.orderBy || "receivedDateTime desc";
2151
2396
  const selectRaw = opts.select;
2152
2397
  const selectFields = Array.isArray(selectRaw)
@@ -2158,7 +2403,12 @@ class OutlookSubscription {
2158
2403
  .filter(Boolean)
2159
2404
  .join(",")
2160
2405
  : "";
2161
- const bodyToMarkdown = (_h = opts.bodyToMarkdown) !== null && _h !== void 0 ? _h : false;
2406
+ const bodyToMarkdown = (_j = opts.bodyToMarkdown) !== null && _j !== void 0 ? _j : false;
2407
+ const listAttachments = Boolean(opts.listAttachments);
2408
+ const downloadAttachments = Boolean(opts.downloadAttachments);
2409
+ // Resolve the OData $filter to use: raw string wins, otherwise
2410
+ // translate the visual filter to OData for server-side filtering.
2411
+ const resolvedOdataFilter = rawOdataFilter || (0, graph_1.filterToOData)(messageFilter) || "";
2162
2412
  const sentItemMessageId = this.getNodeParameter("sentItemMessageId", itemIndex, "").trim();
2163
2413
  if (sentItemMessageId) {
2164
2414
  const qs = {};
@@ -2167,9 +2417,38 @@ class OutlookSubscription {
2167
2417
  if (selectFields)
2168
2418
  qs.$select = selectFields;
2169
2419
  const msg = await graph_1.getSentMessage.call(this, config, sentItemMessageId, Object.keys(qs).length > 0 ? qs : undefined);
2170
- returnData.push({
2171
- json: bodyToMarkdown ? (0, graph_1.convertBodyToMarkdown)(msg) : msg,
2172
- });
2420
+ const resolved = dedupeExtendedProperties(bodyToMarkdown ? (0, graph_1.convertBodyToMarkdown)(msg) : msg);
2421
+ if (!(0, graph_1.evaluateMessageFilter)(messageFilter, resolved))
2422
+ continue;
2423
+ if (listAttachments || downloadAttachments) {
2424
+ const rawAttachments = await graph_1.listMessageAttachments.call(this, config, sentItemMessageId);
2425
+ const binaryData = {};
2426
+ const attachmentsMeta = [];
2427
+ let binaryIndex = 0;
2428
+ for (const attachment of rawAttachments) {
2429
+ if (downloadAttachments &&
2430
+ attachment["@odata.type"] ===
2431
+ "#microsoft.graph.fileAttachment" &&
2432
+ attachment.contentBytes) {
2433
+ const binaryItem = await this.helpers.prepareBinaryData(Buffer.from(attachment.contentBytes, "base64"), attachment.name || "attachment", attachment.contentType ||
2434
+ "application/octet-stream");
2435
+ binaryData[`data_${binaryIndex++}`] = binaryItem;
2436
+ const { contentBytes: _stripped, ...meta } = attachment;
2437
+ attachmentsMeta.push(meta);
2438
+ }
2439
+ else {
2440
+ attachmentsMeta.push(attachment);
2441
+ }
2442
+ }
2443
+ resolved.attachments = attachmentsMeta;
2444
+ returnData.push({
2445
+ json: resolved,
2446
+ binary: Object.keys(binaryData).length > 0 ? binaryData : undefined,
2447
+ });
2448
+ }
2449
+ else {
2450
+ returnData.push({ json: resolved });
2451
+ }
2173
2452
  }
2174
2453
  else {
2175
2454
  const limit = typeof opts.limit === "number" ? opts.limit : 25;
@@ -2177,17 +2456,17 @@ class OutlookSubscription {
2177
2456
  $orderby: orderBy,
2178
2457
  $top: Math.min(limit, 1000),
2179
2458
  };
2180
- if (filter)
2181
- qs.$filter = filter;
2182
2459
  if (expand)
2183
2460
  qs.$expand = expand;
2184
2461
  if (selectFields)
2185
2462
  qs.$select = selectFields;
2463
+ if (resolvedOdataFilter)
2464
+ qs.$filter = resolvedOdataFilter;
2186
2465
  const messages = await graph_1.listSentMessages.call(this, config, qs, false);
2187
2466
  const mapped = bodyToMarkdown
2188
2467
  ? messages.map(graph_1.convertBodyToMarkdown)
2189
2468
  : messages;
2190
- returnData.push(...this.helpers.returnJsonArray(mapped));
2469
+ returnData.push(...this.helpers.returnJsonArray(mapped.map(dedupeExtendedProperties)));
2191
2470
  }
2192
2471
  continue;
2193
2472
  }