Learn how easy it is to create a draft email in your Outlook Draft folder using Power Automate. Rather than send the email direct from Power Automate, let me show you a simple way to create a draft email. You can review, edit and send this email directly from your Outlook Mailbox. As well as a video to demonstrate how this is possible, I will further extend the concept below and show you how you can include attachments as part of your draft email.
Click here to read up on the Graph API we use to perform this PowerAutomate Flow.
Using the above documentation and the Graph Send an HTTP Request Action, we can create a draft email in one simple action. The content can include dynamic data including title, to, subject, body and of course attachments.
I haven’t included any copy / paste samples as Microsoft do a good job of this in their documentation. However, where it’s not so good, is an example that includes attachments.
Adding an attachment (from SharePoint)
In order to add attachments to your draft email, you need to contruct an array of attachment(s) objects that are made up as follows:
{ "@odata.type": "#microsoft.graph.fileAttachment", "name": "@{items('Apply_to_each')?['{FilenameWithExtension}']}", "contentBytes": @{body('Get_file_content')?['$content']} }
Note, that you must escape the @ in the attachment object by including two @@ or you will get an error when trying to save the flow.
In my scenario, I am using get files (properties only) action to get a list of files from SharePoint, you could of course filter this or make your file attachment(s) fixed by using get file content action. I use an apply to each to get each file(s) and add them to an object in a compose called Attachment.
To create our object we must include the file name (which can be dynamic content) but also the contentBytes, this is built using an expression body(‘Get_file_content’)?[‘$content’] and must not include double quotes. Once we have our objects in the Attachment(s) compose action, we can bring them all together in an array using the expression outputs(‘Attachment’). This is a neat little trick to create an array, based on the data contained within the compose action(s) in an apply to each.
{ "subject": "Files?", "importance": "Low", "body": { "contentType": "HTML", "content": "Quite a few files are attached!" }, "toRecipients": [ { "emailAddress": { "address": "damien@yourtenant.onmicrosoft.com" } } ], "Attachments": @{outputs('Attachment')} }
The above HTTP body demonstrates how you might create a draft email with attachments.
Adding an Attachment (from OneDrive)
Sending file(s) from OneDrive is very simlar. You will need to construct the expression for the file content. The expression I have used for my excel file is outputs(‘Get_file_content’)?[‘body’]?[‘$content’].
Above, I am attaching a single file. Don’t forget about escaping the @ symbol. As this is a single file, we need to form an array by adding [ opening and closing ] square brackets (see below).
Adding the attachment array to the body of the email is exactly the same. You can add it by calling the expression outputs(‘Attachment’) or by using the dynamic content block.
The Drafts
All you have to do now, is have a look in your draft folder. Open up the draft, make any changes and hit send!
Looking to go a bit more complex?
If you are looking to create a draft email containing HTML, a link to a website, a mailto link or maybe a signature, take a look at the example flow below which can be downloaded from my git hub here!
And here is what your draft email created in Power Automate will look like:
Please let me know how you have used this in your own solutions.
Hi damobird,
I can’t seem to figure out the flow. When the enter this in compose, I keep getting the error below also.
{
“@@odata.type”: “#microsoft.graph.fileAttachment”
“name”: “@{items(‘Apply_to_each_2’)?[‘{FilenameWithExtension}’]}”,
“contentBytes”: @{body(‘Get_file_content’)?[‘$content’]}
}
“error”: {
“code”: “BadRequest”,
“message”: “Unable to read JSON request payload. Please ensure Content-Type header is set and payload is of valid JSON format.”,
Missing a comma on first line, after …Attachment”,
Thank you! Now, I am getting this error code:
“error”: {
“code”: “BadRequest”,
“message”: “Property Attachments in payload has a value that does not match schema.”,
Would this method not work with arrays or when trying to pull different file attachments for different people?
I believe it should work, based on an attachments array. Try getting one file to work first, then increase the number of attachments. Make sure you don’t have quotes around the file content value in the object.
“error”: {
“code”: “BadRequest”,
“message”: “Unable to read JSON request payload. Please ensure Content-Type header is set and payload is of valid JSON format.”,
I found a solution:
after the “apply to all” loop, I initialized an array variable and gave it the value of the “Attachment” compose function (in the loop).
Then I added a “select” and “filter array” steps (follow those steps: https://powerusers.microsoft.com/t5/Building-Flows/Remove-an-element-from-an-array-in-flow/td-p/367436) because the first item of the array was empty.
Then I assigned the value of the filtered array to a compose function.
Then in the “send HTTP request”, add the attachments as below: “Attachments”: @{outputs(‘Attachment’)} (with the dynmic content window)
That worked 🙂
Great content! It is almost what I am trying to accomplish. I wonder if it would be possible to compose those drafts from incoming messages. I mean, prepare a preformatted message in response to an incoming mail, but keeping the original message as part of the response
I don’t see why not? When a new email arrives, create a draft response and include the original content in the reply.
I am kind of newbie with power automate… You mean selecting the “body” from dynamic content of incoming message and pasting it at the “body” field of JSON data?
That would be the idea, yes. It will be possible but you’ve not chosen the easiest thing to try as a newbie. A steep learning curve. If you get stuck I can try and help one evening.
Hi, I would be also interested in this solution. The Body is in HTML and all Outputs are working well. But getting the original Body doesn’t work. Error Details: “Unable to read JSON request payload. Please ensure Content-Type header is set and payload is of valid JSON format.”
Guess the Body Format is not right. Is there a possibility to get it in the right format?
I’m Like Luiz absolutely a newbie
I am trying to accomplish this same thing. The jist of it is: Pull incoming email to forward, add attachment files, create draft to review before forwarding to recipient. I have figured out everything other than getting the body of the email to be forwarded to work with the https request method. I get the “Unable to read JSON request payload as soon as I try to add this part in.
Try testing a plain string in the body. It looks like you are pulling through a lot more than intended. Then experiment with getting the right expression in a compose action before updating that on your graph api call.
We’ve made use of the example but we need a way to place the draft email into different users mailboxes. How can we specify a different email address from the one running the flows?
You would need to allow the user to run this connection as them.
I have:
{
“name”: “2022-112-100.pdf”,
“contentBytes”: “JVBERi0xLjQKJdP0zOEKMSAwIG9iago….SVFT0YK”,
“@odata.type”: “#microsoft.graph.fileAttachment”
}
….
{
“subject”:”Did you see last night’s game?”,
“importance”:”Low”,
“body”:{
“contentType”:”HTML”,
“content”:”They were awesome!”
},
“toRecipients”:[
{
“emailAddress”:{
“address”:”me@home.de”
}
}
],
“Attachments”:{“name”:”2022-112-100.pdf”,”contentBytes”:”JVBERi0xLjQKJ…..T0YK”,”@odata.type”:”#microsoft.graph.fileAttachment”}
}
but get a
{
“error”: {
“code”: “BadRequest”,
“message”: “Property Attachments in payload has a value that does not match schema.”,
“innerError”: {
“date”: “2022-04-22T19:39:51”,
“request-id”: “xxxxx”,
“client-request-id”: “xxxxx”
}
}
}
Found it myself.
The Attachments is an array, so it needs [ at the beginning and ] at the end of the Attachment part of the JSON. Even if it’s just one file to attach.
Nice work. Thanks for sharing.
Excellent been banging my head on brick wall for a while till i got to this
Amazing!! I have been trying to figure this out for days! You’re the best!
Hi damobird,
Many thanks for sharing the steps. I managed to get the flow working without attachments, but stuck at adding attachments from OneDrive. Everything works until the Attachment Compose action; I can track the file ID in the input and output section when listing files. Then Compose kicks in and Inputs and Outputs become garbled when I look at the Compose output. Here is how it looks:
\”contentBytes\”: outputs(‘PK\u0003\u0004\u0014\u0000\u0006\u0000\b\u0000\u0000\u0000!\u0000�f���\u0001\u0000\u0000D\t\u0000\u0000\u0013\u0000\b\u0002[Content_Types].xml �\u0004\u0002(�\u0000\u0002\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u00
Any idea why that might be the case?
Thanks!
I’m still trying to figure out where things are going wrong.
Here is the contentBytes section:
{
“@@odata.type”:”#microsoft.graph.fileAttachment”,
“name”:”Monthly Report May 2022.xlsx”,
“contentBytes”: outputs(‘Get XLSX Report’)?[‘body’]?[‘$content’]
}
This is exactly what is received from the previous Compose action. Before Compose, in the Get Files action step, I can successfully list the attachment item. Id, File, DisplayName … fields are correct.
The final status code is 400, “Bad request”, with the message “”Unable to read JSON request payload. Please ensure Content-Type header is set and payload is of valid JSON format.””
Any ideas where things are failing?
Hello there, I am looking to go a step further from the main example, found a couple of strings but didn’t work. Is there a way to add the current date of when the draft is created onto the subject field?
Sure, just use formatdatetime(utcnow(),’dd MMM yyyy’) or similar. Check out this video – Working with Dates in Power Automate #PowerAutomate
https://youtu.be/ybPWtu1i1j0
Hi, I am unable to create draft mail using this,, please help someone, please write step by step process and a proper explanation, please help
Hi Rahul, can you explain what is not working? The Microsoft docs provide many examples and I demonstrate how this works in both the blog and video.
Thanks very much for this.
Took quite a bit of trail and error as I’m not that much of a coder but was finally able to crack it today and the results are amazing.
In combination with your other guide – https://damobird365.com/easily-send-email-mail-merge-with-attachments/ – I’ve been able to put together something very smart.
Nice one Ben! Thanks for letting me know. Multiple drafts and attachments, top effort. What’s the next project?
The next part is can I enable this to work for others of my team. Which likely means using a SharePoint folder as the flows are using my OneDrive folder.
Found out the hard way PA does not allow reversion to earlier versions of a Flow so have got the OneDrive versions restored and copies to experiment with.
That the tools available go to this level is stunning though.
Fantastic instructions, thank you! I also went through a lot of trial & error, as I’m pretty inexperienced in this area.
In case it saves anyone else some trouble, make sure you do NOT have double quotes around the Attachments: “outputs” part in the HTTP request, unlike all of the other outputs that may be inserted there. I saw the callout to avoid double quotes in the contentBytes piece, but totally missed it in the JSON, and spent 2 hours troubleshooting such an oversight on my part. Embarrassing. But never could’ve accomplished this without your guidance. Thanks again!
Seconded! Can be tricky to spot this at times.
Hi,
Thank you for excellent article that I can able to create draft email and populate data. But I have issue with attach the attachment as the error is:
Property Attachments in payload has a value that does not match schema.
In compose the code is
{
“@odata.type”: “#microsoft.graph.fileAttachment”,
“name”: “@{outputs(‘Create_file’)?[‘body/Name’]}”,
“contentBytes”: “@{body(‘Get_file_content’)?[‘$content’]}”
}
Is there something wrong?
I think it’s double quotes around the dynamic value for content bytes. Check my sample.
Hi, I found out why. It is because you using read all the file in one folder. which is why you use apply to each. as there is issue outside Apply to each.
So I was using one file only. it there is something attach one file only instead of read each?
Create the compose called attachment but put it straight into an array [ ], ie. put the [] around the existing object.
Working thank you.
Can draft emails be sent to multiple email addresses individually?
I’d also like to include details like names and descriptions from an excel.
You can create multiple drafts with different dynamic content? Just use an apply to each. For instance you could gets rows, loop through the rows and create a draft per row.
Hi! I got this to work, but if I want to add more than one email, it is smashing them together in the draft as one email. any tips?
You want to create an apply to each based on an array of emails [“email1@email.com”, “email2@email.com”, “email3@email.com”] as input and then then you’ll create a draft for each loop.
Is there a way to do this in just one draft?
How would you create a draft manually? Would you expect 3 of the same email or use something like bcc? I don’t understand your requirement.
Is there a way to make it put all of them in just the one draft? I get the apply to each but wouldn’t that make individual drafts?
Hi Brenna, I missed your comment until now. Did you work it out? You would need to create an array of attachments and then a single create draft email call.
Can you help me on how to embed an image in the body of draft email?
Is there a way to display the image in email body instead of adding as an attachment?
I’ve just replied on YouTube also, you need to used an img tag. https://www.w3schools.com/tags/tag_img.asp
I have tried it but it’s throwing me error, could you please post your code just like above
if you are going to attach image, the content must be convert to BASE64, other wise you will got an error
[{
“@@odata.type”: “#microsoft.graph.fileAttachment”,
“name”: “@{item()?[‘DisplayName’]}”,
“contentBytes”: @{Base64(outputs(‘Get_attachment_content’)?[‘body’])}
}]
Thanks for this tutorial and video. Do you know if it’s possible to do the same with Gmail accounts?
Hi DamoBird365!
Thank you for creating this guide! It has been a huge help for me to improve one of my work processes!
There is one item that I am unable to do which is to add multiple attachments. I am unable to comprehend your instructions and apply them to PowerAutomate. I don’t understand how to implement the Apply To Each. Are you able to assist?
Can you let me know where you are stuck? Or what error you are experiencing?
Hello Mr. DamoBird365!
Thank you for your tutorials as they have been immensely helpful.
I am attempting to create a draft email, but instead of coming from my own email, I would like it to come from a shared inbox. In other words, I need the “send from” to be from a shared inbox. Do you know if this is possible? Any help would be much appreciated.
I’ve not attempted the same myself. Assuming you have permissions to the shared mailbox, have you tried adding a “from” value similar to the sample response in the Microsoft docs?
You have to use the other endpoint :
POST /users/{id|userPrincipalName}/messages
For example :
https://graph.microsoft.com/v1.0/users/contact@sharedbox.com/messages
How do i cc someomn in the above example?
You can add an array ccRecipients 👍
Sorry new to this.
Have tried to add the below-
“ccRecipients”:[
{
“emailAddress”:{
“address”: ” EMAIL”
but cant get it to work, are you able to give an example at all please?
Sorry new to this.
Have tried to add the below-
“ccRecipients”:[
{
“emailAddress”:{
“address”: ” EMAIL”
but cant get it to work, are you able to give an example at all please?
“from”: {
“emailAddress”: {
“name”: “Alex Wilber”,
“address”: “AlexW@contoso.com”
}
},
“toRecipients”: [
{
“emailAddress”: {
“name”: “Megan Bowen”,
“address”: “MeganB@contoso.com”
}
}
],
“ccRecipients”: [
{
“emailAddress”: {
“name”: “Jim Bowen”,
“address”: “JimB@contoso.com”
}
}
]
Thankyou!!
Brilliant walkthrough, works great. Thanks Damo!
Cheers Keith, thanks for stopping by 😉
Im trying to attach a single pdf to a draft
heres my Attachment portion
{
“@@odata.type”: “#microsoft.graph.fileAttachment”,
“name”: “@{items(‘Get_Attachment’)?[‘name’]}”,
“contentBytes”: @{body(‘Get_file_content_using_path’)}
}
ive tried both with and without [] around JSON part
Example:
“Attachments”: [@{outputs(‘Attachment’)}]
This gives me the “cannot deserialize” error
“Attachments”: @{outputs(‘Attachment’)}
Gives me the “Property Attachments in payload has a value that does not match schema.” Error
Any idea whats up?
You’ve missed ?[‘$content’] from the expression?
Hey, DamoBird please do not post my previous comment containing some personal work information.
But also, HOLY COW!! It’s been several days but I finally figured out the solution to my problem after troubleshooting and trying many different angles for several days. The solution is so simple as it’s brilliant.
I tried so many different things but what worked and allowed the body content in html of the email I want to forward to go into the draft is by intiatlizing a veriable for the body and passing it through a replace function that changes double quotes to single quotes. Apparently this is valid html that doesn’t conflict with JSON syntax or something like that. This is what I used.
replace(triggerOutputs()?[‘body/body’], ‘”‘, decodeUriComponent(‘%27’))
Also btw, my attachment portion of the flow does not work with the @@ syntax you present in the tutorial although I am using the “get file content using path” to add attachments from OneDrive folders to draft so idk if that is why but this works for me if anyone runs into similar issue.
{
“@odata.type”: “#microsoft.graph.fileAttachment”,
“name”: “
Name
×
”,
“contentBytes”:
$content
×
}
Thank you again!!! This tutorial sparked the start of a long arduous journey as a first time power automate user trying to automate monthly backup report emails that are forwarded from vendor to client with attachments. Cheers!!
Now I just have to clean up the body which I will use the last part of the tutorial to advise me on:)
Glad it’s inspired you. I’ve hidden your original post as requested 👍
I was able to utilize this for an outage notification, I could of sent it right of the cuff from the MS forms page but I always want to make sure I have everything correct before firing off to several departments. My issue is if a coworker uses the forms page to send a notification its being save to my drafts in my inbox. is there a solution or work around assuming https://graph.microsoft.com/v1.0/users/me/messages is pointing to me.
Using forms as a trigger will mean that it runs in the context of the flow owner. If you fired it off from a Power App, you could use run as, as part of the power apps v2 trigger and the draft would potentially be created in the run as users draft folder.
So in power automate I would need to create a flow for run as? is there anywhere I can research this or read more on it?
https://learn.microsoft.com/en-us/power-automate/create-team-flows#share-a-cloud-flow-with-run-only-permissions It has to be a button triggered flow. The obvious solution would be a Power App if you are collecting data via a form.
Would it be possible to save this to a group email or shared email? or would I still need to use power apps.
I think I’ve used a group mail box in this video about the 9:30 mark: Azure OpenAI ChatGPT – Email automation, entity extraction and sentiment analysis
https://youtu.be/Cl8qDFvNzNo
Hi DamoBird365
I am new to power automate and your demo has helped me greatly. I manage to set up an draft email. However I would like to setting the draft email with sensitivity as Confidential.
I tried { “subject”:”xxx”, “importance”:”Low”, “sensitivity”:”Confidential”, “body”:{ “contentType”:”HTML”, “content”:”xxx” }, “from”: { “emailAddress”:{ “name”: “xxx”, “address”:”xxx” } }, “toRecipients”:[ { “emailAddress”:{ “address”:”xxx” } } ], “ccRecipients”:[ { “emailAddress”:{ “name”: “xxx”, “address”:”xxx” }} ] }
and got a error message “UnableToDeserializePostBody”.
Do you know how to add the sensitivity as confidential
It might be the quotes. They need to be straight double quotes ” ” and not the 66 99 style double quotes.
Hi Damo – Trying to get the draft email to land in the Outlook app of the user who modified the item, but the flow only works for myself (as the author). I checked this out, tried to follow, but I get an error “The specified object was not found in the store., The process failed to get the correct properties.”
In the ‘Send a HTTP request”, I am using the URI as https://graph.microsoft.com/v1.0/users/@{triggerOutputs()?[‘body/Editor/Email’]}/messages
The flow is triggered when an item or file is modified.
I am getting below error message. i am drafting only message noot an attachment
URI path is not a valid Graph endpoint, path is neither absolute nor relative or resource/object is not supported for this connector.
Resources: groups. Uri: https://graph.microsoft.com/v1.0/me/messages
{
“subject”:”Did you see last night’s game?”,
“importance”:”Low”,
“body”:{
“contentType”:”HTML”,
“content”:”They were awesome!”
},
“toRecipients”:[
{
“emailAddress”:{
“address”:”gajanang@mycomp.com”
}
}
]
}
Hi DamoBird365.
Trying to implement what you have shown here – actually I simply using the code example directly from MS so nothing complicated.
But my flow is failing reporting: “URI path is not a valid Graph endpoint, path is neither absolute nor relative or resource/object is not supported for this connector. Resources: groups. Uri: https://graph.microsoft.com/v1.0/me/messages“.
Weirdly though, the identical code working through Graph Explorer.
Any ideas or thoughts.
Many thanks in advance,
needs some help with understanding the URI, I have tried several iterations and keep getting an error 400, { “error”: { “code”: 400, “message”: “URI path is not a valid Graph endpoint, path is neither absolute nor relative or resource/object is not supported for this connector. Used HTTP Request V2 and the premium HTTP Power Automate actions. The premium connector gives a 401 error, regarding authentication. It is probably something very simple I am missing. Any help is much appreciated.
Hi, DamoBird365. Thanks for all the great videos.
I am getting the same 400 error as a few others here, “URI path is not a valid Graph endpoint, path is neither absolute nor relative or resource/object is not supported for this connector. Resources: groups. Uri: https://graph.microsoft.com/v1.0/me/messages.”
I am using the Graph connector, Send an HTTP request (Office 365 Groups Email). The same thing happens if I try the V2.
I see others have had this error as well, but I don’t see a solution yet. Any help you may be able to provide would be much appreciated.
Also getting the error about “URI path is not a valid Graph endpoint, …” like the other recent comments. Looking through documentation, etc. but can’t find anything. Hoping for a reply soon to help troubleshoot this. Is it an authentication/permission issue?
Ok, great news I found my solution. Use the “Send an HTTP request” action from “Office 365 Outlook” instead of “Office 365 Groups”!!
Couldn’t reply to my own comment since it is still awaiting moderation as I write this new comment.
I noticed that if you click on the ? in the right side of the action block from Office 365 Outlook, it states “These segments are supported: 1st segement: /me, /users/ 2nd segment: messages, mailFolders, events, …”
In the http request action from “Office 365 Groups” (the one used in this blog), it states ” There is one segment that is supported: /groups.” So it wasn’t accepting the URI with /me/messages.
There must have been an update in these actions since this blog was posted.
I found the solution to the “URI path is not a valid Graph endpoint..” error. Use the “Send an HTTP request” action from “Office 365 Outlook” instead of “Office 365 Groups”!!
Couldn’t reply to my own comment since it is still awaiting moderation as I write this new comment.
I noticed that if you click on the ? in the right side of the action block from Office 365 Outlook, it states “These segments are supported: 1st segement: /me, /users/ 2nd segment: messages, mailFolders, events, …” In the http request action from “Office 365 Groups” (the one used in this blog), it states ” There is one segment that is supported: /groups.” So it wasn’t accepting the URI with /me/messages.
There must have been an update in these actions since this blog was posted.
Thanks so muh for this, Joey. Works a treat!
Hello, I am receiving the following error: URI path is not a valid Graph endpoint, path is neither absolute nor relative or resource/object is not supported for this connector. Resources: groups. Uri: https://graph.microsoft.com/v1.0/me/messages
Any suggestions for a workaround?
This is amazing so far, thank you. I get it to work when I match your steps exactly (including the apply to all), but I’m trying to do it with just “Get file content” and it seems to break it due to a non-matching schema. Any ideas?
“Property Attachments in payload has a value that does not match schema.”
Any chance you can help with drafting an email reply – ie a reply to a thread. I’ve tried defining “conversationId” but that doesn’t work.
Hello, is possible to add multiple “toRecipients” ?
Some example, please.
This is working perfect for me. However, I want to track (set regarding) the email to a specific record. Is there a way to do that?
I am trying to embed a logo image in the signature of the email. how do I do that?
Just follow the steps with detail and it will work! Read!
How do you enter multiple attachments?