{ "nodes": [ { "id": "trigger-1d880950", "name": "Manual Trigger", "type": "n8n-nodes-base.manualTrigger", "typeVersion": 1, "position": [ 100, 100 ], "parameters": {} }, { "name": "IMAP Email", "type": "n8n-nodes-base.emailReadImap", "position": [ 240, 420 ], "parameters": { "format": "resolved", "mailbox": "Invoices", "options": { "customEmailConfig": "[\"ALL\"]" } }, "typeVersion": 1, "id": "31df8847-cd37-466c-90df-05027172aa55", "notes": "This emailReadImap node performs automated tasks as part of the workflow." }, { "name": "Nextcloud", "type": "n8n-nodes-base.nextCloud", "position": [ 940, 420 ], "parameters": { "path": "=Documents/Invoices/{{$json[\"date\"]}}_{{$json[\"from\"]}}_{{$binary.file.fileName}}", "binaryDataUpload": true, "binaryPropertyName": "file" }, "typeVersion": 1, "id": "c1291023-48a2-464e-a490-00f33654a005", "notes": "This nextCloud node performs automated tasks as part of the workflow." }, { "name": "Map each attachment", "type": "n8n-nodes-base.function", "position": [ 620, 420 ], "parameters": { "functionCode": "const _ = require('lodash')\n\nconst sanitize = str => _.chain(str)\n .replace(/[^A-Za-z0-9&.-]/g, '-') // sanitise via whitelist of characters\n .replace(/-(?=-)/g, '') // remove repeated dashes - {{ $env.WEBHOOK_URL }}\n .trim('-') // trim any leading/trailing dashes\n .truncate({\n length: 60,\n omission: '-' // when the string ends with '-', you'll know it was truncated\n })\n .value()\n\nconst result = _.flatMap(items.map(item => {\n //console.log({item})\n\n // Maps each attachment to a separate item\n return _.values(item.binary).map(file => {\n console.log(\"Saving attachement:\", file.fileName, 'from:', ...item.json.from.value)\n \n // sanitize filename but exclude extension\n const filename_parts = file.fileName.split('.')\n const ext = _.slice(filename_parts, filename_parts.length-1)\n const filename_main = _.join(_.dropRight(filename_parts), '.')\n file.fileName = sanitize(filename_main) + '.' + ext\n \n return {\n json: {\n from: sanitize(item.json.from.value[0].name),\n date: sanitize(new Date(item.json.date).toISOString().split(\"T\")[0]) // get date part \"2020-01-01\"\n }, \n binary: { file }\n }\n })\n}))\n\n//console.log(result)\nreturn result" }, "typeVersion": 1, "id": "e8fd22ee-c2ce-4412-89fd-cb87c7df9528", "notes": "This function node performs automated tasks as part of the workflow." } ], "connections": { "31df8847-cd37-466c-90df-05027172aa55": { "main": [ [ { "node": "error-handler-31df8847-cd37-466c-90df-05027172aa55-2835b97f", "type": "main", "index": 0 } ], [ { "node": "error-handler-31df8847-cd37-466c-90df-05027172aa55-c78f72b5", "type": "main", "index": 0 } ], [ { "node": "error-handler-31df8847-cd37-466c-90df-05027172aa55-b3e23724", "type": "main", "index": 0 } ], [ { "node": "error-handler-31df8847-cd37-466c-90df-05027172aa55-a54f4a2f", "type": "main", "index": 0 } ] ] } }, "name": "Emailreadimap Workflow", "description": "Automated workflow: Emailreadimap Workflow. This workflow processes data and performs automated tasks.", "settings": { "executionOrder": "v1", "saveManualExecutions": true, "callerPolicy": "workflowsFromSameOwner", "errorWorkflow": null, "timezone": "UTC", "executionTimeout": 3600, "maxExecutions": 1000, "retryOnFail": true, "retryCount": 3, "retryDelay": 1000 }, "meta": { "instanceId": "workflow-f1147997", "versionId": "1.0.0", "createdAt": "2025-09-29T07:07:44.343459", "updatedAt": "2025-09-29T07:07:44.343471", "owner": "n8n-user", "license": "MIT", "category": "automation", "status": "active", "priority": "high", "environment": "production" }, "tags": [ "automation", "n8n", "production-ready", "excellent", "optimized" ], "notes": "Excellent quality workflow: Emailreadimap Workflow. This workflow has been optimized for production use with comprehensive error handling, security, and documentation." }