n8n-nodes-jmap 0.2.1 → 0.2.3

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.
@@ -123,11 +123,12 @@ export declare function downloadBlob(this: IExecuteFunctions, accountId: string,
123
123
  * Interface for attachment options
124
124
  */
125
125
  export interface IAttachmentOptions {
126
- extractArchives?: boolean;
127
126
  includeInline?: boolean;
128
127
  mimeTypeFilter?: string;
129
128
  }
130
129
  /**
131
- * Get attachments from an email and return them as binary data
130
+ * Get attachments from an email and return them as binary data.
131
+ * Each attachment is returned as a separate item with binary data in the 'file' field.
132
+ * To extract archives (ZIP, tar.gz), chain with the n8n Compression node.
132
133
  */
133
134
  export declare function getAttachments(this: IExecuteFunctions, accountId: string, emailId: string, options?: IAttachmentOptions): Promise<INodeExecutionData[]>;
@@ -473,60 +473,12 @@ function matchesMimeType(mimeType, filter) {
473
473
  return normalizedMime === normalizedFilter;
474
474
  }
475
475
  /**
476
- * Check if a MIME type is a ZIP archive
477
- */
478
- function isZipMimeType(mimeType) {
479
- const zipTypes = [
480
- 'application/zip',
481
- 'application/x-zip-compressed',
482
- 'application/x-zip',
483
- ];
484
- return zipTypes.includes(mimeType.toLowerCase());
485
- }
486
- /**
487
- * Check if a MIME type is a tar.gz archive
488
- */
489
- function isTarGzMimeType(mimeType) {
490
- const tarGzTypes = [
491
- 'application/gzip',
492
- 'application/x-gzip',
493
- 'application/x-tar',
494
- 'application/x-compressed-tar',
495
- ];
496
- return tarGzTypes.includes(mimeType.toLowerCase());
497
- }
498
- /**
499
- * Check if filename suggests tar.gz
500
- */
501
- function isTarGzFilename(filename) {
502
- const lower = filename.toLowerCase();
503
- return lower.endsWith('.tar.gz') || lower.endsWith('.tgz');
504
- }
505
- /**
506
- * Extract files from a ZIP archive
507
- * Note: Archive extraction is not yet available (planned for future release with self-hosted support)
508
- * Returns empty array, causing the archive to be returned as-is
509
- */
510
- function extractZip(_buffer) {
511
- // Archive extraction not yet implemented
512
- // Will be available in a future release for self-hosted n8n
513
- return [];
514
- }
515
- /**
516
- * Extract files from a tar.gz archive
517
- * Note: Archive extraction is not yet available (planned for future release with self-hosted support)
518
- * Returns empty array, causing the archive to be returned as-is
519
- */
520
- async function extractTarGz(_buffer) {
521
- // Archive extraction not yet implemented
522
- // Will be available in a future release for self-hosted n8n
523
- return [];
524
- }
525
- /**
526
- * Get attachments from an email and return them as binary data
476
+ * Get attachments from an email and return them as binary data.
477
+ * Each attachment is returned as a separate item with binary data in the 'file' field.
478
+ * To extract archives (ZIP, tar.gz), chain with the n8n Compression node.
527
479
  */
528
480
  async function getAttachments(accountId, emailId, options = {}) {
529
- const { extractArchives = false, includeInline = false, mimeTypeFilter = '' } = options;
481
+ const { includeInline = false, mimeTypeFilter = '' } = options;
530
482
  // Get email with attachments metadata
531
483
  const emails = await getEmails.call(this, accountId, [emailId], [
532
484
  'id',
@@ -561,63 +513,17 @@ async function getAttachments(accountId, emailId, options = {}) {
561
513
  }
562
514
  // Download the attachment
563
515
  const buffer = await downloadBlob.call(this, accountId, attachment.blobId, attachment.name, attachment.type);
564
- // Check if this is an archive that should be extracted
565
- const isZip = isZipMimeType(attachment.type);
566
- const isTarGz = isTarGzMimeType(attachment.type) || isTarGzFilename(attachment.name);
567
- if (extractArchives && (isZip || isTarGz)) {
568
- // Extract archive contents
569
- let extractedFiles = [];
570
- try {
571
- if (isZip) {
572
- extractedFiles = extractZip(buffer);
573
- }
574
- else if (isTarGz) {
575
- extractedFiles = await extractTarGz(buffer);
576
- }
577
- }
578
- catch (error) {
579
- // If extraction fails, return the archive as-is
580
- extractedFiles = [];
581
- }
582
- if (extractedFiles.length > 0) {
583
- // Return each extracted file as a separate item
584
- for (const file of extractedFiles) {
585
- const binaryData = await this.helpers.prepareBinaryData(file.data, file.name, file.mimeType);
586
- results.push({
587
- json: {
588
- emailId: email.id,
589
- emailSubject: email.subject,
590
- attachmentIndex,
591
- originalFileName: attachment.name,
592
- fileName: file.name,
593
- mimeType: file.mimeType,
594
- fileSize: file.data.length,
595
- wasExtractedFromArchive: true,
596
- sourceArchiveName: attachment.name,
597
- },
598
- binary: {
599
- file: binaryData,
600
- },
601
- });
602
- attachmentIndex++;
603
- }
604
- continue;
605
- }
606
- // If extraction failed or no files, fall through to return the archive as-is
607
- }
608
- // Return the attachment as-is (not an archive, or extraction disabled/failed)
516
+ // Prepare binary data for n8n
609
517
  const binaryData = await this.helpers.prepareBinaryData(buffer, attachment.name, attachment.type);
610
518
  results.push({
611
519
  json: {
612
520
  emailId: email.id,
613
521
  emailSubject: email.subject,
614
522
  attachmentIndex,
615
- originalFileName: attachment.name,
616
523
  fileName: attachment.name,
617
524
  mimeType: attachment.type,
618
525
  fileSize: attachment.size,
619
- wasExtractedFromArchive: false,
620
- sourceArchiveName: null,
526
+ isInline: attachment.isInline || false,
621
527
  },
622
528
  binary: {
623
529
  file: binaryData,
@@ -429,13 +429,6 @@ class Jmap {
429
429
  },
430
430
  },
431
431
  options: [
432
- {
433
- displayName: 'Extract Archives (Coming Soon)',
434
- name: 'extractArchives',
435
- type: 'boolean',
436
- default: false,
437
- description: 'Extract ZIP and tar.gz archives. Note: This feature is planned for a future release and currently returns archives as-is.',
438
- },
439
432
  {
440
433
  displayName: 'Include Inline Images',
441
434
  name: 'includeInline',
@@ -471,6 +464,89 @@ class Jmap {
471
464
  default: 50,
472
465
  description: 'Max number of results to return',
473
466
  },
467
+ // Options for getMany (search filters)
468
+ {
469
+ displayName: 'Options',
470
+ name: 'getManyOptions',
471
+ type: 'collection',
472
+ placeholder: 'Add Option',
473
+ default: {},
474
+ displayOptions: {
475
+ show: {
476
+ resource: ['email'],
477
+ operation: ['getMany'],
478
+ },
479
+ },
480
+ options: [
481
+ {
482
+ displayName: 'Flagged Only',
483
+ name: 'flaggedOnly',
484
+ type: 'boolean',
485
+ default: false,
486
+ description: 'Whether to return only flagged/starred emails',
487
+ },
488
+ {
489
+ displayName: 'From Contains',
490
+ name: 'from',
491
+ type: 'string',
492
+ default: '',
493
+ placeholder: 'sender@example.com',
494
+ description: 'Filter emails where the From address contains this text',
495
+ },
496
+ {
497
+ displayName: 'Full Text Search',
498
+ name: 'text',
499
+ type: 'string',
500
+ default: '',
501
+ placeholder: 'search terms',
502
+ description: 'Search in subject, body, and addresses',
503
+ },
504
+ {
505
+ displayName: 'Has Attachment',
506
+ name: 'hasAttachment',
507
+ type: 'boolean',
508
+ default: false,
509
+ description: 'Whether to return only emails with attachments',
510
+ },
511
+ {
512
+ displayName: 'Received After',
513
+ name: 'after',
514
+ type: 'dateTime',
515
+ default: '',
516
+ description: 'Filter emails received after this date',
517
+ },
518
+ {
519
+ displayName: 'Received Before',
520
+ name: 'before',
521
+ type: 'dateTime',
522
+ default: '',
523
+ description: 'Filter emails received before this date',
524
+ },
525
+ {
526
+ displayName: 'Subject Contains',
527
+ name: 'subject',
528
+ type: 'string',
529
+ default: '',
530
+ placeholder: 'Invoice',
531
+ description: 'Filter emails where the subject contains this text',
532
+ },
533
+ {
534
+ displayName: 'To Contains',
535
+ name: 'to',
536
+ type: 'string',
537
+ default: '',
538
+ placeholder: 'recipient@example.com',
539
+ description: 'Filter emails where the To address contains this text',
540
+ },
541
+ {
542
+ displayName: 'Unread Only',
543
+ name: 'unreadOnly',
544
+ type: 'boolean',
545
+ default: false,
546
+ description: 'Whether to return only unread emails',
547
+ },
548
+ ],
549
+ },
474
550
  // ==================== MAILBOX PARAMETERS ====================
475
551
  {
476
552
  displayName: 'Mailbox ID',
@@ -637,10 +713,42 @@ class Jmap {
637
713
  if (operation === 'getMany') {
638
714
  const mailbox = this.getNodeParameter('mailbox', i);
639
715
  const limit = this.getNodeParameter('limit', i);
716
+ const options = this.getNodeParameter('getManyOptions', i);
640
717
  const filter = {};
718
+ // Mailbox filter
641
719
  if (mailbox) {
642
720
  filter.inMailbox = mailbox;
643
721
  }
722
+ // Date filters
723
+ if (options.after) {
724
+ filter.after = new Date(options.after).toISOString();
725
+ }
726
+ if (options.before) {
727
+ filter.before = new Date(options.before).toISOString();
728
+ }
729
+ // Content filters
730
+ if (options.from) {
731
+ filter.from = options.from;
732
+ }
733
+ if (options.to) {
734
+ filter.to = options.to;
735
+ }
736
+ if (options.subject) {
737
+ filter.subject = options.subject;
738
+ }
739
+ if (options.text) {
740
+ filter.text = options.text;
741
+ }
742
+ // Boolean filters
743
+ if (options.hasAttachment) {
744
+ filter.hasAttachment = true;
745
+ }
746
+ if (options.unreadOnly) {
747
+ filter.notKeyword = '$seen';
748
+ }
749
+ if (options.flaggedOnly) {
750
+ filter.hasKeyword = '$flagged';
751
+ }
644
752
  const { ids } = await GenericFunctions_1.queryEmails.call(this, accountId, filter, [{ property: 'receivedAt', isAscending: false }], limit);
645
753
  if (ids.length > 0) {
646
754
  responseData = await GenericFunctions_1.getEmails.call(this, accountId, ids);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-jmap",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "description": "n8n community node for JMAP email protocol (RFC 8620/8621) - Works with Apache James, Twake Mail, Fastmail, and other JMAP-compatible servers",
5
5
  "keywords": [
6
6
  "n8n-community-node-package",