Office 365 Email Password Reminder

powershell2xa4Regular 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 -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.


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.

About Robert Pearman
Robert Pearman is a UK based Small Business Server enthusiast. He has been working within the SMB IT Industry for what feels like forever. Robert likes Piña colada and taking walks in the rain, on occasion he also enjoys writing about Small Business Technology like Windows Server Essentials or more recently writing PowerShell Scripts. If you're in trouble, and you can find him, maybe you can ask him a question.

62 Responses to Office 365 Email Password Reminder

  1. shareonline says:

    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.

  2. Yves Leduc says:

    Hello Robert,

    Will you please provide me with the full up-to-date script?


  3. wcmulligan says:

    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.

    • Curt Winter says:

      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.

  4. Mike Kullish says:

    I would love to get a copy of the final script if possible.

  5. Stephen says:

    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?

  6. Andrew Hericks says:

    I would like a copy of the full script.

  7. Steve S. says:

    I would also like a copy of the full script, please.

  8. Rebecca says:

    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.

  9. yorkr says:

    Hi Robert, please forward the script. Thank you. –

  10. Alec Brownlie says:


    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

  11. Mark says:

    Robert, May I have a copy. Thank You

  12. Matthew says:

    Would like a copy as well!

  13. Royke says:

    Hi Robert,

    Kindly forward me the full script too.

    Thank you

  14. Andrew says:


    Please could you send me a copy of the script, this sounds excellent!


  15. Chuck says:

    Please send me a copy too. Thanks!

  16. Frank says:

    Anyway to send me the full script thank you

  17. Neil says:

    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

  18. Marco says:

    Robert, can you supply me with the script please?
    Reading above I think this will help me a lot.

  19. Martin says:

    Link is not working anymore. Can you update it and share with full script? Thanks!

  20. Erik says:

    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

  21. Arief says:

    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.

  22. Brian Beckers says:

    The link you provided no longer works.
    Can you please update?
    I have an immediate need for this script.

    Thank you

      • Brian Beckers says:

        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.

      • Brian Beckers says:

        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 -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!

      • Andrew says:

        Since I’m not an expert at PowerShell scripting, is there someone willing to help me debug some errors I’m getting?

  23. Slawek says:

    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

      • Slawek says:


        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.


        Id Name ComputerName State ConfigurationName Availability
        — —- ———— —– —————– ————
        34 Session34 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 ?

      • Slawek says:

        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


      • Slawek says:


        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”
        $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


      • Slawek says:


        I get it working by adding “-all” in “$users = get-msoluser -all”
        Thank You!


  24. Slawek says:

    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

  25. Suzanne Mastaw says:

    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?

      • Suzanne Mastaw says:

        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!

  26. Will Reid says:

    Hi Robert

    Can you send me the script you have for the DIrSync version?

  27. Slawek says:

    Hi Robert

    Link from OneDriver dosent working (redirect to Could You corect it or send me copy of script directly to my email please?

  28. Slawek says:

    Link is OK now

    Inside this file is “Version 1.3 Jan 2015” is it OK?

Leave a reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: