n8n-nodes-jmap 0.2.2 → 0.2.4

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.
package/README.md CHANGED
@@ -4,7 +4,7 @@ Community node for [n8n](https://n8n.io/) to interact with JMAP email servers ([
4
4
 
5
5
  Compatible with:
6
6
  - [Apache James](https://james.apache.org/)
7
- - [Twake Mail](https://twake.app/)
7
+ - [Twake Mail](https://twake.app/) by [LINAGORA](https://linagora.com/)
8
8
  - [Stalwart Mail Server](https://stalw.art/)
9
9
  - [Fastmail](https://www.fastmail.com/)
10
10
  - Any JMAP-compliant email server
@@ -119,7 +119,8 @@ Main node for email operations.
119
119
  | Email | Send | Send a new email |
120
120
  | Email | Reply | Reply to an existing email |
121
121
  | Email | Get | Retrieve an email by ID |
122
- | Email | Get Many | List emails (with optional mailbox filter) |
122
+ | Email | Get Many | List emails with advanced search filters |
123
+ | Email | Get Attachments | Download attachments as binary data |
123
124
  | Email | Create Draft | Create a draft without sending |
124
125
  | Email | Delete | Delete an email |
125
126
  | Email | Mark as Read | Mark email as read |
@@ -149,9 +150,92 @@ Polling-based trigger for new emails.
149
150
 
150
151
  ---
151
152
 
152
- ## Development
153
+ ## Features
154
+
155
+ ### Advanced Email Search
156
+
157
+ The **Get Many** operation supports powerful search filters based on JMAP RFC 8621:
158
+
159
+ | Filter | Description |
160
+ |--------|-------------|
161
+ | **Received After** | Emails received after a specific date |
162
+ | **Received Before** | Emails received before a specific date |
163
+ | **From Contains** | Filter by sender address |
164
+ | **To Contains** | Filter by recipient address |
165
+ | **Subject Contains** | Filter by subject line |
166
+ | **Full Text Search** | Search in subject, body, and addresses |
167
+ | **Has Attachment** | Only emails with attachments |
168
+ | **Unread Only** | Only unread emails |
169
+ | **Flagged Only** | Only starred/flagged emails |
170
+
171
+ Combine multiple filters for precise email retrieval.
172
+
173
+ ### Attachment Handling
174
+
175
+ The **Get Attachments** operation downloads email attachments as binary data, ready to use with other n8n nodes:
176
+
177
+ - **Inline image filtering**: Exclude embedded images (signatures, logos) by default
178
+ - **MIME type filtering**: Filter by file type (e.g., `application/pdf`, `image/*`)
179
+ - **Native compatibility**: Works seamlessly with n8n's Compression, Google Drive, S3, and other nodes
180
+
181
+ Example workflow: `JMAP Trigger` > `Get Attachments` > `Compression` (extract ZIP) > `Google Drive` (upload)
182
+
183
+ ---
184
+
185
+ ## AI Agent Integration
186
+
187
+ This node can be used as a tool by n8n AI Agents, enabling autonomous email operations.
188
+
189
+ ### Setup
190
+
191
+ 1. Ensure you're using n8n version 1.x or later
192
+ 2. The node will automatically appear in the AI Agent's tool list
193
+
194
+ ### Example Use Cases
195
+
196
+ - **Email assistant**: Let the AI read, search, and respond to emails
197
+ - **Automated triage**: AI categorizes and labels incoming emails
198
+ - **Smart notifications**: AI analyzes email content and triggers actions
199
+
200
+ ### Supported Operations as AI Tool
201
+
202
+ The AI Agent can use all JMAP operations:
203
+ - Search emails with natural language queries
204
+ - Read and analyze email content
205
+ - Send replies based on context
206
+ - Organize emails (labels, folders, flags)
207
+ - Download and process attachments
208
+
209
+ ---
210
+
211
+ ## Contributing
212
+
213
+ Contributions are welcome! This project is open source and we encourage the community to help improve it.
214
+
215
+ ### How to Contribute
216
+
217
+ 1. **Fork** the repository
218
+ 2. **Create a branch** for your feature or fix: `git checkout -b feature/my-feature`
219
+ 3. **Make your changes** and test them locally
220
+ 4. **Run linting**: `npm run lint`
221
+ 5. **Commit** with a clear message
222
+ 6. **Push** to your fork and open a **Pull Request**
223
+
224
+ ### Ideas for Contributions
225
+
226
+ - Support for additional JMAP capabilities (Calendar, Contacts)
227
+ - Improved error handling and messages
228
+ - Additional search filters
229
+ - Documentation improvements
230
+ - Bug fixes and optimizations
231
+
232
+ ### Local Development
153
233
 
154
234
  ```bash
235
+ # Clone your fork
236
+ git clone https://github.com/YOUR_USERNAME/n8n-nodes-jmap.git
237
+ cd n8n-nodes-jmap
238
+
155
239
  # Install dependencies
156
240
  npm install
157
241
 
@@ -168,14 +252,11 @@ npm run lint
168
252
  npm run format
169
253
  ```
170
254
 
171
- ### Local Testing
255
+ ### Testing Locally with n8n
172
256
 
173
257
  ```bash
174
- # Link for local n8n development
175
- npm link
176
-
177
- # In your n8n installation
178
- npm link n8n-nodes-jmap
258
+ # Start n8n with the local node
259
+ N8N_CUSTOM_EXTENSIONS="/path/to/n8n-nodes-jmap" n8n start
179
260
  ```
180
261
 
181
262
  ---
@@ -201,4 +282,6 @@ AGPL-3.0
201
282
 
202
283
  ## Author
203
284
 
204
- [Michel-Marie Maudet](https://github.com/mmaudet)
285
+ [Michel-Marie MAUDET](https://github.com/mmaudet)
286
+
287
+ This project is developed with the support of [LINAGORA](https://linagora.com/) and [Twake](https://twake.app/).
@@ -501,7 +501,11 @@ async function getAttachments(accountId, emailId, options = {}) {
501
501
  let attachmentIndex = 0;
502
502
  for (const attachment of attachments) {
503
503
  // Filter by inline status
504
- if (attachment.isInline && !includeInline) {
504
+ // An attachment is considered inline if:
505
+ // - isInline is explicitly true, OR
506
+ // - it has a cid (Content-ID) which is used for inline images in HTML
507
+ const isInlineAttachment = attachment.isInline === true || (attachment.cid !== undefined && attachment.cid !== null);
508
+ if (isInlineAttachment && !includeInline) {
505
509
  continue;
506
510
  }
507
511
  // Filter by MIME type
@@ -523,7 +527,8 @@ async function getAttachments(accountId, emailId, options = {}) {
523
527
  fileName: attachment.name,
524
528
  mimeType: attachment.type,
525
529
  fileSize: attachment.size,
526
- isInline: attachment.isInline || false,
530
+ isInline: isInlineAttachment,
531
+ cid: attachment.cid || null,
527
532
  },
528
533
  binary: {
529
534
  file: binaryData,
@@ -5,12 +5,14 @@ const n8n_workflow_1 = require("n8n-workflow");
5
5
  const GenericFunctions_1 = require("./GenericFunctions");
6
6
  class Jmap {
7
7
  constructor() {
8
+ // @ts-ignore - usableAsTool not in type definitions
8
9
  this.description = {
9
10
  displayName: 'JMAP',
10
11
  name: 'jmap',
11
12
  icon: 'file:jmap.svg',
12
13
  group: ['transform'],
13
14
  version: 1,
15
+ usableAsTool: true,
14
16
  subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
15
17
  description: 'Interact with JMAP email servers (Apache James, Twake Mail, etc.)',
16
18
  defaults: {
@@ -464,6 +466,89 @@ class Jmap {
464
466
  default: 50,
465
467
  description: 'Max number of results to return',
466
468
  },
469
+ // Options for getMany (search filters)
470
+ {
471
+ displayName: 'Options',
472
+ name: 'getManyOptions',
473
+ type: 'collection',
474
+ placeholder: 'Add Option',
475
+ default: {},
476
+ displayOptions: {
477
+ show: {
478
+ resource: ['email'],
479
+ operation: ['getMany'],
480
+ },
481
+ },
482
+ options: [
483
+ {
484
+ displayName: 'Flagged Only',
485
+ name: 'flaggedOnly',
486
+ type: 'boolean',
487
+ default: false,
488
+ description: 'Whether to return only flagged/starred emails',
489
+ },
490
+ {
491
+ displayName: 'From Contains',
492
+ name: 'from',
493
+ type: 'string',
494
+ default: '',
495
+ placeholder: 'sender@example.com',
496
+ description: 'Filter emails where the From address contains this text',
497
+ },
498
+ {
499
+ displayName: 'Full Text Search',
500
+ name: 'text',
501
+ type: 'string',
502
+ default: '',
503
+ placeholder: 'search terms',
504
+ description: 'Search in subject, body, and addresses',
505
+ },
506
+ {
507
+ displayName: 'Has Attachment',
508
+ name: 'hasAttachment',
509
+ type: 'boolean',
510
+ default: false,
511
+ description: 'Whether to return only emails with attachments',
512
+ },
513
+ {
514
+ displayName: 'Received After',
515
+ name: 'after',
516
+ type: 'dateTime',
517
+ default: '',
518
+ description: 'Filter emails received after this date',
519
+ },
520
+ {
521
+ displayName: 'Received Before',
522
+ name: 'before',
523
+ type: 'dateTime',
524
+ default: '',
525
+ description: 'Filter emails received before this date',
526
+ },
527
+ {
528
+ displayName: 'Subject Contains',
529
+ name: 'subject',
530
+ type: 'string',
531
+ default: '',
532
+ placeholder: 'Invoice',
533
+ description: 'Filter emails where the subject contains this text',
534
+ },
535
+ {
536
+ displayName: 'To Contains',
537
+ name: 'to',
538
+ type: 'string',
539
+ default: '',
540
+ placeholder: 'recipient@example.com',
541
+ description: 'Filter emails where the To address contains this text',
542
+ },
543
+ {
544
+ displayName: 'Unread Only',
545
+ name: 'unreadOnly',
546
+ type: 'boolean',
547
+ default: false,
548
+ description: 'Whether to return only unread emails',
549
+ },
550
+ ],
551
+ },
467
552
  // ==================== MAILBOX PARAMETERS ====================
468
553
  {
469
554
  displayName: 'Mailbox ID',
@@ -630,10 +715,42 @@ class Jmap {
630
715
  if (operation === 'getMany') {
631
716
  const mailbox = this.getNodeParameter('mailbox', i);
632
717
  const limit = this.getNodeParameter('limit', i);
718
+ const options = this.getNodeParameter('getManyOptions', i);
633
719
  const filter = {};
720
+ // Mailbox filter
634
721
  if (mailbox) {
635
722
  filter.inMailbox = mailbox;
636
723
  }
724
+ // Date filters
725
+ if (options.after) {
726
+ filter.after = new Date(options.after).toISOString();
727
+ }
728
+ if (options.before) {
729
+ filter.before = new Date(options.before).toISOString();
730
+ }
731
+ // Content filters
732
+ if (options.from) {
733
+ filter.from = options.from;
734
+ }
735
+ if (options.to) {
736
+ filter.to = options.to;
737
+ }
738
+ if (options.subject) {
739
+ filter.subject = options.subject;
740
+ }
741
+ if (options.text) {
742
+ filter.text = options.text;
743
+ }
744
+ // Boolean filters
745
+ if (options.hasAttachment) {
746
+ filter.hasAttachment = true;
747
+ }
748
+ if (options.unreadOnly) {
749
+ filter.notKeyword = '$seen';
750
+ }
751
+ if (options.flaggedOnly) {
752
+ filter.hasKeyword = '$flagged';
753
+ }
637
754
  const { ids } = await GenericFunctions_1.queryEmails.call(this, accountId, filter, [{ property: 'receivedAt', isAscending: false }], limit);
638
755
  if (ids.length > 0) {
639
756
  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.2",
3
+ "version": "0.2.4",
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",