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
JavaScript
;
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