All articles

How to Send Emails with Attachments in Power Automate (Without 0KB Files)

Getting email attachments right in Power Automate is trickier than it looks. Here's how to attach files from SharePoint, Dataverse, and other sources without ending up with empty 0KB files.

· 8 min read

Sending an email from Power Automate is simple. Sending an email with an attachment that actually contains data? That’s where people run into problems. The most common complaint: “My flow sends the email fine, but the attachment is 0KB.”

Here’s how to get attachments right with every common source.

Which Email Connector to Use

Power Automate has multiple email connectors. The ones you’ll see most:

  • Office 365 Outlook — The standard choice if your organization uses Microsoft 365. Sends from the connected user’s mailbox.
  • Send an email notification (Mail) — Sends from a generic Microsoft address. No attachments support, limited formatting. Avoid it for anything beyond simple notifications.
  • Outlook.com — For personal accounts. Not what you want in a business flow.

For attachments, use Office 365 Outlook and the Send an email (V2) action.

Attaching a File from SharePoint

This is the most common scenario. The key: you need the file content, not the file metadata.

Step 1: Use Get file content (not “Get file properties”) from the SharePoint connector.

Step 2: In the Send an email action, switch to the advanced Attachments input. Click “Switch to input entire array” or add an attachment item with:

  • Name: The file name including extension, e.g., Report.pdf
  • Content: The output from the Get file content action
[
  {
    "Name": "Report.pdf",
    "ContentBytes": @{body('Get_file_content').$content}
  }
]

If you’re using the visual designer, just map the outputs:

  • Attachments Name: Use the File name with extension from a “Get file properties” action, or type the name manually.
  • Attachments Content: Use the File Content output from “Get file content.”

Why the File Arrives at 0KB

The number one cause: you used Get file properties instead of Get file content. File properties gives you metadata (name, size, URL). File content gives you the actual bytes. You need both actions — properties for the name, content for the data.

Attaching a File from Dataverse

Dataverse stores files in two ways: the legacy Notes/Annotations table and the newer File/Image columns.

From Notes (Annotations)

Notes store attachments as Base64 in the documentbody field.

Step 1: List rows from the Notes table, filtering by the parent record:

_objectid_value eq '{recordGUID}'

Step 2: For each note with an attachment:

  • Name: filename field from the note
  • Content: Use an expression to decode: base64ToBinary(items('Apply_to_each')?['documentbody'])

From File Columns

If the table has a File-type column, use the Download a file or an image action from the Dataverse connector. The output is already binary content — pass it directly to the attachment Content field.

Attaching Files from an HTTP Request

If you’re getting a file from an external API:

[
  {
    "Name": "data-export.csv",
    "ContentBytes": @{body('HTTP')}
  }
]

If the API returns Base64-encoded content instead of raw bytes:

[
  {
    "Name": "data-export.csv",
    "ContentBytes": @{base64ToBinary(body('HTTP'))}
  }
]

Multiple Attachments

To send multiple attachments, build an array. Initialize an Array variable before your loop, then append to it:

Step 1: Initialize variable varAttachments as Array, value []

Step 2: Inside your loop (ForEach over files):

Append to array:

{
  "Name": "@{items('Apply_to_each')?['fileName']}",
  "ContentBytes": "@{body('Get_file_content').$content}"
}

Step 3: In Send an email, switch Attachments to “input entire array” and pass @{variables('varAttachments')}.

Dynamic File Names

Don’t hardcode file names. Build them from your flow data:

@{formatDateTime(utcNow(), 'yyyy-MM-dd')}_Invoice_@{triggerOutputs()?['body/invoicenumber']}.pdf

This gives you something like 2026-03-22_Invoice_INV-1042.pdf.

Size Limits

The Office 365 Outlook connector has a 150 MB total message size limit (including body and all attachments). For most practical purposes, keep total attachment size under 25 MB to avoid issues with recipient mailboxes.

If you’re attaching large files, consider sending a sharing link instead:

"Please find the file here: @{outputs('Create_sharing_link')?['body/link/webUrl']}"

Common Mistakes and How to Fix Them

Attachment Is 0KB

As mentioned above: you used the wrong SharePoint action. Use Get file content for the bytes, not Get file properties.

Attachment Has the Wrong Name or No Extension

The Name field needs the full filename including extension. If you pass "Report" instead of "Report.pdf", the recipient gets a file with no extension that their computer won’t know how to open.

”InvalidTemplate” Error on the Attachment Expression

This usually means your expression syntax is wrong. The most common issue: mixing up $content and body(). For SharePoint file content, use body('Get_file_content').$content. For Dataverse notes, use base64ToBinary() on the documentbody field.

The Email Sends But No Attachment Appears

Check that the Attachments section is configured in array mode. If you’re passing a single attachment object without the array brackets [], the connector silently ignores it in some configurations. Always wrap in an array.

Base64 Content Appears as Text in the Email Body

You accidentally put the file content in the body instead of the attachment. Double-check that your dynamic content is mapped to the Attachments Content field, not the Body field.

Share this article LinkedIn X / Twitter

Related articles

Your First Approval Flow

A step-by-step guide to building approval flows in Power Automate, including connector provisioning, approval types, custom email content, and handling the response — plus the errors that block most first-time setups.

· 9 min read

Power Automate Formatting Cheat Sheet

formatDateTime, convertTimeZone, formatNumber — these expressions handle 90% of formatting needs in Power Automate. Here's the syntax, common format strings, and fixes for the errors that come up.

· 9 min read