Send email via Logic App (from PowerShell etc.)

One of the things I use Logic Apps for is sending emails from PowerShell scripts (esp Azure Automation Runbooks or Functions). It’s pretty easy to do that.

1) Create a new Logic App with HTTP request as the trigger.

2) Click on “Use sample payload to generate schema”.

3) The idea is I’ll invoke the Logic App via its HTTP URL, using the POST method, and sending a JSON body. This JSON body will contain the addresses of the recipients, the email subject, and body. So that’s what we’ll enter here.

I entered the following:

(After taking the screenshot my OCD clicked in and I changed the case, that’s why you’ll see a difference between screenshot and the rest of this post).

Click “Done” and that generates the schema:

You could totally skip the above step and copy paste the schema instead if you wish. Nothing dodgy in there. :)

4) Create a “Send an email (V2)” connector. Sign in, if required.

Fill up the fields.

This is the completed form.

5) Click “Save” and copy paste the Url from the HTTP request box.

Now I can send emails thus (in PowerShell):

That’s it! Easy peasy. I usually store the Url in a Key Vault or as an encrypted variable as anyone with access to that Url can send an email via this Logic App. So keep it safe and secure.

All this is old stuff by the way. What I wanted to do yesterday was add an attachment! I have a runbook that generates a CSV and I wanted to attach that to the email. How the heck do I do that?

I can add “Attachments” from the additional parameters section.

This creates the following:

Hmm, so we need a name and content. If I click this button in the corner…

… it becomes the following:

Useful if I have more than one attachment I guess.

If I type in some random text and then go to the Code view I can see what it expects:

So it expects and array called “Attachments”. With entries being JSON objects of keys “Name” (the file name) and “ContentBytes” (the contents as bytes). Nice!

So I go back to the HTTP trigger and paste in this as the new sample:

That generates the following schema:

Then let’s edit the Outlook connector to add the Attachments array. I’ll switch to the array view so I can add this “Attachments” array as is. Hopefully that’s fine! 🤞🏼

Testing time!

This failed! :(

The error is No input parameters provided. Please provide required input parameters 'To', 'Subject' and 'Body'.

That is odd as it is receiving the To, Subject, etc.

If I hard code the To, Subject, and Body in the Logic App… only leaving “Attachments” from before it still fails. So looks like the error is incorrect, the issue isn’t the To, Subject, or Body.

So I removed “Attachments” and re-added it, but this time I didn’t switch to the array view. Instead, I added the Name and Contents manually. This makes it a For each loop, so if I have more than one attachment it will send multiple email (not ideal)… but since I have only one attachment currently I’ll cross that bridge later. Let’s see if this works.

It does! Sort of. The email appears with the attachment…

… but the CSV file is an array of bytes rather than the actual thing.

This is the bytes array on the PowerShell side. Notice the numbers match.

Not sure how to make the Logic App convert the bytes array back to a file?

If this were a movie at this point there’d be a montage of our hero tirelessly trying various things, Googling, cursing, more Googling and trying… but thankfully I can skip all that drama here and get straight to the solution. :)

I went to the Code View and saw that the Send an email connector is converting the array it gets into Base64. Which makes sense…

So it gets the bytes array, converts it into Base64, then Exchange Online converts it back to the bytes array and creates the file and sends. Maybe I shouldn’t be sending binary to Exchange Online? I changed it thus to convert the Base64 to binary and then send to Exchange Online.

That didn’t work out of the box until I changed things on the PowerShell side to send Base64 of the bytes.

And then it worked! Yay.

I tried another variant… where-in I removed the Base64 conversion in the Logic App so this step is just:

So it is just sending the array of bytes directly to Exchange Online without any conversion. I had tried this initially and it didn’t work, but coupled with the PowerShell code where it does the Base64 conversion… this works!

None of this makes any sense to me. Essentially I am back to where I started, just that instead of the Logic App converting to Base64 and sending to Exchange Online, it is receiving Base64 encoded text as input and passing that on. Basically I send Base64 from PowerShell instead of an array of bytes, and I tell the Logic App to pass that on to Exchange Online as is.

Recap

I realize this has been a bit of a long-winded post, so to recap: use this as the HTTP schema for the Logic App:

Create the Send Email connector and add the Attachments as above, then go into the Code View and change this:

to this:

Use the following PowerShell to send emails (change to suit your scenario of course, the below sends a test file):

There is a catch in that if there are more than one attachment, each attachment will be sent in separate emails. I spent some time trying to work around that, but left if. Got other things to do…