Showing results for 
Search instead for 
Did you mean: 
Regular Visitor

Microsoft Password Expiration Notification

Microsoft Password Expiration Notification Emails


Microsoft Removes 365 Email Notifications


There was previously a field named "Days before a user is notified about expiration". You are not going crazy, this used to be an option until Microsoft removed it. 



Solution 1: Microsoft Password Expiration Email Notifications with PowerShell


The Password Expiry Email Notification PowerShell Script is commonly used. The script can be loaded onto a domain controller and used with CSS to style the email. 
The emails can look very professional with trial and error and a bit of web tinkering, what engineer doesn't like a bit of web design 😛


There are versions of the script which use "new-StoredCredential" which creates a value in credential manager on the domain controller running the script. These can be easily removed by Windows updates and occasionally windows reboot, which can make them frustrating to manage. You are stuck either re-publishing the value manually to credential manager or scripting it and showing the password in plain text.  


The link above uses a hashed text file and the New-Object with -typename System.Management.Automation.PSCredential. Although this resolves the problem of plain text passwords, it's still not an ideal solution. 


1. When an admin/engineer leaves the business, you are stuck trying to re-hash the password and re-configure the script to accept the new text file. 


2. Microsoft continue to push users away from legacy auth. Although they have once again delayed their September 2022 deadline to January 2023, they will make this change eventually. Yes I know SMTP is not part of the change (as long as you have existing SMTP traffic), but it will be changed eventually and they have made their concerns public about SMTP legacy auth. 


3. More work when you move to a cloud only AAD


Solution 2: Microsoft Password Expiration Email Notifications with PowerAutomate


Articles like this have explained this, however the date format didn't work for me. After manipulating it many times, the solution ended up being quite simple. 


1. Create a recurring timer:




2. For testing, you can use search terms from a Search for Users (V2) which will allow you enter names of test users. *obviously test thoroughly before releasing to prod.





3. Using a loop, iterate through each of the values you got from the Search for Users (V2) {Note: Once you are done testing, change the checkbox to Is Search Term Required: No}. Each returned value is the full schema data for a user including name, ID, phone number, country etc. Select only User Id 





4. Log into Azure and create a new App Registration, with a suitable name. Select the prefered account type when you are creating the app registration. Accounts in this organizational directory only is usually preferred. 





5. Once created, go to API Permissions on the left, add/confirm you have:

If you are missing permissions, click Add a Permission > Microsoft Graph > Application Permission > search for User.Read and click Add Permission. Also do this for User.Read.All. Once complete, click Grant admin consent for <domain name>, you will need administrative permissions for this. 





6. Go back to your Flow and use the HTTP Get action to call the Microsoft Graph API. The summary of details is below:


Method: GET

Authentication: OAUTH


Tenant: Enter tenant ID from Azure AD Portal.

Client ID: Get this value from the App Registration > Overview section in the Azure Portal

Secret: Go to the App Registration > Certificates and Secrets > + New Client Secret > give it a name and expiration date > copy the value. The value will be unreadable when you leave the page. If you lose it, just re-create it and delete the old. 





7. Create a Compose action and use the following as an input body('GetLastPasswordChange')?['lastPasswordChangeDateTime']}  

You will notice the GetLastPasswordChange is the name of the HTTP GET. The lastPasswordChangeDateTime is the name of the schema attribute from the user. 





8. Use a second Compose action and enter the following expression

This will give you the difference in days between the current time and the last password change date. 


9. Depending on your password policy, create a condition for the amount of days needed. You could make this more sophisticated with integration to AAD Groups. If you use Fine Grained Password Policies (FGPP), you could also use on-prem AAD Connect synced groups so users in different groups get different notifications. 




10. If Teams notifications are also needed, this is a simple integration. 

Hope this helps some people!


Accepted Solutions

Hi @monro ,

Thanks for sharing, your sharing is awesome!!!

Please mark this thread as resolved, this will allow more people to see this thread, which will help more people.




Best Regards

Cheng Feng

View solution in original post


Hi @monro ,

Thanks for sharing, your sharing is awesome!!!

Please mark this thread as resolved, this will allow more people to see this thread, which will help more people.




Best Regards

Cheng Feng

Regular Visitor

Replying to myself

If you have hundreds of users and you need to release to UAT users first, step 2 is not correct and you will need to use an array, which realistically means building a separate flow. 

Steps below should be enough to figure out a UAT flow. Format for the Initialize Array is below (no comma on final array line):

"UPN 1",

"UPN 2",

"UPN 3"




Helpful resources

Power Automate News & Announcements

Power Automate News & Announcements

Keep up to date with current events and community announcements in the Power Automate community.

Power Automate Community Blog

Power Automate Community Blog

Check out the latest Community Blog from the community!

Users online (3,321)