1. Home
  2. Guides
  3. Power Automate
  4. How to mail merge with individual attachments using Power Automate and Excel
Power Automate

How to mail merge with individual attachments using Power Automate and Excel

Build an instant Power Automate flow that reads contacts from an Excel table, finds each person's own file in a OneDrive folder, and sends a personalized email with that file attached and an optional CC.

  • By Nur Islam
  • 10:35 video
  • 14 steps
  • 42.2K views
Jump to a step (14)
Who this is for

Sending a different invoice or document to each client usually means writing every email by hand and attaching the right file each time. Outlook's built-in mail merge cannot attach a separate file per recipient, so it is slow and easy to send the wrong file.

The contacts live in an Excel table with a column that holds each person's file name. The files themselves sit in a OneDrive folder. The flow loops through the contacts, searches the folder for the matching file, gets its content and sends one email per contact with merge fields for name, due date and amount.

It only uses Excel Online (Business), OneDrive for Business and Office 365 Outlook, which are all standard connectors. No SharePoint and no premium licence are needed. The flow sends an email only when it finds a file for that row.

What you need

  • Microsoft 365 Business Basic or Standard with Outlook and Power Automate
  • A OneDrive for Business folder with one file per recipient
  • An Excel table in OneDrive with columns such as Email, First Name, Due Date, Amount, Attachment and CC

Step by step

0 of 14 done
  1. 01

    Prepare the files and the contact list

    Put each recipient's file in one OneDrive folder. The video uses demo invoice PDFs, but any file type works. In an Excel Online workbook, list the contacts with an Attachment column holding each person's file name.

    File names can be written with or without the extension. If two people have files with the same name but different extensions, include the extension so the search finds the right one.

  2. 02

    Format the data as a table

    Select all the data, choose Format as Table, make sure My table has headers is ticked and click OK. On the Table Design tab, rename the table (the video uses ContactsData). The flow reads the data through this table.

  3. 03

    Fix date and currency columns

    Power Automate ignores Excel's display format. A date column formatted as a date comes through as a serial number, and a currency column loses its symbol.

    Format those columns as Text instead. For the currency column, copy the values into Notepad, set the column to Text, and paste the values back. The cells now hold text like $250.00 that the flow sends exactly as shown.

  4. 04

    Create an instant cloud flow

    Open Power Automate at make.powerautomate.com. Go to Create, select Instant cloud flow, name it Mail merge with separate attachments, choose Manually trigger a flow and click Create. An instant flow runs only when you press Run, which is what you want for a mail merge.

  5. 05

    Read the Excel table

    Add List rows present in a table from Excel Online (Business). Set Location to OneDrive for Business, Document Library to OneDrive, browse to the contacts workbook and select the table.

  6. 06

    Loop through the contacts

    Add Apply to each from Control. For the input, pick body/value from List rows present in a table. Rename this loop Contacts. The name matters because the expressions later refer to it.

  7. 07

    Find each contact's file

    Inside the loop, add Find files in folder from OneDrive for Business.

    • Search Query: the Attachment column (click See more if it is not listed)
    • Folder: the folder with the attachments
    • File Search Mode: OneDrive Search
  8. 08

    Add a second loop for the found file

    Inside the first loop, add another Apply to each and set its input to the output of Find files in folder. The search returns a list, so this loop handles the file it found. If no file is found, this loop does nothing and no email is sent for that contact.

  9. 09

    Get the file content

    Inside the second loop, add Get file content from OneDrive for Business and set File to Id from Find files in folder. This gives the flow the actual file to attach.

  10. 10

    Add the email action and template

    Still inside the second loop, add Send an email (V2) from Office 365 Outlook. Paste your email template into the body. The video uses a short invoice reminder with placeholders for first name, due date and amount.

  11. 11

    Fill the recipient and merge fields with expressions

    Inside the nested loop, the dynamic content does not list the contact columns properly, and the Excel dynamic fields will not follow the Contacts loop. Use expressions that point at the loop instead.

    In To, switch to advanced mode and insert:

    items('Contacts')?['Email']

    Use the same pattern for the other fields:

    • Subject: items('Contacts')?['Due Date']
    • Body: items('Contacts')?['First Name'], items('Contacts')?['Due Date'] and items('Contacts')?['Amount']

    The name inside the brackets must match your Excel header, including spaces. Capital letters do not matter.

  12. 12

    Attach the file

    Under Advanced parameters, add Attachments and click Add new item.

    • Attachments Name: Name from Find files in folder
    • Attachments Content: File content from Get file content
  13. 13

    Add a CC from the table

    In Advanced parameters, add CC. Switch to advanced mode and insert items('Contacts')?['CC']. Do the same with BCC if you have a BCC column.

  14. 14

    Save and run the flow

    Save the flow, click Run, confirm the connections to OneDrive and Outlook, then click Continue and Run flow. Check your Sent Items. Each contact gets one email with their own attachment and their own name, due date and amount.

Tips and common problems

  • Keep the contacts workbook in a different folder from the attachment files. If they share a folder, the file search can return the wrong file.
  • Format date and currency columns as Text in Excel. Otherwise dates arrive as serial numbers and amounts lose their currency symbol.
  • Rename the first loop to Contacts before writing expressions, because items('Contacts') must match the loop name.
  • No file found means no email. The flow only sends when Find files in folder returns a match for that row.
  • For a large list, you can add a Delay action after Send an email (V2) to space out the emails.
Still stuck? Ask AI to help you fix itChatGPTClaudeGeminiCopilotPerplexityGrok

Expressions used in this flow

FieldExpression
Toitems('Contacts')?['Email']
Subject and body due dateitems('Contacts')?['Due Date']
First nameitems('Contacts')?['First Name']
Amountitems('Contacts')?['Amount']
CCitems('Contacts')?['CC']

Quick version

The short version of this build covers the same idea in under a minute: copy the attachment files into a OneDrive folder, create an Excel Online file with the contacts and a file name column, read it in a new flow, loop through the rows, search for each file name in the folder, and when a file is found, get its content and send the email with the merge fields and the attachment. Watch the short.

There is also a newer, improved tutorial that covers more scenarios: watch it here.

Questions

Can Outlook mail merge send a different attachment to each person?

Not on its own. Power Automate can: read the contacts from Excel, find each person's file in OneDrive with Find files in folder, and attach it in Send an email (V2).

Why do I need expressions instead of the Excel dynamic content?

The email is inside a second loop, so the Excel columns do not follow the outer contacts loop. items('Contacts')?['Email'] reads the column from the current contact row.

Does this need SharePoint or a premium licence?

No. It uses Excel Online (Business), OneDrive for Business and Office 365 Outlook, which are all standard connectors available with Microsoft 365 business plans.

Can I add CC and BCC to a Power Automate mail merge?

Yes. Add columns for them in the Excel table, then set CC or BCC in Send an email (V2) to an expression such as items('Contacts')?['CC'].

Video chapters
Ask a question in the comments Last checked 26 Sep 2026. Screens change: if a step looks different, tell me in the comments.