I am sure we can all agree that at some point or another we had a need to email a user that did not have an account within our domain via a SharePoint Designer (SPD) 2013 workflow. And while attempting to set it up we were surprised to find out it wouldn’t work. Not only did it NOT send the email, but to add insult to injury the attempt actually would suspend the workflow if forced to try. If you have never had the need, well thanks for coming to my post anyways and let me tell you… it can’t be done. An easy workaround is to build a SharePoint 2010 workflow, which doesn’t have this limitation, but then you lose the other fantastic benefits of a 2013 workflow. Microsoft removed this ability as a security enhancement. Today I am going to demonstrate how to email an external user in a SharePoint 2013 Workflow.
Quick note: Microsoft Flow does NOT have this limitation. I am describing how to to it in SharePoint Designer because so many still use this tool
Use a SharePoint 2010 Workflow
The first solution is to create a SharePoint 2010 Workflow first, which will perform the email action, and call it from our 2013 workflow. I don’t recommend this for a couple of reasons:
- SharePoint 2010 Workflows while still supported are much closer to end-of-life than the 2013 workflows so you are building a solution around a product that may be retired before you are ready.
- This solution is limited to the subsite you are working in. If you wish to perform the same steps in another subsite or site collection you will have to recreate the list and workflow all over again. The solution I am going to provide will work within your entire farm.
Email an External User in a SharePoint 2013 Workflow
So to be fully candid I am not actually going to be sending the email via the workflow. I haven’t suddenly come up with a solution that gets around the security restrictions Microsoft put in place. Instead, my solution is a combination of SharePoint, a secondary list and PowerShell. If this sounds complicated at all to you, don’t worry. It really isn’t. Like the SharePoint 2010 solution you still need to have the list in the subsite you are working in, but you actually have two key items (besides recreating the email WF over and over again) that make this method easier
- The list is so simple that you can easily recreate it over and over as needed with a PowerShell script
- You can still use a single list to handle the emails, but with SPD 2013 you are able to use REST calls to insert data into the list even if it is in another site collection (but I am getting ahead of myself).
So the overall solution is pretty straightforward:
- Create a list to hold the messages you wish to send. The list should probably have the following fields:
- Email recipient (single line of text)
- Email Sender (so you aren’t hard-coding it later) (single line of text)
- Email Subject (single line of text)
- Email Body (multiple lines of text)
- A Yes\No or Choice field with Yes and No options called Email Submitted.
- From your workflow set it up so you can insert data into this list where you need to send emails. It should look something like this:
- The next step is to build a PowerShell script that reads from this list and for any item that has the Email Submitted field set to No builds and sends out the email based on the items in the list item.
I’ll include some snippets that are important (if I give you the whole script how will you learn? ;-p)
This first snippet builds out the SPQuery used to find the relevant items
############################################################################################# #Function Name: BuildSingleFieldBooleanQuery # #Parameters: $fieldName - Field to test against # # $boolValue - Boolean value to test for # # # #Return Value: SPQuery object # #Purpose: Creates an SPQuery object that will check against a boolean field for a particular# # value (True\False) # ############################################################################################# function BuildSingleFieldBooleanQuery($fieldName, $boolValue) { $spQuery = New-Object Microsoft.SharePoint.SPQuery; $spQuery.Query = "<Where> <Eq> <FieldRef Name='$fieldName' /> <Value Type='Boolean'>$boolValue</Value> </Eq> </Where>" return $spQuery; }
Then you build the query and execute it against your list:
#build the query to get the list of emails to send $emailsQuery = New-Object Microsoft.SharePoint.SPQuery; $emailsQuery = BuildSingleFieldBooleanQuery $emailSentField 0; #get the list of items that require an email to be sent $emailsToSend = $spList.GetItems($emailsQuery);
Then you loop through each item found and generate the email. Emailing from PowerShell doesn’t have an external user limitation. PowerShell’s Send-MailMessage commandlet is a fire and forget. It doesn’t care about the destination.
foreach($emailItem in $emailsToSend) { if($emailList.EmailSender) { $sendFrom = $emailList.EmailSender; } else { $sendFrom = $emailItem[$emailList.EmailSenderField]; } $emailSubject = $emailItem[$emailList.EmailSubjectField]; $emailBody = $emailItem[$emailList.EmailBodyField]; $emailRecipient = $emailItem[$emailList.EmailRecipientField]; #check to see if we have multiple recipients if($emailRecipient -like "*;*") { [string[]]$emailRecipients = $emailRecipient.Split(';',[System.StringSplitOptions]::RemoveEmptyEntries); } else { $emailRecipients = $emailRecipient; } #send the message Send-MailMessage -To $emailRecipients -From $sendFrom -Subject $emailSubject -Body $emailBody -SmtpServer $emailList.SMTPServer -BodyAsHtml ... ... ... }
And that’s it. What’s great about this is as you add more and more lists that require this process you simply need to update your config file for the PowerShell script to incorporate the new sites and lists. No changes or re-coding required as your needs grow.
Thanks for reading!!
Comments
Great concept Sir, but you didn’t identify how/where to place and execute the associated PowerShell script. Should this be set-up as a recurring Scheduled Task? Manually run at your leisure? Please advise… Thanks! (Also, do you have the consolidate script available for download?)
You are correct I didn’t. The option is up to the admin. It is certainly something that can be automated by placing it on a server with a scheduled task, but that really wasn’t the point of the post. I leave it up to the admin to determine the best method for implementing my solution. I am afraid I do not have the consolidated script.
Thanks for reading the post and leaving a comment!