Have you ever had customers emailing in outside of hours? In this post we will setup some scripted automatic maintenance of Auto-Reply responses on a user account.
We considered several possibilities but the customer did not have an Azure Subscription yet, we ended up using PowerShell, Microsoft Graph, App Authentication, and a Scheduled Task.
Our customer will be moving to Azure later so we will probably revisit this as Azure Functions, or possibly Power Automate later on. For now, we went through a few options for these responses:
- Ticketing system responses
- Outlook rules
- Out-of-office responses
- Some tool or process to receive and process emails and respond at appropriate times
We chose to use the out-of-office responses for our setup, because they would not need a separate server/service to run them, a running copy of Outlook to process them, and this customer did not have a current Azure Subscription to charge against for a more server-less solution like Azure Automation, Functions, or Power Automate.
So, since Microsoft doesn’t have a way to set up multiple sets of responses ahead of time, we need to create:
- something to make the changes
- our script below will use Microsoft Graph to update the user’s Auto-Reply settings
- a way for our script to log in without a user present
- we set up Certificate Authentication so that we can have this working securely, without a password or token to compromise
- and an automated way to run our script
- we opted for a Scheduled Task just as a simple way to schedule the update script to run regularly and access the certificate we will use to authenticate to MS Graph
Create our App Registration
First, we need to create an App to use for authentication, so that a user or administrator doesn’t have to log in every time to run this. Just like my last post, where we created an app registration to Find Microsoft Accounts on your company domain, we need to register an App for our script to authenticate and be granted permissions.
This time, for our setup process we will:
create a single tenant app
add API Permissions to ReadWrite all MailboxSettings
in my example, I am requesting ReadWrite to all, but you should be able to scope it to specific users for a more secure implementation
create a certificate for authentication
upload the authentication certificate to the new App
export local copies of the Public cert and PFX to C:\Temp
if you need to set this Script up on another machine, you will need to import the PFX into the user store on that machine
grant Admin Consent for the app permissions
Generate our Connect-MGGraph Command to use in the out-of-office automation script
This is a long list of tasks, and for more details and a more GUI-based walkthrough, I recommend you check out this post. For the ease of my setup (and to keep this a reasonable length) I included a script below to set everything up.
Just setup the first few variables on lines 2-4 with your options
Using our App Auth Certificate
To use the App auth Certificate is fairly simple, and the script above outputs the command to use. For my app it came out to the Connect-mgGraph command shown below.Sample Connect-mgGraph command shown above Connected with Certificate based, AppOnly login.
You can use the Get-mgContext to verify you are connected AppOnly/non-interactive login, as well as the app name _and your _permissions scopes.
For a comparison, here is a screenshot of what this looks like connected as my Global Admin during the app registration - Screenshot
Assembling our Update Script
Now that we can authenticate to the Graph API, we need to make a script to update the Out-of-office messages, which are part of the MailboxSettings resource.
Using those variables from the previous app we created above, it provided out several variables we will need in the top of the script below. You can see them in the previous screenshot. Pull those variables into Lines 3-6 below.
We can select our User to update the Automatic Out-of-office responses on, and even setup a Teams WebHook notification for failures or errors, like they did for this post Teams Channel Notification when OSD Fails. Just update
$WebHookURL on line 12 with your WebHookURL and set the user you want to maintain on line 9.
In the script below, I set up Out-Of-Office replies scheduled from 5PM until 8AM the following workday morning.
Next, on lines 58-75, I assemble a patch JSON, and use Invoke-GraphRequest to patch it onto our user and change the settings.
Scheduling the Script
Since this script is scheduling the out-of-office messages, but not setting them directly, it can run any time after the previous out-of-office scheduled time has finished.
Since my schedule was 5PM to 8AM Monday-Friday, I made a scheduled task and set it up to run Weekly - Monday-Friday at 9AM.In my testing, since it was only accessing the Current User’s profile, and did not need access to other networked resources, you can skip storing the password to increase security.For the program to run, we just need to specify to run the file with powershell.exe. On my system, it was trying to default opening the .ps1 in notepad, so I switched to directly running powershell.exe to bypass that.
With this setup, we have an automated flow to update the Out-Of-Office replies outside of business hours. To recap, we have:
- Made an app registration to grant the needed API Permissions to.
- Setup and used an authentication certificate for our script to connect without a user logging in.
- Made a script to invoke the Microsoft Graph API and make our change.
- Used a simple scheduled task that could run on any machine with access to the certificate to make the changes. Mostly just for a scheduling and recurrence mechanism.
This was just one small example of using the tools at hand, within our current constraints of this customer that doesn’t currently have an Azure Subscription to charge against, but it can be used with any tenant.
What processes are you looking at automating? You could dump a report of user sign-ins every week, fetch email statistics every hour, schedule removing licenses from users who are inactive, run a report of all newly created Teams and Groups in your Tenant and email those out to your admin team, or any number of other things.
Next time, maybe we can go over some of the serverless options that we could run this on if we have an active subscription, like Azure Functions, or possibly Power Automate.
Where to find me
Kevin Crouch Contributor