AutomationFlowsEmail & Gmail › Archive Outlook Email Attachments to Onedrive with Sharepoint Logging

Archive Outlook Email Attachments to Onedrive with Sharepoint Logging

ByMychel Garzon @mychel-garzon on n8n.io

Stop letting email attachments pile up in your inbox. Let automation file every document the moment it arrives.

Cron / scheduled trigger★★★★☆ complexity22 nodesMicrosoft OutlookMicrosoft One DriveMicrosoft SharePointError Trigger
Email & Gmail Trigger: Cron / scheduled Nodes: 22 Complexity: ★★★★☆ Added:

This workflow corresponds to n8n.io template #15793 — we link there as the canonical source.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "id": "Pi4s0Dv7qBwUdCTA",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Outlook + SharePoint: Smart Attachment Archiver",
  "tags": [],
  "nodes": [
    {
      "id": "ec340ea3-ad89-4bed-8643-9f6553a3be7e",
      "name": "Every Hour",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -368,
        112
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "hours"
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "3c8c1eb2-f169-44ef-bf51-e9bc643bd1c0",
      "name": "Get Unread Emails with Attachments",
      "type": "n8n-nodes-base.microsoftOutlook",
      "position": [
        -144,
        112
      ],
      "parameters": {
        "limit": 50,
        "options": {},
        "operation": "getAll"
      },
      "typeVersion": 2
    },
    {
      "id": "252a50b7-4865-4b3e-a190-75a73eaf5cf5",
      "name": "Has Emails?",
      "type": "n8n-nodes-base.if",
      "position": [
        80,
        112
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "cond-+123456789001",
              "operator": {
                "type": "number",
                "operation": "gt"
              },
              "leftValue": "={{ $input.all().length }}",
              "rightValue": 0
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "ec3849ee-7071-4cad-8199-0605fbc6066c",
      "name": "No Emails - Done",
      "type": "n8n-nodes-base.noOp",
      "position": [
        256,
        240
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "fc78b7fe-aa15-467a-90fc-842a56671439",
      "name": "Process One Email at a Time",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        624,
        96
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "8c35161f-bcd0-4796-8029-63007ef37468",
      "name": "Get Email Attachments",
      "type": "n8n-nodes-base.microsoftOutlook",
      "position": [
        864,
        80
      ],
      "parameters": {
        "options": {},
        "resource": "messageAttachment",
        "messageId": "={{ $('Process One Email at a Time').first().json.id }}",
        "operation": "getAll"
      },
      "typeVersion": 2
    },
    {
      "id": "6d765876-6393-41c5-b3fd-bfdc507e357c",
      "name": "Build Folder Path + Decode Attachment",
      "type": "n8n-nodes-base.code",
      "position": [
        1088,
        80
      ],
      "parameters": {
        "jsCode": "const items = $input.all();\nconst email = $('Process One Email at a Time').first().json;\nconst from = email.from?.emailAddress?.address || 'unknown';\nconst senderDomain = from.includes('@') ? from.split('@')[1] : 'internal_sender';\nconst received = new Date(email.receivedDateTime);\nconst year = received.getFullYear().toString();\nconst month = (received.getMonth() + 1).toString().padStart(2, '0');\nconst folderPath = `/Archives/${year}/${month}/${senderDomain}`;\n\nconst validItems = items.filter(item => (item.json.size || 0) > 0);\n\nif (validItems.length === 0) {\n  return [{ json: {\n    emailId: email.id, from, folderPath,\n    fileName: null, fileSize: 0, contentType: null,\n    noAttachments: true, receivedDate: received.toISOString()\n  }}];\n}\n\nreturn validItems.map(item => {\n  const binaryObj = Object.values(item.binary)[0];\n  return {\n    json: {\n      emailId:       email.id,\n      from,\n      folderPath,\n      fileName:      item.json.name,\n      fileSize:      item.json.size || 0,\n      contentType:   item.json.contentType || 'application/octet-stream',\n      noAttachments: false,\n      receivedDate:  received.toISOString()\n    },\n    binary: { data: binaryObj }\n  };\n});"
      },
      "typeVersion": 2
    },
    {
      "id": "0b674137-7b62-4ed3-b00c-567fc52428dc",
      "name": "Upload to OneDrive",
      "type": "n8n-nodes-base.microsoftOneDrive",
      "position": [
        1568,
        64
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "bcbce129-c09b-43b9-a13f-e03c2895021a",
      "name": "Log to SharePoint Audit List",
      "type": "n8n-nodes-base.microsoftSharePoint",
      "position": [
        2112,
        96
      ],
      "parameters": {
        "resource": "listItem",
        "requestOptions": {}
      },
      "typeVersion": 1
    },
    {
      "id": "2ae7847b-0175-42df-ad8e-470f37532543",
      "name": "Mark Email as Read",
      "type": "n8n-nodes-base.microsoftOutlook",
      "position": [
        2352,
        96
      ],
      "parameters": {
        "messageId": "={{ $('Process One Email at a Time').first().json.id }}",
        "operation": "update",
        "updateFields": {
          "isRead": true,
          "categories": [
            "Archived"
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "6445a8ae-8a66-4bb8-affe-ba1d19d60ded",
      "name": "Workflow Error Trigger",
      "type": "n8n-nodes-base.errorTrigger",
      "position": [
        -352,
        592
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "60fcc58e-8964-451a-abda-25ca51071b62",
      "name": "Send Error Email",
      "type": "n8n-nodes-base.microsoftOutlook",
      "position": [
        -128,
        592
      ],
      "parameters": {
        "subject": "={{ `\u274c n8n Workflow Error: Attachment Archiver [` + $json.execution.id + `]` }}",
        "bodyContent": "={{ `<p>Workflow <b>Outlook + SharePoint Attachment Archiver</b> failed.</p><ul><li><b>Execution:</b> ` + $json.execution.id + `</li><li><b>Node:</b> ` + $json.execution.lastNodeExecuted + `</li><li><b>Error:</b> ` + $json.execution.error.message + `</li></ul>` }}",
        "toRecipients": [
          "user@example.com"
        ],
        "additionalFields": {}
      },
      "typeVersion": 2
    },
    {
      "id": "edc93424-5f0e-4806-99d2-de98917466a1",
      "name": "Is Upload Error?",
      "type": "n8n-nodes-base.if",
      "position": [
        96,
        592
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": false,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "cond-upload-error-01",
              "operator": {
                "type": "string",
                "operation": "contains"
              },
              "leftValue": "={{ $json.execution.lastNodeExecuted }}",
              "rightValue": "Upload"
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "f7e8af9b-0889-43c5-ba58-a73530acd095",
      "name": "Log Failed Upload to SharePoint",
      "type": "n8n-nodes-base.microsoftSharePoint",
      "position": [
        320,
        576
      ],
      "parameters": {
        "resource": "listItem",
        "requestOptions": {}
      },
      "typeVersion": 1
    },
    {
      "id": "d2a25248-b8c4-4b62-84ec-f310be0826bc",
      "name": "Has File Attachments?",
      "type": "n8n-nodes-base.if",
      "position": [
        1360,
        80
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "cond-0002-att-+1234567890",
              "operator": {
                "type": "boolean",
                "operation": "equals"
              },
              "leftValue": "={{ $json.noAttachments }}",
              "rightValue": false
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "59ccf3ed-3db1-40bd-86b6-6f4354919577",
      "name": "Aggregate Attachment Uploads",
      "type": "n8n-nodes-base.code",
      "position": [
        1792,
        96
      ],
      "parameters": {
        "jsCode": "const items    = $input.all();\nconst email    = $('Process One Email at a Time').first().json;\nconst fileData = $('Build Folder Path + Decode Attachment').all().filter(i => !i.json.noAttachments);\n\nreturn [{ json: {\n  emailId:       email.id,\n  from:          email.from?.emailAddress?.address || 'unknown',\n  filesUploaded: fileData.length,\n  fileNames:     fileData.map(i => i.json.fileName).join(', ') || '(none)',\n  folderPath:    items[0]?.json?.folderPath || ''\n} }];"
      },
      "typeVersion": 2
    },
    {
      "id": "23c4fdeb-7dda-45e6-8aca-f37e4f8b037c",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -400,
        -64
      ],
      "parameters": {
        "color": 7,
        "width": 892,
        "height": 468,
        "content": "## Ingestion\nRuns every hour. Fetches up to 50 unread Outlook emails. Exits cleanly with no further execution if the inbox is empty."
      },
      "typeVersion": 1
    },
    {
      "id": "490d1177-8566-4cbb-a631-8b2e239fb8d8",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        544,
        -64
      ],
      "parameters": {
        "color": 7,
        "width": 684,
        "height": 468,
        "content": "## Per-Email Processing\nSplits emails into individual items for sequential processing. Fetches all attachments per email, drops 0-byte items, decodes binary data, and computes the OneDrive folder path from the sender domain and received date."
      },
      "typeVersion": 1
    },
    {
      "id": "bedffe41-ac08-4527-9b5e-ce9be8270188",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1280,
        -64
      ],
      "parameters": {
        "color": 7,
        "width": 668,
        "height": 460,
        "content": "## Upload & Aggregation\nRoutes emails with real attachments to OneDrive upload. Emails with no valid attachments skip directly to aggregation. Results are collected into a single summary item with file names, upload count, and folder path."
      },
      "typeVersion": 1
    },
    {
      "id": "ded74909-0497-4af8-8931-7f9e758e0de0",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2000,
        -64
      ],
      "parameters": {
        "color": 7,
        "width": 568,
        "height": 456,
        "content": "## Audit & Completion\nLogs the upload summary to a SharePoint list for compliance tracking. Marks the email as read and applies the `Archived` category in Outlook. Loops back to process the next email in the batch."
      },
      "typeVersion": 1
    },
    {
      "id": "02b6d91c-6b61-42fb-a472-817a7dd5560b",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -400,
        448
      ],
      "parameters": {
        "color": 7,
        "width": 900,
        "height": 308,
        "content": "## Global Error Failsafe\nCatches any execution failure and sends an error email via Outlook with the execution ID and failed node name. If the failure was an upload error, also logs a failed upload record to the SharePoint audit list."
      },
      "typeVersion": 1
    },
    {
      "id": "801301b0-52c5-4160-80d5-b22e1b2b53c8",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1120,
        -64
      ],
      "parameters": {
        "width": 672,
        "height": 816,
        "content": "## Outlook Attachment Archiver\n\n### Microsoft 365 Automatic Attachment Archiving to OneDrive + SharePoint\n\n### How it works\n1. **Ingest:** Checks Outlook every hour for unread emails. Skips immediately if the inbox is empty.\n2. **Process:** Splits emails one at a time. Fetches attachments, drops 0-byte items, and builds a structured folder path from the sender's domain and the received date (`/Archives/YYYY/MM/sender-domain`).\n3. **Upload:** Files with valid attachments are uploaded to OneDrive into the computed folder path. Emails with no real attachments skip straight to logging.\n4. **Audit:** Aggregates upload results and logs a record to a SharePoint list with sender, file names, folder path, and upload count.\n5. **Complete:** Marks the email as read and tags it with the `Archived` category in Outlook, then loops back for the next email in the batch.\n\n### Setup steps\n- [ ] Connect Microsoft Outlook credential to Get Unread Emails, Get Email Attachments, Mark Email as Read, and Send Error Email nodes\n- [ ] Connect Microsoft OneDrive credential to Upload to OneDrive node\n- [ ] Connect Microsoft SharePoint credential to Log to SharePoint Audit List and Log Failed Upload to SharePoint nodes\n- [ ] Configure the Upload to OneDrive node with your target drive ID and set the folder path expression to `{{ $json.folderPath }}`\n- [ ] Configure Log to SharePoint Audit List with your Site ID and List ID\n- [ ] Update the error email recipient in Send Error Email (`it-admin@company.fi`)\n- [ ] Activate and run manually once to verify the folder structure is created correctly\n\n### Required credentials\n- Microsoft Outlook OAuth2\n- Microsoft OneDrive OAuth2\n- Microsoft SharePoint OAuth2\n\n### Folder structure\nAttachments are organized automatically:\n`/Archives/{year}/{month}/{sender-domain}/filename.ext`"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "executionOrder": "v1"
  },
  "versionId": "507a3a07-4883-46ce-b1d9-9394f60fa71f",
  "connections": {
    "Every Hour": {
      "main": [
        [
          {
            "node": "Get Unread Emails with Attachments",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Has Emails?": {
      "main": [
        [
          {
            "node": "Process One Email at a Time",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "No Emails - Done",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Is Upload Error?": {
      "main": [
        [
          {
            "node": "Log Failed Upload to SharePoint",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Error Email": {
      "main": [
        [
          {
            "node": "Is Upload Error?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Mark Email as Read": {
      "main": [
        [
          {
            "node": "Process One Email at a Time",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upload to OneDrive": {
      "main": [
        [
          {
            "node": "Aggregate Attachment Uploads",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Email Attachments": {
      "main": [
        [
          {
            "node": "Build Folder Path + Decode Attachment",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Has File Attachments?": {
      "main": [
        [
          {
            "node": "Upload to OneDrive",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Aggregate Attachment Uploads",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Workflow Error Trigger": {
      "main": [
        [
          {
            "node": "Send Error Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Process One Email at a Time": {
      "main": [
        [
          {
            "node": "Get Email Attachments",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate Attachment Uploads": {
      "main": [
        [
          {
            "node": "Log to SharePoint Audit List",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Log to SharePoint Audit List": {
      "main": [
        [
          {
            "node": "Mark Email as Read",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Unread Emails with Attachments": {
      "main": [
        [
          {
            "node": "Has Emails?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Folder Path + Decode Attachment": {
      "main": [
        [
          {
            "node": "Has File Attachments?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

Stop letting email attachments pile up in your inbox. Let automation file every document the moment it arrives.

Source: https://n8n.io/workflows/15793/ — original creator credit. Request a take-down →

More Email & Gmail workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Email & Gmail

This workflow automates the process of saving binary attachments from Outlook emails into newly created folders in OneDrive. It's ideal for users who regularly receive files and need them organized in

Microsoft Outlook Trigger, Microsoft One Drive, Microsoft Outlook
Email & Gmail

Keep your IT operations moving, every action email becomes a tracked task, and every security alert lands where it belongs, automatically.

Microsoft Outlook, HTTP Request, Microsoft Teams +1
Email & Gmail

This workflow automates the backup of your self-hosted n8n instance by exporting all workflows and saving them as individual files to a designated OneDrive folder. Each file is timestamped for easy ve

n8n, Microsoft One Drive, Microsoft Outlook
Email & Gmail

This workflow takes new Outlook emails with attachments and helps archive the relevant files in DATEV DMS.

Microsoft Outlook Trigger, @Klardaten/N8N Nodes Datevconnect, Slack +1
Email & Gmail

Create Add An Attachment And Send A Draft Using Microsoft Outlook. Uses manualTrigger, microsoftOutlook, httpRequest. Event-driven trigger; 5 nodes.

Microsoft Outlook, HTTP Request