UNPKG

n8n-nodes-imap-ai

Version:

Simplified IMAP node for n8n with AI-agent support. Clean and modular email and mailbox management for automation workflows.

150 lines 7.55 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.downloadAttachmentOperation = void 0; const n8n_workflow_1 = require("n8n-workflow"); const EmailParts_1 = require("../../../utils/EmailParts"); const ImapUtils_1 = require("../../../utils/ImapUtils"); const SearchFieldParameters_1 = require("../../../utils/SearchFieldParameters"); exports.downloadAttachmentOperation = { operation: { name: 'Download Attachment', value: 'downloadAttachment', description: 'Download email attachments for processing, analysis, or storage. Perfect for AI agents to extract documents, images, files from emails automatically and process them in workflows.', }, parameters: [ { ...SearchFieldParameters_1.parameterSelectMailbox, description: 'Select the mailbox containing the email with attachments. AI agents can specify: INBOX, Sent, Archive, or custom folder names.', }, { displayName: 'Email UID', name: 'emailUid', type: 'string', default: "={{ $fromAI('email_uid', 'UID of the email containing attachments to download') }}", description: 'UID of the email containing attachments. AI can specify this based on email search results.', placeholder: '123', }, { displayName: 'All Attachments', name: 'allAttachments', type: 'boolean', default: false, description: 'Whether to download all attachments from the email', }, { displayName: 'Attachment Part IDs', name: 'partId', type: 'string', default: "={{ $fromAI('attachment_parts', 'Comma-separated list of attachment part IDs to download') }}", required: true, description: 'Comma-separated list of attachment part IDs to download. AI can specify these from email analysis.', placeholder: '1.2,1.3,2.1', hint: 'Part IDs can be found in the email "attachmentsInfo" property', displayOptions: { show: { allAttachments: [false], }, }, }, { displayName: 'Include Inline Attachments', name: 'includeInlineAttachments', type: 'boolean', default: false, description: 'Whether to include inline attachments (e.g. images embedded in HTML)', displayOptions: { show: { allAttachments: [true], }, }, }, ], async executeImapAction(context, itemIndex, client) { var _a, _b, _c, _d, _e, _f, _g, _h; const returnItem = { json: {}, binary: {}, }; const jsonAttachments = []; let attachmentCounter = 0; const mailboxPath = (0, SearchFieldParameters_1.getMailboxPathFromNodeParameter)(context, itemIndex); await client.mailboxOpen(mailboxPath, { readOnly: true }); const emailUid = context.getNodeParameter('emailUid', itemIndex); const allAttachments = context.getNodeParameter('allAttachments', itemIndex); const partsToDownload = []; if (allAttachments) { const includeInlineAttachments = context.getNodeParameter('includeInlineAttachments', itemIndex); const query = { uid: true, bodyStructure: true, }; const emailInfo = await client.fetchOne(emailUid, query, { uid: true }); if (emailInfo.bodyStructure) { const partsInfo = (0, EmailParts_1.getEmailPartsInfoRecursive)(context, emailInfo.bodyStructure); for (const partInfo of partsInfo) { (_a = context.logger) === null || _a === void 0 ? void 0 : _a.debug(`Attachment part info: ${JSON.stringify(partInfo)}`); if (partInfo.disposition === 'attachment') { partsToDownload.push(partInfo.partId); } else if (partInfo.disposition === 'inline' && includeInlineAttachments) { partsToDownload.push(partInfo.partId); } } } else { (_b = context.logger) === null || _b === void 0 ? void 0 : _b.warn(`IMAP server has not returned email body structure for email "${emailUid}"`); } if (partsToDownload.length > 0) { (_c = context.logger) === null || _c === void 0 ? void 0 : _c.info(`Downloading all attachments from email "${emailUid}": ${partsToDownload.join(', ')}`); } else { (_d = context.logger) === null || _d === void 0 ? void 0 : _d.warn(`Email "${emailUid}" does not have any attachments`); } } else { const partId = context.getNodeParameter('partId', itemIndex); const parts = partId.split(',').map((part) => part.trim()); partsToDownload.push(...parts); (_e = context.logger) === null || _e === void 0 ? void 0 : _e.info(`Downloading some attachments from email "${emailUid}": ${partsToDownload.join(', ')}`); } for (const partId of partsToDownload) { (_f = context.logger) === null || _f === void 0 ? void 0 : _f.info(`Downloading attachment "${partId}" from email "${emailUid}"`); ImapUtils_1.ImapFlowErrorCatcher.getInstance().startErrorCatching(); const resp = await client.download(emailUid, partId, { uid: true, }); if (!resp.meta) { const internalImapErrors = ImapUtils_1.ImapFlowErrorCatcher.getInstance().stopAndGetErrors(); let errorDetails = ''; if (internalImapErrors.length > 0) { errorDetails = `IMAP server responded: \n${internalImapErrors.join(', \n')}`; } (_g = context.logger) === null || _g === void 0 ? void 0 : _g.error(`IMAP server has not returned attachment info: ${errorDetails}`); throw new n8n_workflow_1.NodeApiError(context.getNode(), {}, { message: 'IMAP server has not returned attachment info', description: errorDetails, }); } const binaryData = await context.helpers.prepareBinaryData(resp.content, resp.meta.filename, resp.meta.contentType); (_h = context.logger) === null || _h === void 0 ? void 0 : _h.info(`Attachment downloaded: ${binaryData.data.length} bytes`); const fieldName = `attachment_${attachmentCounter}`; attachmentCounter++; const jsonAttachmentInfo = { partId: partId, binaryFieldName: fieldName, ...resp.meta, }; jsonAttachments.push(jsonAttachmentInfo); returnItem.binary[fieldName] = binaryData; } returnItem.json.attachments = jsonAttachments; returnItem.json.operation = 'downloadAttachment'; returnItem.json.emailUid = emailUid; returnItem.json.mailboxPath = mailboxPath; returnItem.json.totalAttachments = jsonAttachments.length; returnItem.json.downloadedAt = new Date().toISOString(); returnItem.json.success = true; return [returnItem]; }, }; //# sourceMappingURL=EmailDownloadAttachment.js.map