今回はシステム管理者向けのお話です。
システム管理者またはITヘルプデスク業務を行われている方は、あるあるな話ではないでしょうかね。
社内PCがWindow10になってからドメインユーザのPW更新ポップアップを見落とすことが多くなり、ユーザのPW更新切れのヘルプコールが増発しました。
今回、画面ポップアップ+メール通知して更新を促す仕組みを作ってみました。
これにより、更新切れのヘルプコールは無くなりました。
ちなみにこのパスワード有効期限のチェックプログラムは、Windowsの日本語、英語、韓国語環境に対応しています。
1. 現状課題
私の会社では、以下のような設定・環境になっています。
- パスワードの有効期限は半年、45日前からアラート通知
- 作業の効率化のため、ノートPCを貸与しており、外部モニタも利用
- ユーザはPW変更が面倒という認識で、ほとんどの人がギリギリに変更
->主にWindowsのメインモニタがPC側のため、いつも外部モニタを見ているとノート画面の右下に出る通知を見落としてしまう。
2. 解決策
パスワード有効期限が迫ったユーザに対して、「ポップアップ画面表示」と「パスワード有効期限通知メールの送信」で通知する。
- 「有効期限通知メッセージ」ウィンドウを画面に表示
- 「パスワード有効期限の通知」メールを自動送信
- 管理用として、毎日最新の「PW有効期限リスト」を自動作
2.1「有効期限通知メッセージ」ウィンドウの仕様
- 期限20日前から2時間毎(*)、メッセージボックスを表示 (*月曜~金曜の10時から16時まで)
- メッセージボックスは前面表示し、OKボタンを押さない限り、他の操作をさせない
2.2「パスワード有効期限の通知」メールの仕様
- 期限10日前から3時間毎(*)、ユーザ+システム管理者宛へ通知メールを自動送信 (*月曜~金曜の6時から18時まで)
3. 作成したプログラムと実行フロー図
3.1 プログラム構成
#1〜#5のファイルを同じ場所に保管し、#1と#5の実行で自動で設定が完了します。
変更する際、保管先は、ユーザの閲覧権限がある場所に保管されると良いです。
また、#2、3、6のファイルは、ユーザプロファイルの直下に保管した方が無難と思います。
# | ファイル名 | 用途 | 保管先 |
1 | PWCHK_Setup.vbs | システム用)PWチェック関連プログラムのセットアップ | \\FS\UserPWchk\ |
2 | PWGET.vbs | ユーザ用)パスワード有効期限を取得 | \\FS\UserPWchk\ (動作時)%USERPROFILE%\ |
3 | PWMSG.vbs | ユーザ用)パスワード有効期限のメッセージを表示 | \\FS\UserPWchk\ (動作時)%USERPROFILE%\ |
4 | PWAlertML.vbs | ユーザ用)有効期限10日以内のユーザにメール通知 サーバ側のタスクスケジューラーより実行 | \\FS\UserPWchk\ |
5 | TaskSchedule-Reg.bat | 管理者用)タスクスケジューラー登録バッチ | \\FS\UserPWchk\ |
6 | PasswordExpire.txt | ユーザ用)ユーザのパスワード有効期限日を保存 | %USERPROFILE%\ |
7 | PWNotify.csv | 管理者用)全ユーザのパスワード有効期限一覧 | \\FS\UserPWchk\ |
3.2 実行フロー
1.ユーザの初回ログオン時に実行
ログオンスクリプトやGPOなどに登録しておき、#1のプログラムをユーザの初回ログイン時のみ実行させるようにします。
#1プログラムでは、下図の通り、以下の動作を行なっています。
- 2つのプログラムをコピー
- PCにタスクスケジューラーを登録
- #2のプログラムを実行し、PW有効期限を取得する
2.PCのタスクスケジューラーにて、月〜金の10、12、14、16時に実行
上記で登録したタスクスケジューラーは、ユーザのPCで月〜金1日4回、下図の動作を実行します。
3.サーバのタスクスケジューラーにて、期限10日以内であれば3時間毎に通知メールを送信
ADサーバやファイルサーバなどに#6のプログラムをタスクスケジューラーに設定し、PW有効期限が近いユーザへメール送信、管理者向けにユーザのPW有効期限一覧を作成します。
3.3 実行プログラム
さて、ここからプログラム本体の話になりますが、文面が長くなりそうですので、目次のリンクから辿ると良いと思います。
1.PWCHK_Setup.vbs
このプログラムは、ログインスクリプトなどでユーザがログインするたびに実行するようにしておきます。
初回実行済みかは、タスクスケジューラの登録確認をしています。
実際の使用には、コメントアウトした【## 変更箇所 ##】の欄を変更してください。
Option Explicit
Dim WSH, wExec, sCmd, Return
Dim FSO, UserHome, PWCHK_Path
Set WSH = CreateObject("WScript.Shell")
Set FSO = CreateObject("Scripting.FileSystemObject")
'タスクスケジューラーにPWExpireCheckが登録されているか確認
'未登録の場合は、スケジュール登録、必要ファイルをローカルにコピーする。
sCmd = "schtasks /query /tn PWExpireCheck10"
Return = WSH.Run("%ComSpec% /c " & sCmd, 0)
If Return = 0 Then
'Get User home directory
UserHome = WSH.ExpandEnvironmentStrings("%USERPROFILE%")
'【## 変更箇所 ##】PWMSG/PWGETファイルをユーザフォルダにコピー保存
FSO.CopyFile "\\fs\UserPWchk\PWMSG.vbs", UserHome & "\", true
FSO.CopyFile "\\fs\UserPWchk\PWGET.vbs", UserHome & "\", true
'PWGETを実行しパスワード有効期限ファイルを作成
sCmd = FSO.BuildPath(UserHome, "\PWGET.vbs")
WSH.Run "%ComSpec% /c " & sCmd, 0
'タスクスケジューラの登録(実際は、5分前通知)
PWCHK_Path = FSO.BuildPath(UserHome, "\PWMSG.vbs")
sCmd = "schtasks /create /tn PWExpireCheck10 /tr """ & PWCHK_Path & """ /sc weekly /d mon,tue,wed,thu,fri /st 9:55 /F"
WSH.Run "%ComSpec% /c " & sCmd, 0
sCmd = "schtasks /create /tn PWExpireCheck12 /tr """ & PWCHK_Path & """ /sc weekly /d mon,tue,wed,thu,fri /st 11:55 /F"
WSH.Run "%ComSpec% /c " & sCmd, 0
sCmd = "schtasks /create /tn PWExpireCheck14 /tr """ & PWCHK_Path & """ /sc weekly /d mon,tue,wed,thu,fri /st 13:55 /F"
WSH.Run "%ComSpec% /c " & sCmd, 0
sCmd = "schtasks /create /tn PWExpireCheck16 /tr """ & PWCHK_Path & """ /sc weekly /d mon,tue,wed,thu,fri /st 15:55 /F"
WSH.Run "%ComSpec% /c " & sCmd, 0
End If
Set wExec = Nothing
Set FSO = Nothing
Set WSH = Nothing
2. PWGET.vbs
#1でユーザPCにコピーされる本プログラムですが、タスクスケジューラにより実行されます。
net userコマンドを実行して有効期限を取得しますが、今回、日本語、英語、韓国語の3ヶ国語の環境で動作するように設定しています。
※2019/12/20追記:Windows10のVer1903からなぜか日付に?が入るようになったので、41行目に削除するコードを仕込みました。
Option Explicit
Dim WSH, FSO, wExec, PWE_File
Dim sCmd, UserHome, input, str_tmp, Expires_date, Lang, Expire, PWE_Path
Set WSH = CreateObject("WScript.Shell")
Set FSO = CreateObject("Scripting.FileSystemObject")
'Get User home directory
UserHome = WSH.ExpandEnvironmentStrings("%USERPROFILE%")
'Get Account informations of Logon user
sCmd = "net user %USERNAME% /domain"
Set wExec = WSH.Exec("%ComSpec% /c " & sCmd)
Do While Not wExec.StdOut.AtEndOfStream
input = wExec.StdOut.ReadLine
'Get "有効期間" colum, if japanese OS
If InStr(input, "有効期間") > 0 Then
str_tmp = input
Lang = "JP"
End If
'Get "Password expires" colum, if English OS
If InStr(input, "Password expires") > 0 Then
str_tmp = input
Lang = "EN"
End If
'Get "암호 만료 날짜" colum, if English OS
If InStr(input, "암호 만료 날짜") > 0 Then
str_tmp = input
Lang = "KR"
End If
Loop
'パスワード有効期間までの残り日数を計算
if InStr(str_tmp, "?") > 0 Then
str_tmp = Replace(str_tmp, "?", "")
End If
Expires_date = Split(str_tmp, " ")
If Lang = "JP" Then
Expire = Expires_date(19)
End If
If Lang = "EN" Then
Expire = Expires_date(14)
End If
If Lang = "KR" Then
Expire = Expires_date(23)
End If
'パスワード有効期間情報をファイル保存
PWE_Path = FSO.BuildPath(UserHome, "\PasswordExpire.txt")
Set PWE_File = FSO.CreateTextFile(PWE_Path, True)
PWE_File.Writeline(Expire)
PWE_File.Close()
Set wExec = Nothing
Set PWE_File = Nothing
Set FSO = Nothing
Set WSH = Nothing
3. PWMSG.vbs
ポップアップメッセージウィンドウを表示するプログラムです。こちらもユーザPCのタスクスケジューラで自動実行します。
2箇所ほどコメントアウトに変更箇所を明示しましたので、ご自由に変更してください。
- メッセージ通知を開始する日の設定(有効期限の何日前からメッセージを出すか)
- メッセージ本文
Option Explicit
Dim WSH, FSO, TextFile
Dim UserHome, PWNoticeDays, PWE_Path, str_tmp, Expires_date, sCmd, AttMsg
'【## 変更箇所 ##】パスワード有効期限メッセージ通知する日数
PWNoticeDays = 20
Set WSH = CreateObject("WScript.Shell")
Set FSO = CreateObject("Scripting.FileSystemObject")
'Get User home directory
UserHome = WSH.ExpandEnvironmentStrings("%USERPROFILE%")
'Get Password expires date from PasswordExpire.txt
PWE_Path = FSO.BuildPath(UserHome, "\PasswordExpire.txt")
On Error Resume Next
Set TextFile = FSO.OpenTextFile(PWE_Path,1)
If Err.Number = 0 Then
str_tmp = TextFile.ReadLine()
'パスワード有効期間までの残り日数を計算
Expires_date = DateDiff("d", Now, str_tmp)
'Expire_dateがxx日以内ならパスワード有効期限を再取得
If Expires_date < PWNoticeDays Then
sCmd = FSO.BuildPath(UserHome, "\PWGET.vbs")
WSH.Run "%ComSpec% /c " & sCmd, 0
Set TextFile = FSO.OpenTextFile(PWE_Path,1)
If Err.Number = 0 Then
str_tmp = TextFile.ReadLine()
Expires_date = DateDiff("d", Now, str_tmp)
End If
End If
'Expire_dateがxx日以内ならメッセージボックスを表示
If Expires_date < PWNoticeDays Then
'【## 変更箇所 ##】ポップアップメッセージ文
AttMsg = " Your password will expire in " & Expires_date & " days" & vbCrLf & vbCrLf _
& "Please change your password before it expires." & vbCrLf _
& " - IT Team -"
'メッセージボックス表示
MsgBox AttMsg, vbExclamation Or vbSystemModal, "Password Expiration"
End If
Else
sCmd = FSO.BuildPath(UserHome, "\PWGET.vbs")
WSH.Run "%ComSpec% /c " & sCmd, 0
Set TextFile = FSO.OpenTextFile(PWE_Path,1)
End If
TextFile.Close()
Set TextFile = Nothing
Set FSO = Nothing
Set WSH = Nothing
4. PWAlertML.vbs
パスワード有効期限が10日前になると送信&全ユーザのパスワード有効期限を一覧取得するプログラムです。
こちらはADサーバなどにタスクスケジューラー登録して、定期的に起動させます。
いくつかの<## 変更箇所 ##>をご自身の環境に合わせ変更してください。
【## 変更箇所 ##】の位置:4行目、60行目、77行目、139行目以降
Option Explicit
On Error Resume Next
'【## 変更箇所 ##】基本設定
'-----------------------------------------------------------------------------------------
'ドメイン名
Const Domain = "xxxx.co.jp"
'パスワード変更通知期限(この日数以下になるとユーザーへ通知します)
Const NotifyLimit = 10
'メール送信設定
'SMTPサーバ
Const SmtpServer = "mail.xxxx.co.jp"
'送信元メールアドレス(From)
Const MailFrom = "nortice@xxxx.co.jp"
'メール件名
Const MailSubJect = "Password expiration notice"
'既定のメールアドレス(ユーザーのメールアドレスが未登録の場合はこのアドレスへ通知)
Const DefaultTo = "nortice@xxxx.co.jp"
'SMTP認証情報
Const SmtpAuth = True
Const SmtpUser = "postmaster"
Const SmtpPassword = "password"
'除外ユーザー(セミコロン区切りでユーザー名を記載)
Const ExcludeUser = ""
'-----------------------------------------------------------------------------------------
Const ADS_UF_DONT_EXPIRE_PASSWD = &h10000
Dim cmdResult, strLogFile, strLine, strCmd, strUser, intUAC, strMailBody, i, j
Dim objShell, objFS, objFile, objUser
Dim arrUsers, intMaxPwdDays, dtmExpDay, intVal, MailTo
Set objShell = WScript.CreateObject("WScript.Shell")
Set objFS = WScript.CreateObject("Scripting.FileSystemObject")
objShell.CurrentDirectory = objFS.GetParentFolderName(WScript.ScriptFullName)
'全ユーザのパスワード有効期限一覧ファイルの初期化(このプログラムと同じディレクトリに保管)
strLogFile = "PWNotify.csv"
objFS.CreateTextFile strLogFile, True
Set objFile = objFS.OpenTextFile(strLogFile, 2)
objFile.WriteLine "User,E-Mail,PasswordLastChanged,ExpirationDate,Status"
objFile.Close
'Main Routine
'ユーザーのLDAPパス取得
arrUsers = Split(GetLdapPaths(Domain), ";")
'パスワード期限のチェック
For Each strUser In arrUsers
Set objUser = GetObject(strUser)
intUAC = objUser.Get("userAccountControl")
'【## 変更箇所 ##】ユーザが格納されているOUだけ処理&PW無期限ユーザは除外
If InStr(objUser.distinguishedName, "OU=Users") > 0 then
If intUAC And ADS_UF_DONT_EXPIRE_PASSWD Then
'無期限ユーザーの処理
strLine = objUser.sAMAccountName & "," & objUser.mail & "," & objUser.PasswordLastChanged & ",None,Permanent"
Else
intMaxPwdDays = GetMaxPwdDays(Domain)
dtmExpDay = DateAdd("d", intMaxPwdDays, objUser.PasswordLastChanged)
intVal = Int(intMaxPwdDays - (Now - objUser.PasswordLastChanged))
'期限切れユーザーへメール送信
If CheckExcludeUser(objUser.sAMAccountName, ExcludeUser) Then
'除外ユーザーの処理
strLine = objUser.sAMAccountName & "," & objUser.mail & "," & objUser.PasswordLastChanged & "," & dtmExpDay & ",Exclusion"
Else
If intVal <= NotifyLimit Then
'【## 変更箇所 ##】メール送信対象ユーザーの処理 & メール本文内容
strMailBody = "To: " & objUser.DisplayName & Chr(13) & Chr(10) & _
Chr(13) & Chr(10) & _
"Your password will expire in " & intVal & " day(s) at " & dtmExpDay & "(JST)." & Chr(13) & Chr(10) & _
Chr(13) &Chr(10) & _
"Please change your password before it expires." & Chr(13) & Chr(10) & _
Chr(13) & Chr(10) & _
Chr(13) & Chr(10)
strMailBody = strMailBody & _
"===== How to Change password =====" & Chr(13) & Chr(10) & _
"1. Connect to Corporate Network!" & Chr(13) & Chr(13) & Chr(10) & _
"2. Press Ctrl + Alt + Delete Key" & Chr(13) & Chr(13) & Chr(10) & _
"3. Choose [Password change(c)] menu and [xxxxx" & chr(92) & "<Username>] icon (not bird graphic icon) " & Chr(13) & Chr(13) & Chr(10) & _
"4. Type, Old Password & New Password twice" & Chr(13) & Chr(10) & _
" (alphabetical uppercase or lowercase, special character, numeric, 8characters and either 3types )"& Chr(13) & Chr(13) & Chr(10) & _
"5. Finish!" & Chr(13) & Chr(10) & _
Chr(13) &Chr(10) & _
Chr(13) &Chr(10) & _
"IT Team" & Chr(13) & Chr(10) & _
"nortice@xxxx.co.jp" & Chr(13) & Chr(10)
If Len(objUser.mail) = 0 Then
MailTo = DefaultTo
Else
MailTo = objUser.mail & "," & DefaultTo
End If
'メール送信実行
cmdResult = SendMsg(SmtpServer, SmtpUser, SmtpPassword, MailFrom, MailTo, MailSubject, strMailBody)
If cmdResult Then
strLine = objUser.sAMAccountName & "," & objUser.mail & "," & objUser.PasswordLastChanged & "," & dtmExpDay & ",Send Mail"
Else
strLine = objUser.sAMAccountName & "," & objUser.mail & "," & objUser.PasswordLastChanged & "," & dtmExpDay & ",Send Error"
End If
Else
'メール送信対象外ユーザーの処理
strLine = objUser.sAMAccountName & "," & objUser.mail & "," & objUser.PasswordLastChanged & "," & dtmExpDay & ",Not Expired"
End If
End If
End If
Set objFile = objFS.OpenTextFile(strLogFile, 8)
objFile.WriteLine strLine
objFile.Close
End If
Next
WScript.Quit(0)
'Sub Routine
Function GetLdapPaths(Fqdn)
Dim objConn, objCmd, objRecSet
Dim arrDn, strDn, strOu, strPathLine, n
arrDn = Split(Fqdn, ".")
For n = 0 To UBound(arrDn)
If n = 0 Then
strDn = "DC=" & arrDn(n)
Else
strDn = strDn & ",DC=" & arrDn(n)
End If
Next
'【## 変更箇所 ##】ユーザOUを指定 (最後はカンマをつける)
strOu = "OU=Users,"
Set objConn = CreateObject("ADODB.Connection")
Set objCmd = CreateObject("ADODB.Command")
objConn.Provider = "ADsDSOObject"
objConn.Open "Active Directory Provider"
objCmd.ActiveConnection = objConn
'接続プロパティ
objCmd.Properties("Page Size") = 1000
objCmd.Properties("Timeout") = 30
objCmd.Properties("Searchscope") = 5
objCmd.Properties("Cache Results") = False
objCmd.CommandText = "SELECT AdsPath FROM 'LDAP://" & strOu & strDn & "' WHERE objectCategory='user' ORDER BY pwdLastSet"
Set objRecSet = objCmd.Execute
objRecSet.MoveFirst
strPathLine = objRecSet.Fields("AdsPath").Value
objRecSet.MoveNext
Do Until objRecSet.EOF
strPathLine = strPathLine & ";" & objRecSet.Fields("AdsPath").Value
objRecSet.MoveNext
Loop
objConn.Close
Set objCmd = Nothing
GetLdapPaths = strPathLine
End Function
'パスワード有効日数(ドメインポリシー)
Function GetMaxPwdDays(Fqdn)
Dim objDom, objMaxPwdAge
Dim arrDn, strDn, maxPwdNano, maxPwdSecs, n
arrDn = Split(Fqdn, ".")
For n = 0 To UBound(arrDn)
If n = 0 Then
strDn = "DC=" & arrDn(n)
Else
strDn = strDn & ",DC=" & arrDn(n)
End If
Next
Set objDom = GetObject("LDAP://" & strDn)
Set objMaxPwdAge = objDom.Get("maxPwdAge")
GetMaxPwdDays = CCur((objMaxPwdAge.HighPart * 2 ^ 32) + objMaxPwdAge.LowPart) / CCur(-864000000000)
Set objDom = Nothing
End Function
'除外ユーザー判定
Function CheckExcludeUser(TargetUser,ExcludeList)
Dim arrExcludeUsers, tmpUser
CheckExcludeUser = False
arrExcludeUsers = Split(ExcludeList, ";")
For Each tmpUser In arrExcludeUsers
If LCase(tmpUser) = LCase(TargetUser) Then
CheckExcludeUser = True
Exit For
End If
Next
End Function
'メール送信
Function SendMsg(strSmtp, strSmtpUser, strSmtpPass, strFrom, strTo, strSubject, strBody)
Dim objMsg, strSchem, intPort
strSchem = "http://schemas.microsoft.com/cdo/configuration/"
intPort = 25
Set objMsg = CreateObject("CDO.Message")
'SMTP認証を使用する場合
If SmtpAuth Then
objMsg.Configuration.Fields.Item(strSchem & "sendusername") = strSmtpUser
objMsg.Configuration.Fields.Item(strSchem & "sendpassword") = strSmtpPass
objMsg.Configuration.Fields.Item(strSchem & "smtpauthenticate") = 1
'SMTP over SSLを使用する場合
'objMsg.Configuration.Fields.Item(strSchem & "smtpusessl") = True
End If
'アドレス情報定義
objMsg.From = strFrom
objMsg.To = strTo
'objMsg.Cc = strCc
'objMsg.Bcc = strBcc
'件名/本文定義/添付ファイル
objMsg.Subject = strSubject
objMsg.TextBody = strBody
objMsg.TextBodyPart.Charset = "UTF-8"
'添付ファイル
'objMsg.AddAttachment(strAttacheFile)
'SMTPサーバ定義
objMsg.Configuration.Fields.Item(strSchem & "sendusing") = 2
objMsg.Configuration.Fields.Item(strSchem & "smtpserver") = strSmtp
objMsg.Configuration.Fields.Item(strSchem & "smtpserverport") = intPort
'メール送信
objMsg.Configuration.Fields.Update
objMsg.Send
If Err.Number = 0 or Err.Number = -2147463155 Then
SendMsg = True
Else
SendMsg = False
End If
End Function
5. TaskSchedule-Reg.bat
上記4番のパスワード有効期限通知メールを送信するプログラムをタスクスケジューラーに登録するバッチです。
ADやファイルサーバなどで実行しスケジューラーを登録します。
実行間隔:月〜金の6時、9時、12時、15時、18時
REM パスワード通知メールを送信するプログラムのタスクスケジューラー登録バッチ
REM ADサーバ等のタスクスケジューラーで実行する。(タスクでユーザがログオフ時も実行にしている場合は、PWNotify.csvをFILEサーバに保管できないため。)
schtasks /create /tn PasswordExpireNotice06 /tr \\fs\UserPWchk\PWAlertML.vbs /ru SYSTEM /sc weekly /d mon,tue,wed,thu,fri /st 06:00 /F
schtasks /create /tn PasswordExpireNotice09 /tr \\fs\UserPWchk\PWAlertML.vbs /ru SYSTEM /sc weekly /d mon,tue,wed,thu,fri /st 09:00 /F
schtasks /create /tn PasswordExpireNotice12 /tr \\fs\UserPWchk\PWAlertML.vbs /ru SYSTEM /sc weekly /d mon,tue,wed,thu,fri /st 12:00 /F
schtasks /create /tn PasswordExpireNotice15 /tr \\fs\UserPWchk\PWAlertML.vbs /ru SYSTEM /sc weekly /d mon,tue,wed,thu,fri /st 15:00 /F
schtasks /create /tn PasswordExpireNotice18 /tr \\fs\UserPWchk\PWAlertML.vbs /ru SYSTEM /sc weekly /d mon,tue,wed,thu,fri /st 18:00 /F
4. まとめ
ポップアップ表示にメール送信とあまりにもしつこいやり方ですが、この方法でユーザのPW期限切れの問い合わせは無くなりました。
同じような境遇で困っている方がいらっしゃいましたら、こちらをご活用いただければと思います。
とは言えど、当日ギリギリまで変更しない人もおり、期限切れ前日までにヘルプデスクから案内メールをしていますけどね。
コメント
こんにちは。
会社でシステム管理を行っている渡邉と申します。
本サイトの管理人様と同じように、ユーザのPW更新切れのヘルプコールが増発しており、
何かいい案はないか調べたところ、こちらのサイトに辿り着きました。
こちらに公開されている内容を基に、自社用にカスタマイズを使用と思っております。
1点確認があり、メールをいたしました。
・2. PWGET.vbs がありますが、こちらのコードは公開されていないのでしょうか。
何卒よろしくお願いいたします。
ご覧いただきありがとうございます。2019年の夏頃からPW変更したのに有効期限通知が何度も表示されるということがあり、プログラムを変更しなければと思いブログから削除したままでした。
先ほど更新しましたので、ご確認ください。
こちらの方法でお役に立てれば幸いです。
[…] Active Directory ユーザーにパスワード更新期限をメール通知する ドメインユーザのパスワード有効期限更新通知を積極的に促す […]