Office 365 Email Password Reminder
January 23, 2015 62 Comments
Regular readers will no doubt be aware of the script i wrote about two years ago to alert a user their password was about to expire. If not, just what exactly have you been doing with your time?
In any case, several people have asked me if it can be made to work with Office 365. Using 365 as the email relay to send the messages, was one thing, querying 365 for a users password expiry, was something else. Something which at the time i believe could not be done.
Given they constantly release new features and tweaks, i revisited it this week and found that actually it can now be done, with a few tweaks to the original script.
The first changes are that you will need the Microsoft Online Services PowerShell tools. There are various guides on this out there, this is just the first one i hit when writing.
Once you have that you can use this code to Connect to Office 365.
# Connect to Office 365
Import-Module MSOnline
$cred = Get-Credential
Connect-MSolService -credential $cred
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell/ -Credential $cred -Authentication Basic -AllowRedirection
Import-PSSession $Session
Those familiar with PowerShell will see i am using the Get-Credential command here, rather than saving credentials directly into the script. Whilst saving credentials certainly makes things easier for scheduling the task, it is a security risk. i am not comfortable with suggesting you store credentials in the script (hashed or encrypted) or showing an example of it. so feel free to investigate that at your own risk.
Anyway running the command above, will get you connected into Office 365. We can then find our Users who have passwords that expire.
# Get Users From MSOL where Passwords Expire
$users = get-msoluser | where { $_.PasswordNeverExpires -eq $false }
We will also get the Default 365 domain, and the Maximum Password Age.
$domain = Get-MSOLDomain | where {$_.IsDefault -eq $true }
$maxPasswordAge = ((Get-MsolPasswordPolicy -domain $domain.Name).ValidityPeriod).ToString()
Once we have this info, it is trivial to go through and work out when a users Password is going to expire.
# Process Each User for Password Expiry
foreach ($user in $users)
{
$Name = $user.DisplayName
$emailaddress = $user.UserPrincipalName
$passwordSetDate = $user.LastPasswordChangeTimestamp
$expireson = $passwordsetdate + $maxPasswordAge
$today = (get-date)
$daystoexpire = (New-TimeSpan -Start $today -End $Expireson).Days
}
The full script of course goes on to include the other items like logging, sending the email etc etc but i just wanted to focus on the Office 365 specific parts here.
If anyone would like a copy to try out in their environment please download it from here.
Update:
Lots of people have requested a copy of the script, thanks for the support! I just want to add this script is for a fully separate 365 deployment. If you have any on premises Domain Controllers, and you are using DirSync (or the current incarnation) then you can use the other script to query your on Prem DCs for Password Expiry info.
Also noted recently that a tenant with Azure AD linked, no longer shows a MaxPasswordAge attribute, so this may prevent the script working in the future without some manual tweaks.
Hi Robert.
I tried to incorporate the 365 parts into your old script, but i can’t seem to get it working. Is it possible you could send me the complete script?
The script i’m using doesn’t give me any errors but nothing happens anyway.
Hello Robert,
Will you please provide me with the full up-to-date script?
Reagrds
Hi Robert,
we are using Azure AD Sync to sync our AD accounts with Office 365. Do you have an updated script that will allow an Office 365 account to send the email notification to the users? We have no on premises smtp or Exchange servers.
I am enjoying reading your posts!
Thank You.
Did you ever get this to work in your environment? I have the same environment and would like to be able to schedule the script to send these emails.
Robert,
I would love to get a copy of the final script if possible.
Is there a script that would allow our hosted exchange to send the emails? We’re not using 365 (we run apps through Citrix) but I’m guessing the hosted bit might make it a little more tricky of a script. Any thoughts?
I guess it depends on the platform your Exchange is hosted with.
I would like a copy of the full script.
I would also like a copy of the full script, please.
Did anybody get a copy of this script? It would really come in handy in MSP world with clients who are less-than-tech-savy.
I can send you one if you like.
Hi Robert, please send the script through to me also. Cheers.
Got it! Thank you Robert!
Can You send the final script to me too?
Hi Robert,
Can i get a copt too?
Hi Robert, please forward the script. Thank you. – rexila@gmail.com
Robert,
I would love to have a copy of the script. We have many off site clients that are on their mobile devices and never get a notification that their password is going to expire. Could you please send me a copy when you get a chance?
Thank you
Robert, May I have a copy. Thank You
Would like a copy as well!
Hi Robert,
Kindly forward me the full script too.
Thank you
Hello,
Please could you send me a copy of the script, this sounds excellent!
Thanks
Please send me a copy too. Thanks!
You can download it from here.
http://1drv.ms/1dMrtQu
Thanks!
Anyway to send me the full script thank you
You can download it from here.
http://1drv.ms/1dMrtQu
I am unable to download the script. Link is no longer valid. Could you provide a new link
Hi, can you send me the full script? Link doesn’t work anymore.
Thank you so much for this, one issue my date format is ddmmyyyy but in the log file it is mmddyyyy Should i change the script to match the log file
Yes you can do!
Robert, can you supply me with the script please?
Reading above I think this will help me a lot.
Link is still working for me?
Try this one instead.
https://onedrive.live.com/redir?resid=76ADE246838C632B!153608&authkey=!AIuGGnDzUiBuXF8&ithint=file%2cps1
Thanks, that link worked.
Robert, I’ve tried both links in the article and I’m not able to download the script. Do you have a new link available?
I can set one up yes.
I think this should work.
https://1drv.ms/u/s!AitjjING4q12ldtkqxPYqQbgd9e4eg
Hi,
Link is not working anymore. Can you update it and share with full script? Thanks!
Dear Robert, could you provide me a link for downloading the script. The links above don’t seem to work anymore. Thanks in advance.
Kind regarsd, Erik
Hi Marco,
The link you provided on 4 May 2016 is no longer work. Can you please provide another link or you can email me?
Thank you.
Robert,
The link you provided no longer works.
Can you please update?
I have an immediate need for this script.
Thank you
https://1drv.ms/u/s!AitjjING4q12ldtkqxPYqQbgd9e4eg Try this one
That works!
Thank you so very much.
I stumbled across your site and I have found a lot of help on some things.
I really appreciate your contributions.
Robert,
I found a couple of issues in your script.
I made some modifications to correct the issues and am including them below.
You may want to update your script.
First, for whatever reason, Microsoft changed the ConnectionUri. “-liveid” should be added in the Uri. The script will run without this, but you get a bunch of warnings in your PowerShell window.
Here is the corrected PSSession:
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell-liveid/ -Credential $cred -Authentication Basic -AllowRedirection
Also, you MUST remember to remove your session at the end of the script. I added the following to the end of the script:
#####################################
#
# Disconnect from Office 365
#
Remove-PSSession $Session
#
# End
I hope these changes help everyone else who uses this script. I have been trying to get some kind of PowerShell script like this to work for some time. Robert, I really appreciate your putting your script out there for us.
Thanks, it’s quite an old script now and they seem to update 365 daily these days with new requirements!
Since I’m not an expert at PowerShell scripting, is there someone willing to help me debug some errors I’m getting?
We can try.
Hello
I’m using this scripts with Brian modyfication. Unfortunetelly in testing mode scripts runs with warnings but in log file I have only headers nothing else. For sure i have account that password will expire soon.
How to degug problems?
How to verify if expire date is properly calculated?
How to chech if this script check all my users ?
Maybe this is problem with locale or date format?
I have polish regional settings.
Help me please
Regards
Slawek
You can use this post as a starting point for troubleshooting, https://windowsserveressentials.com/2014/09/17/troubleshooting-my-password-change-notification-script/
Hi
As You recomended I started with easiest things first:
get-msoluser | where { $_.PasswordNeverExpires -eq $false } | Export-Csv c:\temp\Users.csv -NoTypeInformation
WARNING: More results are available. Please specify one of the All or MaxResults parameters.
Files was created, but is empty.
get-pssession
Id Name ComputerName State ConfigurationName Availability
— —- ———— —– —————– ————
34 Session34 ps.outlook.com Opened Microsoft.Exchange Available
So I’m logged in
Could You point me what to do next?
I’m PS newbe ….
I believe you solved this using -all ?
Yes, -all solved problem with users.
I had to modify a bit:
$maxPasswordAge to constat value – and now it seems to be working with user from all of my 3 domains.
Of course I need more time to verify because I cant prepare users with password that expires in dew days
Regards
Slawek
Hello
Unfortunately something is wrong with “my” script now.
It warn only account that’s expire today. I don’t know why. I modyfied:
In variables section I add “$maxPasswordAge = 180”
and
$users = get-msoluser -all | where { $_.PasswordNeverExpires -eq $false }
#$domain = Get-MSOLDomain | where {$_.IsDefault -eq $true }
$domain = Get-MSOLDomain
#$maxPasswordAge = ((Get-MsolPasswordPolicy -domain $domain.Name).ValidityPeriod).ToString()
I tryed to debug using:
Get-MsolUser -All | select DisplayName, LastPasswordChangeTimeStamp,@{Name=”PasswordAge”;Expression={(Get-Date)-$_.LastPasswordChangeTimeStamp}} | where {$_.PasswordAge -gt “1”} | sort-object PasswordAge -descending
But this command need modyfication to list only account that are not with PasswordNeverExpires is true
{ $_.PasswordNeverExpires -eq $false }
I try to add this condition, but I get 0 resoults :(
Help me please
Regards
Slawek
Hello
I get it working by adding “-all” in “$users = get-msoluser -all”
Thank You!
Regards
SLawek
Hi
I need help with Your script. If I test it on my test tenat (with one domain) is working fine. When I lunched it on tenant with 3 domain it shown nothing…. Help me please to debug problem.
With regards
Slawek
I’m trying to set this up, and have an issue with the smtp exception… we only use Office365 in the cloud, and it requires a secure connection. Suggestions on how to make this work within our environment so it sends the mail? It gives the error on line 110.
What value are you using for your smtp server?
I actually figured it out. I needed to put in the smtp I use for configuring my non-tls devices. Thank you for this! It helped me sort out a HUGE issue today. Powershell is definitely the friend of the Office 365 Admin!
Hi Robert
Can you send me the script you have for the DIrSync version?
Are you using Azure AD?
Hi Robert
Link from OneDriver dosent working (redirect to https://onedrive.live.com/?v=error&type=linknotsupported). Could You corect it or send me copy of script directly to my email please?
I have updated the link in the post.
Link is OK now
Inside this file is “Version 1.3 Jan 2015” is it OK?