imap-search.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. /**
  2. * @node imap-search
  3. * @name IMAP Search
  4. * @category email
  5. * @version 1.0.1
  6. * @description Search and list emails from an IMAP server with various filters.
  7. * @icon search
  8. */
  9. const configSchema = {
  10. type: 'object',
  11. properties: {
  12. credentialId: {
  13. type: 'string',
  14. title: 'IMAP Credential',
  15. description: 'Select the IMAP credential to use for authentication',
  16. dynamicOptions: {
  17. source: 'credentials',
  18. filter: { type: 'imap' }
  19. }
  20. },
  21. mailbox: {
  22. type: 'string',
  23. title: 'Mailbox',
  24. description: 'The mailbox to search (e.g., INBOX, Sent, Drafts)',
  25. default: 'INBOX'
  26. },
  27. criteria: {
  28. type: 'string',
  29. title: 'Search Criteria',
  30. description: 'IMAP search criteria (e.g., ALL, UNSEEN, FROM user@example.com)',
  31. default: 'ALL'
  32. },
  33. filterUnread: {
  34. type: 'boolean',
  35. title: 'Only Unread',
  36. description: 'Add UNSEEN filter to search criteria',
  37. default: false
  38. },
  39. filterFrom: {
  40. type: 'string',
  41. title: 'Filter by From',
  42. description: 'Filter emails from this address (optional)'
  43. },
  44. filterSubject: {
  45. type: 'string',
  46. title: 'Filter by Subject',
  47. description: 'Filter emails containing this text in subject (optional)'
  48. },
  49. filterSince: {
  50. type: 'string',
  51. title: 'Since Date',
  52. description: 'Filter emails since this date (DD-Mon-YYYY format, e.g., 01-Jan-2024)'
  53. },
  54. limit: {
  55. type: 'integer',
  56. title: 'Limit',
  57. description: 'Maximum number of emails to return',
  58. default: 50,
  59. minimum: 1,
  60. maximum: 1000
  61. },
  62. fetchContent: {
  63. type: 'boolean',
  64. title: 'Fetch Content',
  65. description: 'Fetch full email content for each result',
  66. default: false
  67. }
  68. },
  69. required: ['credentialId']
  70. };
  71. const inputSchema = {
  72. type: 'object',
  73. properties: {
  74. criteria: {
  75. type: 'string',
  76. description: 'Override search criteria from input'
  77. },
  78. mailbox: {
  79. type: 'string',
  80. description: 'Override mailbox from input'
  81. }
  82. }
  83. };
  84. const outputSchema = {
  85. type: 'object',
  86. properties: {
  87. uids: {
  88. type: 'array',
  89. items: { type: 'string' },
  90. description: 'Array of message UIDs'
  91. },
  92. count: {
  93. type: 'integer',
  94. description: 'Number of emails found'
  95. },
  96. emails: {
  97. type: 'array',
  98. description: 'Array of email objects (if fetchContent is enabled)'
  99. }
  100. }
  101. };
  102. const outputs = [
  103. { name: 'main', displayName: 'Search Results', type: 'object', color: '#3b82f6' }
  104. ];
  105. module.exports = {
  106. configSchema,
  107. inputSchema,
  108. outputSchema,
  109. outputs,
  110. async execute(config, input, context) {
  111. const credentialId = config.credentialId;
  112. const mailbox = input.mailbox || config.mailbox || 'INBOX';
  113. const limit = config.limit || 50;
  114. const fetchContent = config.fetchContent || false;
  115. if (!credentialId) {
  116. throw new Error('IMAP credential is required');
  117. }
  118. // Build search criteria
  119. let criteria = input.criteria || config.criteria || 'ALL';
  120. if (config.filterUnread && criteria.indexOf('UNSEEN') === -1) {
  121. criteria = criteria === 'ALL' ? 'UNSEEN' : `${criteria} UNSEEN`;
  122. }
  123. if (config.filterFrom) {
  124. criteria += ` FROM "${config.filterFrom}"`;
  125. }
  126. if (config.filterSubject) {
  127. criteria += ` SUBJECT "${config.filterSubject}"`;
  128. }
  129. if (config.filterSince) {
  130. criteria += ` SINCE "${config.filterSince}"`;
  131. }
  132. // Perform search
  133. const searchResult = smartbotic.imap.search({
  134. credentialId,
  135. mailbox,
  136. criteria,
  137. limit
  138. });
  139. if (!searchResult.success) {
  140. throw new Error(`IMAP search failed: ${searchResult.error}`);
  141. }
  142. const result = {
  143. uids: searchResult.uids,
  144. count: searchResult.count,
  145. mailbox,
  146. criteria
  147. };
  148. // Optionally fetch content for each email
  149. if (fetchContent && searchResult.uids.length > 0) {
  150. result.emails = [];
  151. for (const uid of searchResult.uids) {
  152. const fetchResult = smartbotic.imap.fetch({
  153. credentialId,
  154. mailbox,
  155. uid
  156. });
  157. if (fetchResult.success) {
  158. result.emails.push({
  159. uid: fetchResult.uid,
  160. subject: fetchResult.subject,
  161. from: fetchResult.from,
  162. to: fetchResult.to,
  163. date: fetchResult.date,
  164. body: fetchResult.body
  165. });
  166. }
  167. }
  168. }
  169. return result;
  170. }
  171. };