通过Powershell更新AD密码



太所有Powershell专家:我需要一些帮助来弄清楚为什么它工作不正确。我的意思是错误的,CSV密码中的帐户使用随机密码进行更新,并且电子邮件会发送给用户,但我不知道为什么他们获得相同的密码,并且AD中的每个帐户都被解决了。请参阅电子邮件输出:

第一个用户电子邮件:

Hello Guest DefaultAccount user1, user2, user3, user4 test John Doe, 
Your AD Account user1, password has been updated to e,wQlsGfBE;J'4  

第二个用户电子邮件

Hello Guest DefaultAccount user1, user2, user3, user4 test John Doe, 
Your AD Account jdoe, password has been updated to e,wQlsGfBE;J'4  

我想要完成的如下:

  1. 列表项
  2. 导入仅包含"samAccountName"的一列cvs。
  3. 使用随机生成的 20 个字符长的密码重置 CSV 中列出的帐户的密码
  4. 使用新密码向 AD 帐户关联的电子邮件地址发送电子邮件。(我这样做是因为他们的电子邮件地址与他们的AD帐户不同(,所以他们能够收到他们的电子邮件。

Import-Module ActiveDirectory
# Import AD user objects and store in users variables 
$users = Get-ADUser -Filter *  -Properties Name, EmailAddress,SamAccountName | Select SamAccountName,Name,EmailAddress

$Name = $users.Name
$SamAccountName = $users.SamAccountName
$EmailAddress = $users.EmailAddress
#Date
$date = (Get-Date -Format F) 
#Generate a random password and store in newpwd 
$newpwd = -join (33..126|%{[char]$_}|Get-Random -Count 20)
$newPassword = ConvertTo-SecureString -AsPlainText "$newpwd" -Force
# Import users from CSV
Import-Csv "C:Userlist.csv" | ForEach-Object {
$samAccountName= $_."samAccountName"
#Proceed with password reset
Set-ADAccountPassword -Identity $samAccountName -NewPassword $newPassword -Reset
Set-AdUser -Identity $samAccountName -ChangePasswordAtLogon $true
#Server configuration 
$smtpServer =""
$SmtpPort = ""
# sending option
$from = "it-operation@example.com"
$to = $EmailAddress 
$subject  ="AD Password updated - " + $date
$priority = "Normal"
$from = ""
$body = @"
Hello $name, <br> 
Your AD Account $samAccountName, password has been updated to $newpwd
"@
try {
# Send the report email
Send-MailMessage -To $to -Subject $subject -BodyAsHtml -body $body -SmtpServer $smtpServer -Port $SmtpPort -From $From -Priority $priority  
}
catch{
write-warning "error in sending. $_"
}  # End User Processing

}

帐户密码正在更新,但无法发送emai

当你执行$Name = $users.Name时,$Name变量会得到一个数组,其中包含CSV中的所有用户名。

删除该行,改为在ForEach-Object循环中设置变量:

# Import users from CSV
$UserList = Import-Csv "C:Userlist.csv" | ForEach-Object {
$samAccountName= $_.samAccountName
$name = $_.Name
# then the rest of your code
}

注意:

  • SmtpPort 采用整数,而不是字符串
  • 发件人不能为空字符串

P.S. 尝试做一些正确的代码缩进,这样更容易看到代码块(如 ForEach-Object(的开始和结束位置(


您的代码已修订:

Import-Module ActiveDirectory
# Import AD user objects and store in users variables 
$users = Get-ADUser -Filter *  -Properties Name, EmailAddress,SamAccountName | Select SamAccountName,Name,EmailAddress
#Date
$date = (Get-Date -Format F) 
# Import users from CSV
Import-Csv "C:Userlist.csv" | ForEach-Object {
# read this from the CSV
$samAccountName= $_.samAccountName
# get the user object from the $users array
$user = $users | Where-Object { $_.SamAccountName -eq $samAccountName }
$name = $user.Name
$emailAddress = $user.EmailAddress
#Generate a random password and store in newpwd 
$newpwd = -join (33..126|%{[char]$_}|Get-Random -Count 14)
$newPassword = ConvertTo-SecureString -AsPlainText "$newpwd" -Force
$body = @"
Hello $name, <br> 
Your AD Account $samAccountName, password has been updated to $newpwd
"@
#Proceed with password reset
Set-ADAccountPassword -Identity $samAccountName -NewPassword $newPassword -Reset
Set-AdUser -Identity $samAccountName -ChangePasswordAtLogon $true
#Server configuration 
$mailParams = @{
SmtpServer = "YourSMTPServer"
Port = 25  # <-- an integer value
# sending option
From = "it-operation@example.com"
To = $user.EmailAddress 
Subject  ="AD Password updated - " + $date
Priority = "Normal"
Body = $body
BodyAsHtml = $true
}
try {
# Send the report email
Send-MailMessage @mailParams -ErrorAction Stop
}
catch{
write-warning "error in sending. $_"
}  # End User Processing
}

在这里,我只是建立在@Theo的答案之上。

Import-Module ActiveDirectory
# Import AD user objects and store in users variables 
$Users = @{} 
Get-ADUser -Filter *  -Properties Name,EmailAddress,SamAccountName | Select-Object SamAccountName,Name,EmailAddress |
ForEach-Object{ $Users.Add( $_.samAccountName, $_ ) }
#Date
$Date = (Get-Date -Format F) 
# Generate a random password and store in newPassword 
$newPassword = -join ( 33..126 | ForEach-Object{ [char]$_ }| Get-Random -Count 20 )
$newPassword = ConvertTo-SecureString -AsPlainText "$newPassword" -Force
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# Move to the loop if you want each user's pwd to be different!!!
# Put this here so you can indent the loop easier...
$BaseBody = 
@"
Hello %NAME%, <br> 
Your AD Account %SAMACCOUNTNAME%, password has been updated to %NEWPASSWORD%
"@
# Server configuration & recipien configurations...:
$MailParams = @{
$smtpServer = "YorServer.example.com" #MAKE SURE YOU CHANGE THIS
$SmtpPort   = 25
$from       = "it-operation@example.com"
$To         = ""
$subject    ="AD Password updated - " + $date
$Body       = ""
}
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# Removed -Priority if it's alwasy going to be normal you don't need it.
# Import users from CSV
Import-Csv "C:Userlist.csv" | 
ForEach-Object {
$samAccountName = $_."samAccountName"
# Proceed with password reset
Set-ADAccountPassword -Identity $samAccountName -NewPassword $newPassword -Reset
Set-ADUser -Identity $samAccountName -ChangePasswordAtLogon $true

# Get the Name & Email address from the $Users Hash...:
$EmailAddress = $Users[$samAccountName].EmailAddress
$Name         = $Users[$samAccountName].Name
# Reset the To & Body values
$MailParams['To']   = $EmailAddress
$MailParams['Body'] = $BaseBody.Replace('%NAME%', $Name).Replace('%SAMACCOUNTNAME%', $samAccountName).Replace('%NEWPASSWORD%', $newPassword)    
try { # Send the report email
Send-MailMessage @MailParams -ErrorAction Stop
}
catch{
write-warning "Error in sending : $_"
}
} # End User Processing
  • 使用哈希表来存储 AD 用户对象,这样就不必在每次循环迭代时重新执行 Where{}。 根据用户数量,这可能会快得多。 当在 2 个来源之间关联数据时,我倾向于哈希表。
  • 已将$Body变量移出循环。 这里的字符串不喜欢缩进,通过将其移出,我们不必干扰循环缩进;提高可读性。 然后在循环中,我们可以通过执行一些字符串替换来获取实际的主体。
  • 我还将$MailParams参数哈希放在循环之外。然后在循环中,我重置了 2 个不同的键。 吹毛求疵,但我宁愿不在每个循环迭代中声明哈希。
  • $Reused$newPassword变量,而不是让多余的$newpdw变量闲置。
  • 扩展了别名,只是因为 PSScriptAnalyzer 抱怨它......

显然这是未经测试的!

最新更新