I have scripted PwdNotifyAll.bat to email a password expiration notice to all users whose password will expire in n days.

The syntax for using PwdNotifyAll.bat is:

PwdNotifyAll \[Days\]

Where days is an optional parameter that defaults to 10.

PwdNotifyAll.bat generates a PwdNotifyAll.log file, in the same folder as PwdNotifyAll.bat.

PwdNotifyAll.bat uses DSQUERY, and the following files, which must be in your path:

GetUsers.bat
JSIDateM.bat
Univdate.bat
Date2JD.bat
JD2Date.bat
Blat.exe

I recommend scheduling PwdNotifyAll.bat, using a Domain Admins account whose password never expires, and that never logs on, so it will run in the background, such as SchedTask@jsiinc.com. I use Scheduled Tasks to run PwdNotifyAll.bat every day, at 00:01, on the PDC emulator.

PwdNotifyAll.bat contains:

@echo off
setlocal
set days=10
if not \{%1\}==\{\} set days=%1
set /a days=1000%days%%%1000
:: set folder path
set pwdnotifyall=%~f0
set log="%pwdnotifyall:bat=log%"
call univdate
set /a mm=100%mm%%%100
set /a dd=100%dd%%%100
set /a yy=10000%yy%%%10000
if %yy% LSS 10 set /a yy=200%yy%
if %yy% LSS 100 set /a yy=20%yy%
if %mm% LSS 10 set mm=0%mm%
if %dd% LSS 10 set dd=0%dd%
set tdyy=%yy%
set tdmm=%mm%
set tddd=%dd%
@echo %tdyy% %tdmm% %tddd%>%log%
set today=%tdyy%%tdmm%%tddd%
call :logit>>%log% 2>>&1
if exist "%temp%\PwdNotifyAll.tmp" del /q "%temp%\PwdNotifyAll.tmp"
endlocal
exit /b 0
:logit
for /f "Tokens=*" %%a in ('getusers') do (
 call :userinfo %%a
)
goto :EOF
:userinfo
set user=%1
set expires=N
for /f "Tokens=3" %%b in ('net user %user% /domain^|findstr /i /c:"Password expires"') do (
 set expires=%%b
)
if /i "%expires%" EQU "N" goto error1
if /i "%expires%" EQU "Never" goto :EOF
:: The following is for MM/DD/YY date format. If net user returns DD/MM/YY, or DD-MM-YY,
:: then set dd=%%x and set mm=%%y.
for /f "Tokens=1-3 Delims=/-" %%x in ('@echo %expires%') do (
 set mm=%%x
 set dd=%%y
 set yy=%%z
)
set /a mm=100%mm%%%100
set /a dd=100%dd%%%100
set /a yy=10000%yy%%%10000
if %yy% LSS 10 set /a yy=200%yy%
if %yy% LSS 100 set /a yy=20%yy%
if %mm% LSS 10 set mm=0%mm%
if %dd% LSS 10 set dd=0%dd%
Call JSIDateM %yy% %mm% %dd% - %days%
if "%today%" LSS "%AYMD%" goto :EOF
set getemail=dsquery * domainroot -filter "(&(objectCategory=Person)(objectClass=User)(sAMAccountName=%user%))" -attr mail
for /f "Skip=1 Tokens=*" %%e in ('%getemail%') do (
 set email=%%e
)
set email=%email:  =%
set work=%email:@=%
if "%work%" EQU "%email%" goto error2
@echo The %USERDNSDOMAIN% domain password for user %user% expires on %expires%. Please change your domain password.>"%temp%\PwdNotifyAll.tmp"
blat "%temp%\PwdNotifyAll.tmp" -to %email% -s "The %USERDNSDOMAIN% domain password for user '%user%' expires on %expires%."
goto :EOF
:error1
@echo PwdNotifyAll - Syntax - %user% user not found.
goto :EOF
:error2
@echo PwdNotifyAll - Syntax - %user% email %email% invalid.