请求修改PowerShell脚本:向Azure AD组所有者发送带成员列表的邮件
问题需求
我正在编写PowerShell脚本,用于收集Azure AD组所有所有者的邮箱地址,以组名为文件名导出为TXT/CSV文件(比如GroupName.csv里包含Owner1@domain.com、Owner2@domain.com等),用于安全审计。
现在需要实现:读取指定文件夹中的组所有者CSV文件,给每个组所有者发送邮件,同时附加对应组的成员列表文件(同样以组名命名,存在另一个指定文件夹),让所有者验证组成员是否正确。
我对PowerShell了解基础,已完成导出所有者的脚本,也找到一份邮件发送脚本,请求帮忙修改适配需求。注:公司使用Outlook。
现有脚本
导出Azure AD组所有者脚本(可正常运行,可按需修改)
# 这是我目前写的导出组所有者列表并按组名保存的脚本,运行正常,可按需修改 $cred = Get-Credential Connect-AzureAD -Credential $cred $groups = Get-AzureADGroup -All $true ForEach($group in $groups) { $resultsarray = @() $owners = Get-AzureADGroupOwner -ObjectId $group.ObjectId -All $true ForEach($owner in $owners) { $resultsarray += [PSCustomObject] @{" " = $owner.UserPrincipalName} $gName = $group.DisplayName[IO.Path]::GetinvalidFileNameChars() | ForEach - Object{$gName = $gName.Replace( $_, "_")}[IO.Path] ::GetinvalidFileNameChars() | ForEach - Object{$gName = $gName.Replace( '[', "_")}[IO.Path] ::GetinvalidFileNameChars() | ForEach - Object{$gName = $gName.Replace(']', "_")} #$resultsarray | Export-CSV -Path D :\\Script\\AzureADOwners$gName.csv -Delimiter ',' -NoTypeInformation $resultsarray | Out-File -Filepath D:\\Script\\AzureADOwners$gName.txt } }
网上找到的邮件发送脚本
# 这是我在网上找的脚本,所有者CSV文件路径是D:\\Script\\AzureADOwners\\,文件名为GroupName.csv Import-Module ImportExcel $csv_files = Get-ChildItem -Path 'D:\\Script\\AzureADOwners' -Filter '*.csv' foreach ($csv_file in $csv_files) { $data = Import-Csv -Path $csv_file.FullName foreach ($row in $data) { $email_address = $row.Column1 $attachment = D:\Script\AzureADMembers\$csv_file.csv Send-MailMessage -To $email_address -Subject 'Test Email' -Body 'This is a test email.' -Attachments $attachment -SmtpServer 'smtp.gmail.com' -Credential(Get-Credential) } }
修改后的解决方案
1. 修正后的导出组所有者脚本
修复原脚本语法错误,优化文件名清理逻辑,优先导出为CSV(方便后续邮件脚本读取):
# 导出Azure AD组所有者到CSV文件 $cred = Get-Credential Connect-AzureAD -Credential $cred # 定义存储所有者文件的路径 $ownerFolder = "D:\Script\AzureADOwners" # 确保文件夹存在,不存在则创建 if (-not (Test-Path $ownerFolder)) { New-Item -Path $ownerFolder -ItemType Directory | Out-Null } $groups = Get-AzureADGroup -All $true foreach ($group in $groups) { $owners = Get-AzureADGroupOwner -ObjectId $group.ObjectId -All $true if ($owners) { # 清理组名中的非法文件名字符 $cleanGroupName = $group.DisplayName [IO.Path]::GetInvalidFileNameChars() | ForEach-Object { $cleanGroupName = $cleanGroupName.Replace($_, "_") } # 给导出的列设置明确名称,避免读取时出错 $ownerList = $owners | Select-Object @{Name="OwnerEmail"; Expression={$_.UserPrincipalName}} # 导出到CSV文件 $exportPath = Join-Path $ownerFolder "$cleanGroupName.csv" $ownerList | Export-Csv -Path $exportPath -NoTypeInformation -Encoding UTF8 Write-Host "已导出组 [$($group.DisplayName)] 的所有者到文件: $exportPath" } else { Write-Host "组 [$($group.DisplayName)] 没有所有者,跳过导出" } }
2. 适配Outlook的邮件发送脚本
改用Outlook COM对象发送邮件,无需配置SMTP服务器,适配企业Outlook环境:
# 读取组所有者CSV并发送带成员列表附件的邮件(基于Outlook) # 定义文件路径 $ownerFolder = "D:\Script\AzureADOwners" $memberFolder = "D:\Script\AzureADMembers" # 检查文件夹是否存在 if (-not (Test-Path $ownerFolder)) { Write-Error "所有者文件文件夹 [$ownerFolder] 不存在,脚本终止" exit 1 } if (-not (Test-Path $memberFolder)) { Write-Error "成员列表文件夹 [$memberFolder] 不存在,脚本终止" exit 1 } # 获取所有所有者CSV文件 $ownerCsvFiles = Get-ChildItem -Path $ownerFolder -Filter "*.csv" # 初始化Outlook应用 $outlook = New-Object -ComObject Outlook.Application foreach ($csvFile in $ownerCsvFiles) { # 获取组名(去掉文件后缀) $groupName = $csvFile.BaseName # 对应成员列表文件路径 $memberFile = Join-Path $memberFolder "$groupName.csv" if (-not (Test-Path $memberFile)) { Write-Warning "组 [$groupName] 的成员列表文件不存在,跳过发送" continue } # 读取所有者邮箱列表 $owners = Import-Csv -Path $csvFile.FullName foreach ($owner in $owners) { $ownerEmail = $owner.OwnerEmail if (-not $ownerEmail) { Write-Warning "文件 [$($csvFile.Name)] 中存在空邮箱地址,跳过该条目" continue } # 创建邮件 $mail = $outlook.CreateItem(0) $mail.To = $ownerEmail $mail.Subject = "请验证Azure AD组 [$groupName] 的成员列表" $mail.Body = @" 您好, 请查看附件中的Azure AD组「$groupName」成员列表,确认所有成员归属正确。 如有异常,请及时联系IT部门。 谢谢! "@ # 添加成员列表附件 $mail.Attachments.Add($memberFile) # 发送邮件(如需保存草稿,替换为 $mail.Save()) $mail.Send() Write-Host "已向 [$ownerEmail] 发送组 [$groupName] 的验证邮件" } } # 释放Outlook COM对象,避免内存泄漏 [System.Runtime.Interopservices.Marshal]::ReleaseComObject($outlook) | Out-Null Remove-Variable outlook
注意事项
- 运行导出脚本前需安装AzureAD模块:
Install-Module -Name AzureAD -Force - 邮件脚本需在已安装Outlook且当前用户已登录Outlook的机器上运行
- 需自行补充导出组成员列表的脚本(逻辑与导出所有者类似,使用
Get-AzureADGroupMember获取成员并导出为同名CSV) - 确保文件夹路径正确,且当前用户对文件夹有读写权限
内容的提问来源于stack exchange,提问作者Raybanz_UK
相关产品推荐
相关产品推荐

