@prismatic-io/components-imap 0.0.0-stage → 0.0.1

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,933 @@
1
+ let _prismatic_io_spectral = require("@prismatic-io/spectral");
2
+ let imapflow = require("imapflow");
3
+ let mailparser = require("mailparser");
4
+ let _prismatic_io_spectral_http = require("@prismatic-io/spectral/http");
5
+ //#region src/connections/index.ts
6
+ const imapConnection = (0, _prismatic_io_spectral.onPremConnection)({
7
+ key: "imap",
8
+ display: {
9
+ label: "IMAP Connection",
10
+ description: "Provide the details of your IMAP server."
11
+ },
12
+ inputs: {
13
+ host: {
14
+ label: "Host",
15
+ placeholder: "Host",
16
+ type: "string",
17
+ required: true,
18
+ clean: (param) => _prismatic_io_spectral.util.types.toString(param) || void 0,
19
+ shown: true,
20
+ comments: "Provide the host address for the desired IMAP server.",
21
+ example: "imap.example.com",
22
+ onPremControlled: true
23
+ },
24
+ port: {
25
+ label: "Port",
26
+ placeholder: "Port",
27
+ type: "string",
28
+ required: true,
29
+ clean: (param) => _prismatic_io_spectral.util.types.toNumber(param) || void 0,
30
+ shown: true,
31
+ comments: "Provide the port for the desired IMAP server.",
32
+ example: "993",
33
+ default: "993",
34
+ onPremControlled: true
35
+ },
36
+ secure: {
37
+ label: "Secure",
38
+ placeholder: "Secure",
39
+ type: "boolean",
40
+ clean: (param) => _prismatic_io_spectral.util.types.toBool(param) || void 0,
41
+ required: true,
42
+ shown: true,
43
+ default: "true",
44
+ comments: "Determines if the connection is secure."
45
+ },
46
+ user: {
47
+ label: "Username",
48
+ placeholder: "Username",
49
+ type: "string",
50
+ clean: (param) => _prismatic_io_spectral.util.types.toString(param) || void 0,
51
+ required: true,
52
+ shown: true,
53
+ comments: "Provide a valid username or email.",
54
+ example: "someone@example.com"
55
+ },
56
+ pass: {
57
+ label: "Password",
58
+ placeholder: "Password",
59
+ type: "password",
60
+ required: false,
61
+ shown: true,
62
+ clean: (param) => _prismatic_io_spectral.util.types.toString(param) || void 0,
63
+ comments: "Provide the password for the given user. This value is required if secured is set to true.",
64
+ example: "examplePassword"
65
+ },
66
+ minVersion: {
67
+ label: "Minimum TLS Version",
68
+ type: "string",
69
+ required: true,
70
+ shown: true,
71
+ clean: (param) => _prismatic_io_spectral.util.types.toString(param) || void 0,
72
+ comments: "Provide a valid TLS version to be used in the connection.",
73
+ example: "TLSv1.1",
74
+ default: "TLSv1.1",
75
+ model: [
76
+ {
77
+ label: "TLSv1.1",
78
+ value: "TLSv1.1"
79
+ },
80
+ {
81
+ label: "TLSv1.2",
82
+ value: "TLSv1.2"
83
+ },
84
+ {
85
+ label: "TLSv1.3",
86
+ value: "TLSv1.3"
87
+ }
88
+ ]
89
+ },
90
+ maxVersion: {
91
+ label: "Maximum TLS Version",
92
+ type: "string",
93
+ required: true,
94
+ shown: true,
95
+ clean: (param) => _prismatic_io_spectral.util.types.toString(param) || void 0,
96
+ comments: "Provide a valid TLS version to be used in the connection.",
97
+ example: "TLSv1.3",
98
+ default: "TLSv1.3",
99
+ model: [
100
+ {
101
+ label: "TLSv1.1",
102
+ value: "TLSv1.1"
103
+ },
104
+ {
105
+ label: "TLSv1.2",
106
+ value: "TLSv1.2"
107
+ },
108
+ {
109
+ label: "TLSv1.3",
110
+ value: "TLSv1.3"
111
+ }
112
+ ]
113
+ },
114
+ minDHSize: {
115
+ label: "Min DH Size",
116
+ type: "string",
117
+ required: true,
118
+ shown: true,
119
+ clean: (param) => _prismatic_io_spectral.util.types.toInt(param) || void 0,
120
+ comments: "Minimum size of bits to accept in a TLS connection",
121
+ example: "512",
122
+ default: "1024"
123
+ }
124
+ }
125
+ });
126
+ var connections_default = [imapConnection];
127
+ //#endregion
128
+ //#region src/client.ts
129
+ const createClient = (connection, debug) => {
130
+ if (connection.key !== imapConnection.key) throw new _prismatic_io_spectral.ConnectionError(connection, `Unsupported connection provided: ${connection.key}`);
131
+ return new imapflow.ImapFlow({
132
+ host: _prismatic_io_spectral.util.types.toString(connection.fields.host),
133
+ port: _prismatic_io_spectral.util.types.toNumber(connection.fields.port),
134
+ secure: _prismatic_io_spectral.util.types.toBool(connection.fields.secure),
135
+ auth: {
136
+ user: _prismatic_io_spectral.util.types.toString(connection.fields.user),
137
+ pass: _prismatic_io_spectral.util.types.toString(connection.fields.pass)
138
+ },
139
+ tls: {
140
+ minDHSize: _prismatic_io_spectral.util.types.toInt(connection.fields.minDHSize),
141
+ rejectUnauthorized: true,
142
+ minVersion: _prismatic_io_spectral.util.types.toString(connection.fields.minVersion),
143
+ maxVersion: _prismatic_io_spectral.util.types.toString(connection.fields.maxVersion),
144
+ ciphers: "ALL"
145
+ },
146
+ logger: debug ? console : false
147
+ });
148
+ };
149
+ //#endregion
150
+ //#region src/examplePayloads.ts
151
+ const addFlagsExamplePayload = { data: true };
152
+ const appendMessageExamplePayload = { data: {
153
+ destination: "INBOX",
154
+ uid: 456,
155
+ uidValidity: "596391842",
156
+ seq: 61
157
+ } };
158
+ const copyMessageExamplePayload = { data: {
159
+ path: "My-Source-Mailbox",
160
+ destination: "My-Destination-Mailbox",
161
+ uidValidity: "596391920",
162
+ uidMap: /* @__PURE__ */ new Map([[1, 2]])
163
+ } };
164
+ const createMailboxExamplePayload = { data: {
165
+ path: "New-Mailbox",
166
+ created: true
167
+ } };
168
+ const deleteMessageExamplePayload = { data: true };
169
+ const downloadMessageExamplePayload = { data: {
170
+ meta: {
171
+ expectedSize: 12345,
172
+ contentType: "message/rfc822"
173
+ },
174
+ message: {
175
+ headers: {
176
+ from: { value: [{
177
+ address: "sender@example.com",
178
+ name: "Sender"
179
+ }] },
180
+ to: { value: [{
181
+ address: "recipient@example.com",
182
+ name: "Recipient"
183
+ }] },
184
+ subject: "Example Subject",
185
+ date: "2025-07-21T12:00:00.000Z"
186
+ },
187
+ attachments: [],
188
+ attachmentsMetadata: [],
189
+ text: "This is the plain text body of the email.",
190
+ html: "<p>This is the HTML body of the email.</p>"
191
+ }
192
+ } };
193
+ const getStatusExamplePayload = { data: {
194
+ path: "INBOX",
195
+ highestModseq: "10914782",
196
+ messages: 61,
197
+ recent: 0,
198
+ uidNext: 76791,
199
+ uidValidity: "596391842",
200
+ unseen: 41
201
+ } };
202
+ const listMailboxesExamplePayload = { data: [
203
+ {
204
+ path: "Drafts",
205
+ flags: /* @__PURE__ */ new Set(),
206
+ delimiter: "/",
207
+ listed: true,
208
+ name: "Drafts",
209
+ subscribed: true
210
+ },
211
+ {
212
+ path: "INBOX",
213
+ flags: /* @__PURE__ */ new Set(),
214
+ delimiter: "/",
215
+ listed: true,
216
+ specialUse: "\\Inbox",
217
+ name: "INBOX",
218
+ subscribed: true
219
+ },
220
+ {
221
+ path: "Sent",
222
+ flags: /* @__PURE__ */ new Set(),
223
+ delimiter: "/",
224
+ listed: true,
225
+ name: "Sent",
226
+ subscribed: true
227
+ }
228
+ ] };
229
+ const removeFlagsExamplePayload = { data: true };
230
+ const renameMailboxExamplePayload = { data: {
231
+ path: "Old-Mailbox",
232
+ newPath: "New-Mailbox"
233
+ } };
234
+ const searchMailboxExamplePayload = { data: [
235
+ 1,
236
+ 5,
237
+ 12,
238
+ 45,
239
+ 78
240
+ ] };
241
+ const setFlagsExamplePayload = { data: true };
242
+ //#endregion
243
+ //#region src/inputs/general.ts
244
+ const connection = (0, _prismatic_io_spectral.input)({
245
+ label: "Connection",
246
+ type: "connection",
247
+ required: true,
248
+ comments: "The IMAP connection to use."
249
+ });
250
+ const mailbox = (0, _prismatic_io_spectral.input)({
251
+ label: "Mailbox",
252
+ type: "string",
253
+ required: true,
254
+ comments: "Provide a string value for the name of the mailbox.",
255
+ example: "INBOX",
256
+ placeholder: "Enter mailbox name",
257
+ clean: _prismatic_io_spectral.util.types.toString
258
+ });
259
+ const path = (0, _prismatic_io_spectral.input)({
260
+ label: "Path",
261
+ type: "string",
262
+ required: true,
263
+ comments: "Mailbox path to upload the message to.",
264
+ example: "INBOX",
265
+ placeholder: "Enter mailbox path",
266
+ clean: _prismatic_io_spectral.util.types.toString
267
+ });
268
+ const range = (0, _prismatic_io_spectral.input)({
269
+ label: "Range",
270
+ type: "string",
271
+ required: true,
272
+ comments: "Provide a range of messages. Alternatively you can specify * to get the latest message.",
273
+ example: "1,2,4:6",
274
+ placeholder: "Enter message range",
275
+ clean: _prismatic_io_spectral.util.types.toString
276
+ });
277
+ const flags = (0, _prismatic_io_spectral.input)({
278
+ label: "Flags",
279
+ type: "string",
280
+ required: true,
281
+ collection: "valuelist",
282
+ comments: "For each item, provide a string value to be added to an existing message.",
283
+ example: "exampleFlag",
284
+ placeholder: "Enter flag value",
285
+ clean: (value) => value
286
+ });
287
+ const content = (0, _prismatic_io_spectral.input)({
288
+ label: "Message Content",
289
+ type: "string",
290
+ required: true,
291
+ comments: "The raw RFC 822 formatted message content to append.",
292
+ example: `
293
+ From: someone@<yourcompany>.com
294
+ Subject: A basic RFC 850 formatted message
295
+ Newsgroups: comp.<yourcompany>.test
296
+
297
+ The body of this message is plain text. Note the blank line
298
+ between the header information and the body of the message.
299
+ `,
300
+ placeholder: "Enter message content",
301
+ clean: _prismatic_io_spectral.util.types.toString
302
+ });
303
+ const messageIndex = (0, _prismatic_io_spectral.input)({
304
+ label: "Message UID",
305
+ type: "string",
306
+ required: true,
307
+ example: "5",
308
+ comments: "The UID of the message.",
309
+ placeholder: "Enter message UID",
310
+ clean: _prismatic_io_spectral.util.types.toString
311
+ });
312
+ //#endregion
313
+ //#region src/inputs/actions.ts
314
+ const from = (0, _prismatic_io_spectral.input)({
315
+ label: "From",
316
+ type: "string",
317
+ required: false,
318
+ comments: "Filter email messages by sender.",
319
+ example: "someone@example.com",
320
+ placeholder: "Enter sender email address",
321
+ clean: _prismatic_io_spectral.util.types.toString
322
+ });
323
+ const to = (0, _prismatic_io_spectral.input)({
324
+ label: "To",
325
+ type: "string",
326
+ required: false,
327
+ comments: "Filter email messages by recipient.",
328
+ example: "someone@example.com",
329
+ placeholder: "Enter recipient email address",
330
+ clean: _prismatic_io_spectral.util.types.toString
331
+ });
332
+ const readUnread = (0, _prismatic_io_spectral.input)({
333
+ label: "Read / Unread Filter",
334
+ type: "string",
335
+ required: true,
336
+ default: "all",
337
+ comments: "Filter messages by read or unread status.",
338
+ model: [
339
+ {
340
+ label: "Show all messages",
341
+ value: "all"
342
+ },
343
+ {
344
+ label: "Show only unread messages",
345
+ value: "unread"
346
+ },
347
+ {
348
+ label: "Show only read messages",
349
+ value: "read"
350
+ }
351
+ ],
352
+ clean: _prismatic_io_spectral.util.types.toString
353
+ });
354
+ const filterOptions = (0, _prismatic_io_spectral.input)({
355
+ label: "Filter Options",
356
+ type: "code",
357
+ language: "json",
358
+ required: false,
359
+ comments: "Extra parameters to filter the search results.",
360
+ placeholder: "Enter filter options as JSON",
361
+ example: JSON.stringify({
362
+ recent: true,
363
+ subject: "example",
364
+ from: "someone@example.com",
365
+ to: "someone@example.com",
366
+ since: "2025-01-01",
367
+ before: "2025-01-01"
368
+ }, null, 2),
369
+ clean: _prismatic_io_spectral.util.types.toObject
370
+ });
371
+ const addFlagsInputs = {
372
+ connection,
373
+ mailbox,
374
+ range,
375
+ flags
376
+ };
377
+ const appendMessageInputs = {
378
+ connection,
379
+ mailbox,
380
+ path,
381
+ content
382
+ };
383
+ const copyMessageInputs = {
384
+ connection,
385
+ mailbox,
386
+ range,
387
+ path: {
388
+ ...path,
389
+ label: "New Path"
390
+ }
391
+ };
392
+ const createMailboxInputs = {
393
+ connection,
394
+ path
395
+ };
396
+ const deleteMessageInputs = {
397
+ connection,
398
+ mailbox,
399
+ messageIndex
400
+ };
401
+ const downloadMessageInputs = {
402
+ connection,
403
+ mailbox,
404
+ messageIndex: {
405
+ ...messageIndex,
406
+ label: "Message Index or ID",
407
+ comments: "The index of the message you would like to download (1 for the oldest message, 2 for second oldest, etc), or the ID of the message."
408
+ }
409
+ };
410
+ const getStatusInputs = {
411
+ connection,
412
+ mailbox
413
+ };
414
+ const listMailboxesInputs = { connection };
415
+ const removeFlagsInputs = {
416
+ connection,
417
+ mailbox,
418
+ range,
419
+ flags
420
+ };
421
+ const renameMailboxInputs = {
422
+ connection,
423
+ path,
424
+ newPath: {
425
+ ...path,
426
+ label: "New Path"
427
+ }
428
+ };
429
+ const searchMailboxInputs = {
430
+ connection,
431
+ mailbox,
432
+ from,
433
+ to,
434
+ readUnread,
435
+ filterOptions
436
+ };
437
+ const setFlagsInputs = {
438
+ connection,
439
+ mailbox,
440
+ range,
441
+ flags
442
+ };
443
+ //#endregion
444
+ //#region src/actions/index.ts
445
+ var actions_default = {
446
+ listMailboxes: (0, _prismatic_io_spectral.action)({
447
+ display: {
448
+ label: "List Mailboxes",
449
+ description: "Returns a list of available mailboxes"
450
+ },
451
+ perform: async (context, params) => {
452
+ const client = createClient(params.connection, context.debug.enabled);
453
+ await client.connect();
454
+ try {
455
+ return { data: await client.list() };
456
+ } finally {
457
+ client.close();
458
+ }
459
+ },
460
+ inputs: listMailboxesInputs,
461
+ examplePayload: listMailboxesExamplePayload
462
+ }),
463
+ getStatus: (0, _prismatic_io_spectral.action)({
464
+ display: {
465
+ label: "Get Mailbox Status",
466
+ description: "Returns the status of a mailbox's properties"
467
+ },
468
+ perform: async (context, params) => {
469
+ const client = createClient(params.connection, context.debug.enabled);
470
+ await client.connect();
471
+ try {
472
+ const status = await client.status(_prismatic_io_spectral.util.types.toString(params.mailbox), {
473
+ unseen: true,
474
+ messages: true,
475
+ highestModseq: true,
476
+ recent: true,
477
+ uidNext: true,
478
+ uidValidity: true
479
+ });
480
+ return { data: JSON.parse(JSON.stringify(status, (_key, value) => typeof value === "bigint" ? value.toString() : value)) };
481
+ } finally {
482
+ client.close();
483
+ }
484
+ },
485
+ inputs: getStatusInputs,
486
+ examplePayload: getStatusExamplePayload
487
+ }),
488
+ addFlags: (0, _prismatic_io_spectral.action)({
489
+ display: {
490
+ label: "Add Flags",
491
+ description: "Add new flags to an existing message"
492
+ },
493
+ perform: async (context, params) => {
494
+ const client = createClient(params.connection, context.debug.enabled);
495
+ await client.connect();
496
+ try {
497
+ await client.mailboxOpen(_prismatic_io_spectral.util.types.toString(params.mailbox));
498
+ return { data: await client.messageFlagsAdd(_prismatic_io_spectral.util.types.toString(params.range), params.flags.map((flag) => _prismatic_io_spectral.util.types.toString(flag)), { uid: true }) };
499
+ } finally {
500
+ client.close();
501
+ }
502
+ },
503
+ inputs: addFlagsInputs,
504
+ examplePayload: addFlagsExamplePayload
505
+ }),
506
+ appendMessage: (0, _prismatic_io_spectral.action)({
507
+ display: {
508
+ label: "Append Message",
509
+ description: "Appends a new message to an existing mailbox"
510
+ },
511
+ perform: async (context, params) => {
512
+ const client = createClient(params.connection, context.debug.enabled);
513
+ await client.connect();
514
+ try {
515
+ const data = await client.append(_prismatic_io_spectral.util.types.toString(params.path), Buffer.from(_prismatic_io_spectral.util.types.toString(params.content)));
516
+ return { data: JSON.parse(JSON.stringify(data, (_key, value) => typeof value === "bigint" ? value.toString() : value)) };
517
+ } finally {
518
+ client.close();
519
+ }
520
+ },
521
+ inputs: appendMessageInputs,
522
+ examplePayload: appendMessageExamplePayload
523
+ }),
524
+ copyMessage: (0, _prismatic_io_spectral.action)({
525
+ display: {
526
+ label: "Copy Message",
527
+ description: "Copies a message from one mailbox to another."
528
+ },
529
+ perform: async (context, params) => {
530
+ const client = createClient(params.connection, context.debug.enabled);
531
+ await client.connect();
532
+ try {
533
+ await client.mailboxOpen(_prismatic_io_spectral.util.types.toString(params.mailbox));
534
+ const data = await client.messageCopy(_prismatic_io_spectral.util.types.toString(params.range), _prismatic_io_spectral.util.types.toString(params.path), { uid: true });
535
+ if (data) return { data: {
536
+ ...data,
537
+ uidValidity: data.uidValidity?.toString()
538
+ } };
539
+ else throw new Error("An error occurred copying the message. Check your message ID and that your destination inbox exists.");
540
+ } finally {
541
+ client.close();
542
+ }
543
+ },
544
+ examplePayload: copyMessageExamplePayload,
545
+ inputs: copyMessageInputs
546
+ }),
547
+ createMailbox: (0, _prismatic_io_spectral.action)({
548
+ display: {
549
+ label: "Create Mailbox",
550
+ description: "Creates a new mailbox folder and sets up subscription for the created mailbox"
551
+ },
552
+ perform: async (context, params) => {
553
+ const client = createClient(params.connection, context.debug.enabled);
554
+ await client.connect();
555
+ try {
556
+ return { data: await client.mailboxCreate(_prismatic_io_spectral.util.types.toString(params.path)) };
557
+ } finally {
558
+ client.close();
559
+ }
560
+ },
561
+ inputs: createMailboxInputs,
562
+ examplePayload: createMailboxExamplePayload
563
+ }),
564
+ deleteMessage: (0, _prismatic_io_spectral.action)({
565
+ display: {
566
+ label: "Delete Message",
567
+ description: "Delete an existing message"
568
+ },
569
+ perform: async (context, params) => {
570
+ const client = createClient(params.connection, context.debug.enabled);
571
+ await client.connect();
572
+ try {
573
+ await client.mailboxOpen(_prismatic_io_spectral.util.types.toString(params.mailbox));
574
+ return { data: await client.messageDelete(_prismatic_io_spectral.util.types.toString(params.messageIndex), { uid: true }) };
575
+ } finally {
576
+ client.close();
577
+ }
578
+ },
579
+ inputs: deleteMessageInputs,
580
+ examplePayload: deleteMessageExamplePayload
581
+ }),
582
+ downloadMessage: (0, _prismatic_io_spectral.action)({
583
+ display: {
584
+ label: "Download Message",
585
+ description: "Download either full RFC-822 formatted message or a specific body structure part"
586
+ },
587
+ perform: async (context, params) => {
588
+ const client = createClient(params.connection, context.debug.enabled);
589
+ await client.connect();
590
+ try {
591
+ await client.getMailboxLock(_prismatic_io_spectral.util.types.toString(params.mailbox));
592
+ const { content, meta } = await client.download(params.messageIndex, "", { uid: true });
593
+ const parsed = await (0, mailparser.simpleParser)(content, {
594
+ writableObjectMode: true,
595
+ autoDestroy: true
596
+ });
597
+ return { data: {
598
+ meta,
599
+ message: {
600
+ headers: Object.fromEntries(parsed.headers),
601
+ attachments: parsed.attachments.map(({ contentType, content }) => ({ file: {
602
+ contentType,
603
+ data: content
604
+ } })),
605
+ attachmentsMetadata: parsed.attachments.map(({ filename, size, checksum, headers, related }) => ({
606
+ filename,
607
+ size,
608
+ checksum,
609
+ headers,
610
+ related
611
+ })),
612
+ text: parsed.text,
613
+ html: parsed.html
614
+ }
615
+ } };
616
+ } finally {
617
+ client.close();
618
+ }
619
+ },
620
+ inputs: downloadMessageInputs,
621
+ examplePayload: downloadMessageExamplePayload
622
+ }),
623
+ removeFlags: (0, _prismatic_io_spectral.action)({
624
+ display: {
625
+ label: "Remove Flags From Message",
626
+ description: "Remove existing flags from an existing message"
627
+ },
628
+ perform: async (context, params) => {
629
+ const client = createClient(params.connection, context.debug.enabled);
630
+ await client.connect();
631
+ try {
632
+ await client.mailboxOpen(_prismatic_io_spectral.util.types.toString(params.mailbox));
633
+ return { data: await client.messageFlagsRemove(_prismatic_io_spectral.util.types.toString(params.range), params.flags.map((flag) => _prismatic_io_spectral.util.types.toString(flag)), { uid: true }) };
634
+ } finally {
635
+ client.close();
636
+ }
637
+ },
638
+ inputs: removeFlagsInputs,
639
+ examplePayload: removeFlagsExamplePayload
640
+ }),
641
+ renameMailbox: (0, _prismatic_io_spectral.action)({
642
+ display: {
643
+ label: "Rename Mailbox",
644
+ description: "Change the name of an existing mailbox"
645
+ },
646
+ perform: async (context, params) => {
647
+ const client = createClient(params.connection, context.debug.enabled);
648
+ await client.connect();
649
+ try {
650
+ return { data: await client.mailboxRename(_prismatic_io_spectral.util.types.toString(params.path), _prismatic_io_spectral.util.types.toString(params.newPath)) };
651
+ } finally {
652
+ client.close();
653
+ }
654
+ },
655
+ inputs: renameMailboxInputs,
656
+ examplePayload: renameMailboxExamplePayload
657
+ }),
658
+ searchMailbox: (0, _prismatic_io_spectral.action)({
659
+ display: {
660
+ label: "Search / List Mailbox Messages",
661
+ description: "Returns all messages in the given mailbox"
662
+ },
663
+ perform: async (context, params) => {
664
+ const client = createClient(params.connection, context.debug.enabled);
665
+ await client.connect();
666
+ try {
667
+ await client.getMailboxLock(_prismatic_io_spectral.util.types.toString(params.mailbox));
668
+ const options = {
669
+ from: _prismatic_io_spectral.util.types.toString(params.from) || void 0,
670
+ to: _prismatic_io_spectral.util.types.toString(params.to) || void 0,
671
+ ...params.filterOptions
672
+ };
673
+ if (params.readUnread === "unread") options.seen = false;
674
+ if (params.readUnread === "read") options.seen = true;
675
+ if (params.readUnread === "all") options.all = true;
676
+ return { data: await client.search(options, { uid: true }) };
677
+ } finally {
678
+ client.close();
679
+ }
680
+ },
681
+ inputs: searchMailboxInputs,
682
+ examplePayload: searchMailboxExamplePayload
683
+ }),
684
+ setFlags: (0, _prismatic_io_spectral.action)({
685
+ display: {
686
+ label: "Set Flags",
687
+ description: "Set a value for an existing message flag"
688
+ },
689
+ perform: async (context, params) => {
690
+ const client = createClient(params.connection, context.debug.enabled);
691
+ await client.connect();
692
+ try {
693
+ return { data: await client.messageFlagsSet(_prismatic_io_spectral.util.types.toString(params.range), params.flags.map((flag) => _prismatic_io_spectral.util.types.toString(flag)), { uid: true }) };
694
+ } finally {
695
+ client.close();
696
+ }
697
+ },
698
+ inputs: setFlagsInputs,
699
+ examplePayload: setFlagsExamplePayload
700
+ })
701
+ };
702
+ //#endregion
703
+ //#region src/inputs/dataSources.ts
704
+ const listMailboxesDataSourceInputs = { connection };
705
+ //#endregion
706
+ //#region src/dataSources/index.ts
707
+ var dataSources_default = { listMailboxes: (0, _prismatic_io_spectral.dataSource)({
708
+ display: {
709
+ label: "List Mailboxes",
710
+ description: "Returns a picklist of available mailboxes that users can choose from"
711
+ },
712
+ dataSourceType: "picklist",
713
+ perform: async (_context, params) => {
714
+ const client = createClient(params.connection, false);
715
+ await client.connect();
716
+ try {
717
+ return { result: (await client.list()).map((mailbox) => ({
718
+ key: mailbox.path,
719
+ label: mailbox.name
720
+ })) };
721
+ } finally {
722
+ client.close();
723
+ }
724
+ },
725
+ inputs: listMailboxesDataSourceInputs
726
+ }) };
727
+ //#endregion
728
+ //#region src/constants.ts
729
+ const LOOK_BACK_DATE_PATTERN = /^\d{4}-\d{2}-\d{2}$/;
730
+ //#endregion
731
+ //#region src/util/polling.ts
732
+ const lookBackDateClean = (value) => {
733
+ const str = _prismatic_io_spectral.util.types.toString(value).trim();
734
+ if (!str) return "";
735
+ if (!LOOK_BACK_DATE_PATTERN.test(str)) throw new Error("Look-back Date must be in YYYY-MM-DD format.");
736
+ const parts = str.split("-");
737
+ const year = _prismatic_io_spectral.util.types.toNumber(parts[0]);
738
+ const month = _prismatic_io_spectral.util.types.toNumber(parts[1]);
739
+ const day = _prismatic_io_spectral.util.types.toNumber(parts[2]);
740
+ const parsed = new Date(year, month - 1, day);
741
+ if (parsed.getFullYear() !== year || parsed.getMonth() !== month - 1 || parsed.getDate() !== day) throw new Error(`Look-back Date "${str}" is not a valid calendar date.`);
742
+ if (parsed > /* @__PURE__ */ new Date()) throw new Error("Look-back Date cannot be a future date.");
743
+ return str;
744
+ };
745
+ const resolveImapRecordChanges = (data) => {
746
+ if (!data || !Array.isArray(data)) return [];
747
+ return data.map((record) => ({
748
+ changeType: "created",
749
+ record
750
+ }));
751
+ };
752
+ //#endregion
753
+ //#region src/inputs/triggers.ts
754
+ const fetchContent = (0, _prismatic_io_spectral.input)({
755
+ label: "Fetch Content",
756
+ type: "boolean",
757
+ required: false,
758
+ default: "false",
759
+ comments: "When enabled, downloads and parses the full message body for each new email.",
760
+ clean: _prismatic_io_spectral.util.types.toBool
761
+ });
762
+ const markAsRead = (0, _prismatic_io_spectral.input)({
763
+ label: "Mark as Read",
764
+ type: "boolean",
765
+ required: false,
766
+ default: "false",
767
+ comments: "When enabled, sets the Seen flag on new emails after polling.",
768
+ clean: _prismatic_io_spectral.util.types.toBool
769
+ });
770
+ const newEmailsPollingTriggerInputs = {
771
+ connection,
772
+ mailbox,
773
+ lookBackDate: (0, _prismatic_io_spectral.input)({
774
+ label: "Look-back Date",
775
+ placeholder: "Enter look-back date (YYYY-MM-DD)",
776
+ type: "string",
777
+ required: false,
778
+ comments: "The date the initial sync starts from, in YYYY-MM-DD format. Cannot be a future date. Leave empty to start from the first recurrence with no backfill. When set, the initial sync delivers each email received on or after this date once.",
779
+ example: "2026-01-01",
780
+ clean: lookBackDateClean
781
+ }),
782
+ fetchContent,
783
+ markAsRead
784
+ };
785
+ //#endregion
786
+ //#region src/triggers/index.ts
787
+ var triggers_default = { newEmailsPollingTrigger: (0, _prismatic_io_spectral.pollingTrigger)({
788
+ display: {
789
+ label: "New Emails",
790
+ description: "Retrieves existing and new emails for a specified IMAP mailbox. Load history once, check for changes on a schedule, or both."
791
+ },
792
+ inputs: newEmailsPollingTriggerInputs,
793
+ triggerResolverSupport: "valid",
794
+ batchConfig: { batchSize: 50 },
795
+ triggerResolver: { resolveItems: (_context, { payload }) => resolveImapRecordChanges(payload.body.data) },
796
+ perform: async (context, payload, { connection, fetchContent, mailbox, markAsRead, lookBackDate }) => {
797
+ const now = (/* @__PURE__ */ new Date()).toISOString();
798
+ const client = createClient(connection, context.debug.enabled);
799
+ await client.connect();
800
+ try {
801
+ const mailboxName = mailbox;
802
+ const status = await client.status(mailboxName, {
803
+ uidNext: true,
804
+ uidValidity: true,
805
+ messages: true,
806
+ recent: true,
807
+ unseen: true,
808
+ highestModseq: true
809
+ });
810
+ const currentUidNext = status.uidNext ?? 0;
811
+ const currentUidValidity = typeof status.uidValidity === "bigint" ? _prismatic_io_spectral.util.types.toString(status.uidValidity) : _prismatic_io_spectral.util.types.toString(status.uidValidity ?? "");
812
+ const state = context.polling.getState();
813
+ const isFirstPoll = !state.lastUidNext || state.uidValidity !== currentUidValidity;
814
+ if (isFirstPoll && !lookBackDate) {
815
+ context.polling.setState({
816
+ lastUidNext: currentUidNext,
817
+ uidValidity: currentUidValidity,
818
+ lastPolledAt: now
819
+ });
820
+ return {
821
+ payload: {
822
+ ...payload,
823
+ body: { data: [] }
824
+ },
825
+ polledNoChanges: true
826
+ };
827
+ }
828
+ if (state.lastUidNext !== void 0 && currentUidNext <= state.lastUidNext) {
829
+ context.polling.setState({
830
+ ...state,
831
+ lastPolledAt: now
832
+ });
833
+ return {
834
+ payload: {
835
+ ...payload,
836
+ body: { data: [] }
837
+ },
838
+ polledNoChanges: true
839
+ };
840
+ }
841
+ await client.getMailboxLock(mailboxName);
842
+ const shouldFetchContent = fetchContent;
843
+ const shouldMarkAsRead = markAsRead;
844
+ let uidRange;
845
+ if (isFirstPoll && lookBackDate) {
846
+ const searchDate = new Date(lookBackDate);
847
+ const uids = await client.search({ since: searchDate }, { uid: true });
848
+ if (!uids || uids.length === 0) {
849
+ context.polling.setState({
850
+ lastUidNext: currentUidNext,
851
+ uidValidity: currentUidValidity,
852
+ lastPolledAt: now
853
+ });
854
+ return {
855
+ payload: {
856
+ ...payload,
857
+ body: { data: [] }
858
+ },
859
+ polledNoChanges: true
860
+ };
861
+ }
862
+ uidRange = `${Math.min(...uids)}:*`;
863
+ } else uidRange = `${state.lastUidNext}:*`;
864
+ const rawMessages = [];
865
+ for await (const message of client.fetch(uidRange, {
866
+ uid: true,
867
+ envelope: true,
868
+ flags: true,
869
+ internalDate: true,
870
+ size: true,
871
+ source: shouldFetchContent
872
+ }, { uid: true })) rawMessages.push(message);
873
+ const emails = await Promise.all(rawMessages.map(async (message) => {
874
+ const email = {
875
+ uid: message.uid,
876
+ envelope: message.envelope,
877
+ flags: [...message.flags ?? []],
878
+ internalDate: message.internalDate,
879
+ size: message.size
880
+ };
881
+ if (shouldFetchContent && message.source) {
882
+ const parsed = await (0, mailparser.simpleParser)(message.source);
883
+ email.text = parsed.text;
884
+ email.html = parsed.html;
885
+ email.attachments = parsed.attachments.map(({ filename, size, contentType }) => ({
886
+ filename,
887
+ size,
888
+ contentType
889
+ }));
890
+ }
891
+ return email;
892
+ }));
893
+ if (shouldMarkAsRead && emails.length > 0) await client.messageFlagsAdd(uidRange, ["\\Seen"], { uid: true });
894
+ context.polling.setState({
895
+ lastUidNext: currentUidNext,
896
+ uidValidity: currentUidValidity,
897
+ lastPolledAt: now
898
+ });
899
+ return {
900
+ payload: {
901
+ ...payload,
902
+ body: { data: emails }
903
+ },
904
+ polledNoChanges: emails.length === 0
905
+ };
906
+ } finally {
907
+ client.close();
908
+ }
909
+ }
910
+ }) };
911
+ //#endregion
912
+ //#region src/index.ts
913
+ var src_default = (0, _prismatic_io_spectral.component)({
914
+ key: "imap",
915
+ public: true,
916
+ documentationUrl: "https://prismatic.io/docs/components/imap/",
917
+ display: {
918
+ category: "Application Connectors",
919
+ label: "IMAP",
920
+ description: "Interact with your IMAP email account",
921
+ iconPath: "icon.png"
922
+ },
923
+ hooks: { error: _prismatic_io_spectral_http.handleErrors },
924
+ actions: actions_default,
925
+ triggers: triggers_default,
926
+ dataSources: dataSources_default,
927
+ connections: connections_default
928
+ });
929
+ //#endregion
930
+ //#region npm-dist/.entry.ts
931
+ var _entry_default = (0, _prismatic_io_spectral.callableComponent)(src_default);
932
+ //#endregion
933
+ module.exports = _entry_default;