Sending Emails from SharePoint Solutions Using Microsoft Flow
It’s not at all unusual to want to send an email from some page in SharePoint where there isn’t a native capability available. While there are lots of external services which can send email for us – like SendGrid – we usually want to keep the email “in house” in an enterprise environment. (In fact, there’s even a connector for SendGrid in Flow.)
While using an external service may not be appealing, even Flow is an “external” service. Once you’re in the cloud, you’re in the cloud. However, it seems to make more sense in many cases to simply use Flow to send emails via the Outlook Send an email action.
I’ve started setting up a generic Send an email Flow to support several client projects, so I figured I’d document what I’ve been doing.
The basic idea here is that I want to be able to call a REST endpoint with the details of the email I’d like to send and have it go out to the recipient(s). There’s no validation or tracking here; I just assume it happens. It wouldn’t be all that hard to add another few steps to log the emails to a SharePoint list or something if that were useful for you.
Flow has a perfect trigger for this: When a HTTP request is received. (I would have gone with When an HTTP request is received, personally.)
Start by creating a Flow “from blank”, meaning without using a template. If you search for HTTP, you’ll find the When a HTTP request is received trigger.
This trigger is a great way to create a poor man’s Web Service, just like we need here. Note that the REST endpoint will be provisioned after you save the Flow, so at this point, we don’t know what it will be, but no matter.
I had decided that my payload for the emails was going to be pretty simple, made up only of the To (recipient), Subject, and Body. That’s all it really takes to make a useful email. To set up a sample payload, I decided what I’d like to send in one of my client side SPAs (Single Page Applications) and dummied up some data, like so:
{ "To": "[email protected]", "Subject": "This is the email", "Body": "Welcome to Flow!" }
The nice thing here is that Flow will generate the schema it needs from sample data like this. Click on Use sample payload to generate schema and paste in your sample data, like so:When you click Done, you’ll see the schema the trigger needs to “understand” the data you will be sending. If you wanted to make changes to the structure of the incoming data, you could paste in a new sample or edit the schema manually.
{ "type": "object", "properties": { "To": { "type": "string" }, "Subject": { "type": "string" }, "Body": { "type": "string" } } }
Next we simply add a new step to send the email by clicking on New step, then Add an action. I find it by searching for “email”.
Once you’ve chosen that action, you can add the incoming data properties to the properties the Send an email action uses to form the email.
I like to have the option to send HTML emails (all pretty and everything), so I set the Is HTML advanced option to Yes.
It’s also worth noting – mainly because John Liu (@johnnliu) just reminded me after he read this post – that emails go out with Low priority unless you change the setting.
It’s not at all intuitive that this wold be the case, but it may well be how you’d want it set. If not, it’s a simply change in the dropdown in the advanced options.
Once you’ve saved the Flow, you can go back into it to get the REST endpoint you need to invoke it.
Finally, you’ll want to call the REST endpoint whenever you want to send an email. Here’s an example function I use in one of my Angular-based SPAs. It’s a pretty generic function, and I simply pass in the to, subject, and body values. Any work I need to do to build up those values happens elsewhere. (Lest you think you can use my Flow, I’ve edited the endpoint inventively. My Flow is still in an undisclosed location.)
self.sendEmail = function (to, subject, body) { var deferred = $q.defer(); var emailData = { To: to, Subject: subject, Body: body } var request = { url: "https://prod-22.westus.logic.azure.com:443/workflows/bb870e92045487cd9bec959ed37b222a/triggers/manual/paths/invoke?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=FMfqf93y0-MRXh05PcZnr4WSHJ6z3gYZ3mQapvNab3c", data: angular.toJson(emailData), headers: { "Accept": "application/json", "content-type": "application/json;odata=nometadata" } }; var success = function (response) { deferred.resolve(response.data); }; var error = function (response) { deferred.reject(response.data); }; $http(request).then(success, error); return deferred.promise; };
And voila! Now you have an easy to use, generic emailing function. One downside to this approach is that the email will be sent using your own connection. For this reason, you may want to set up some fake “users” for the connections in Flow – maybe “SharePoint administrator” or something. I’m hoping the Flow team comes up with a better way for us to manage who the Flow runs as in the future, but for now this works.
Addendum: Eagle-eyed reader Charles Phillips (aka Grumpy Old SharePoint Guy) asked via email why I didn’t just send the email via JavaScript. Call me lame, but to be honest, I wasn’t aware of the method Charles covered in his post How do I send an email in JavaScript?, specifically the /_api/SP.Utilities.Utility.SendEmail method. I guess the other benefit of using Flow is that we can layer in additional generic capabilities as we need them, perhaps logging to a list, informing the sender, etc. without writing any code to do it. I like having a generic call that can do this stuff for me. However, if you’re on premises or can’t use Flow for some reason, the SP.Utilities.Utility.SendEmail endpoint could work well for you.
Hi Marc,
thank you for sharing your code!
According to the SPUtility.SendEmail method there is still the difference that it cannot send attachments where it seems that you could add this in the shown Flow action.
Of course you have not used this in your example but I think this limitation of SPUtility.SendEmail is important to know.
Best regards,
Nicolai Hess
Hi Marc,
I’d probably go for “send an email from a shared inbox” action, then you have the email coming from a more generic address.
regards
Terry
Hi Marc,
I think this connector on Power Automate no longer existed. fyi :)
@Ethem:
True! If I tried to go back and correct all my old blog posts as things change, I’d never get anything else done. :)
M.