imap-fetch.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. /**
  2. * @node imap-fetch
  3. * @name IMAP Fetch Email
  4. * @category email
  5. * @version 1.2.0
  6. * @description Fetch the full content of an email from an IMAP server.
  7. * @icon download
  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 containing the email',
  25. default: 'INBOX'
  26. },
  27. uid: {
  28. type: 'string',
  29. title: 'Email UID',
  30. description: 'The unique identifier of the email to fetch (can be provided from input)'
  31. },
  32. peek: {
  33. type: 'boolean',
  34. title: 'Peek (Don\'t Mark as Read)',
  35. description: 'Fetch without marking the email as read',
  36. default: true
  37. }
  38. },
  39. required: ['credentialId']
  40. };
  41. const inputSchema = {
  42. type: 'object',
  43. properties: {
  44. uid: {
  45. type: 'string',
  46. description: 'Email UID to fetch'
  47. },
  48. mailbox: {
  49. type: 'string',
  50. description: 'Override mailbox from input'
  51. }
  52. }
  53. };
  54. const outputSchema = {
  55. type: 'object',
  56. properties: {
  57. uid: { type: 'string', description: 'Unique email identifier' },
  58. subject: { type: 'string' },
  59. from: { type: 'string' },
  60. to: { type: 'string' },
  61. date: { type: 'string' },
  62. body: { type: 'string', description: 'Email body text' },
  63. raw: { type: 'string', description: 'Raw email content (for attachment extraction)' },
  64. hasAttachments: { type: 'boolean', description: 'Whether email has attachments' },
  65. mailbox: { type: 'string' }
  66. }
  67. };
  68. const outputs = [
  69. { name: 'main', displayName: 'Email Content', type: 'object', color: '#8b5cf6' }
  70. ];
  71. /**
  72. * Check if email has attachments by looking for Content-Disposition: attachment
  73. * or multipart content types
  74. */
  75. function detectAttachments(rawEmail) {
  76. if (!rawEmail) return false;
  77. const lower = rawEmail.toLowerCase();
  78. return lower.includes('content-disposition: attachment') ||
  79. lower.includes('content-disposition:attachment') ||
  80. (lower.includes('multipart/mixed') && lower.includes('boundary='));
  81. }
  82. module.exports = {
  83. configSchema,
  84. inputSchema,
  85. outputSchema,
  86. outputs,
  87. async execute(config, input, context) {
  88. const credentialId = config.credentialId;
  89. const mailbox = input.mailbox || config.mailbox || 'INBOX';
  90. const uid = input.uid || config.uid;
  91. const peek = config.peek !== false; // Default to true (don't mark as read)
  92. if (!credentialId) {
  93. throw new Error('IMAP credential is required');
  94. }
  95. if (!uid) {
  96. throw new Error('Email UID is required');
  97. }
  98. // Fetch the email
  99. const fetchResult = smartbotic.imap.fetch({
  100. credentialId,
  101. mailbox,
  102. uid,
  103. peek
  104. });
  105. if (!fetchResult.success) {
  106. throw new Error(`IMAP fetch failed: ${fetchResult.error}`);
  107. }
  108. return {
  109. uid: fetchResult.uid,
  110. subject: fetchResult.subject,
  111. from: fetchResult.from,
  112. to: fetchResult.to,
  113. date: fetchResult.date,
  114. body: fetchResult.body,
  115. raw: fetchResult.raw,
  116. hasAttachments: detectAttachments(fetchResult.raw),
  117. mailbox
  118. };
  119. }
  120. };