太所有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
我想要完成的如下:
- 列表项
- 导入仅包含"samAccountName"的一列cvs。
- 使用随机生成的 20 个字符长的密码重置 CSV 中列出的帐户的密码
- 使用新密码向 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 抱怨它......
显然这是未经测试的!