我对新的 Microsoft API Graph 有一些问题。我在通用 Outlook 配置文件中有一个默认联系人文件夹。我已经已经将其推送给我的所有用户. 每个人都有一个通用文件夹里面有 530 个联系人。
现在的问题是更新它无需删除并重新启动,否则脚本将执行长达14个小时!
我见过API 图表增量但是我不知道如何使用它,我是 powershell 的“新手”,所以 URI 请求和所有这些典型的东西都有点困难,有人可以给我举个例子,说明如何使用我的默认文件夹更新文件夹吗?我会做剩下的。
我制作了这个 powershell 代码,其中引用了互联网上第一个脚本的一部分,归功于肖恩·麦卡维纽
<#
Details: Graph / PowerShell Script t populate user contacts based on CSV input,
Please fully read and test any scripts before running in your production environment!
.SYNOPSIS
Populates mail contacts into user mailboxes from a CSV
.DESCRIPTION
Creates a new mail contact for each entry in the input CSV in the target mailbox.
.PARAMETER Mailbox
User Principal Name of target mailbox
.PARAMETER CSVPath
Full path to the input CSV
.PARAMETER ClientID
Application (Client) ID of the App Registration
.PARAMETER ClientSecret
Client Secret from the App Registration
.PARAMETER TenantID
Directory (Tenant) ID of the Azure AD Tenant
.EXAMPLE
.\graph-PopulateContactsFromCSV.ps1 -Mailbox $mailbox -ClientSecret $clientSecret -ClientID $clientID -TenantID $tenantID -CSVPath $csv
.Notes
For similar scripts check out the links below
Blog: https://seanmcavinue.net
GitHub: https://github.com/smcavinue
Twitter: @Sean_McAvinue
Linkedin: https://www.linkedin.com/in/sean-mcavinue-4a058874/
#>
#>
#################################################
####################FONCTIONS####################
#################################################
function GetGraphToken {
# Azure AD OAuth Application Token for Graph API
# Get OAuth token for a AAD Application (returned as $token)
<#
.SYNOPSIS
This function gets and returns a Graph Token using the provided details
.PARAMETER clientSecret
-is the app registration client secret
.PARAMETER clientID
-is the app clientID
.PARAMETER tenantID
-is the directory ID of the tenancy
#>
Param(
[parameter(Mandatory = $true)]
[String]
$ClientSecret,
[parameter(Mandatory = $true)]
[String]
$ClientID,
[parameter(Mandatory = $true)]
[String]
$TenantID
)
# Construct URI
$uri = "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token"
# Construct Body
$body = @{
client_id = $clientId
scope = "https://graph.microsoft.com/.default"
client_secret = $clientSecret
grant_type = "client_credentials"
}
# Get OAuth 2.0 Token
$tokenRequest = Invoke-WebRequest -Method Post -Uri $uri -ContentType "application/x-www-form-urlencoded" -Body $body -UseBasicParsing
# Access Token
$token = ($tokenRequest.Content | ConvertFrom-Json).access_token
return $token
}
function ImportContact {
<#
.SYNOPSIS
Imports contact into specified user mailbox
.DESCRIPTION
This function accepts an AAD token, user account and contact object and imports the contact into the users mailbox
.PARAMETER Mailbox
User Principal Name of target mailbox
.PARAMETER Contact
Contact object for processing
.PARAMETER Token
Access Token
#>
Param(
[parameter(Mandatory = $true)]
[String]
$Token,
[parameter(Mandatory = $true)]
[String]
$Mailbox,
[parameter(Mandatory = $true)]
[String]
$folder,
[parameter(Mandatory = $true)]
[PSCustomObject]
$contact
)
write-host "contactcompanyname $($contact.companyname)"
write-host $contact
#Creation de l'objet "contact"
$ContactObject = @"
{
"assistantName": "$($contact.assistantName)",
"businessHomePage": "$($contact.businessHomePage)",
"businessPhones": [
"$($contact.businessPhones)"
],
"displayName": "$($contact.displayName)",
"emailAddresses": [
{
"address": "$($contact.emailaddress)",
"name": "$($contact.displayname)"
}
],
"givenName": "$($contact.givenname)",
"middleName": "$($contact.middleName)",
"nickName": "$($contact.nickName)",
"surname": "$($contact.surname)",
"title": "$($contact.title)"
}
"@
write-host "contact object: $contactobject"
#Creation du token d'autentification pour chaque boite mail contenue dans cible.txt
foreach($mail in $CSVPath){
$apiUri = "https://graph.microsoft.com/v1.0/users/$person/contactFolders/$folderid/contacts"
write-host $apiuri
$NewContact = (Invoke-RestMethod -Headers @{Authorization = "Bearer $($token)" } -ContentType 'application/json' -Body $contactobject -Uri $apiUri -Method Post)
return $NewContact
}
catch {
throw "Error creating contact $($contact.emailaddress) for $person $($_.Exception.Message)"
continue
}
}
##Import CSV
try {
$Contacts = import-csv $CSVPath -ErrorAction stop
}
catch {
throw "Erreur d'import CSV: $($_.Exception.Message)"
break
}
##Graph Token
Try {
$Token = GetGraphToken -ClientSecret $ClientSecret -ClientID $ClientID -TenantID $TenantID
}
catch {
throw "Erreur d'obtention de token"
break
}
##ProcessImport
foreach ($contact in $contacts) {
$NewContact = ImportContact -Mailbox $person -token $token -contact $contact -folder "Sync-Opac"
}
然后我的脚本需要很多“if”来定位错误并向同事展示。这对于第一次“大型”部署很有用。
<#
"----Installation --ET-- importation du module Pwsh Microsoft Graph pour executer le script---" -ForegroundColor red
"----------Processus LONG, patientez 10/15min------"
Install-module -Name Microsoft.Graph -verbose
Import-Module -Name Microsoft.Graph -verbose
#>
##Connexion###
$uri = "https://login.microsoftonline.com/4f232a97-8219-4450-9bec-410e6d0472d0/oauth2/v2.0/token"
#
$body = @{
client_id = $clientId
scope = "https://graph.microsoft.com/.default"
client_secret = $clientSecret
grant_type = "client_credentials"
}
#
$tokenRequest = Invoke-WebRequest -Method Post -Uri $uri -ContentType "application/x-www-form-urlencoded" -Body $body -UseBasicParsing -verbose
#
write-host "-------------Obtention & Conversion du token en cours...-------------" -ForegroundColor green
$token = ($tokenRequest.Content | ConvertFrom-Json).access_token
#
if ($? -eq $true){
write-host "-------------Token genere >> securisation en cours-------------" -ForegroundColor green
}
else{
write-host "-------------Erreur sur la recuperation du token-------------" -ForegroundColor red
break
}
$tokensecure = ConvertTo-SecureString -string $token -AsPlainText -Force -verbose
#
if ($? -eq $true){
write-host "-------------Token sécurisé obtenu, connexion...-------------" -ForegroundColor green
try{
Connect-MgGraph -NoWelcome -AccessToken $tokensecure
"---------------------------------------"
"------------#CONNEXION OK!#------------"
"---------------------------------------"
}catch{
write-host "-------------Connexion impossible avec le token specifie-------------" -ForegroundColor red
break
}
}
foreach ($person in $mailbox ){
Clear-Host
$folder = Get-MgUserContactFolder -UserID $person | ? {$_.DisplayName -eq"Sync-Opac"} -errorAction ignore
if($folder -eq $null){
##Connexion###
$uri = "https://login.microsoftonline.com/4f232a97-8219-4450-9bec-410e6d0472d0/oauth2/v2.0/token"
$body = @{
client_id = $clientId
scope = "https://graph.microsoft.com/.default"
client_secret = $clientSecret
grant_type = "client_credentials"
}
$tokenRequest = Invoke-WebRequest -Method Post -Uri $uri -ContentType "application/x-www-form-urlencoded" -Body $body -UseBasicParsing -verbose
#
write-host "-------------Obtention & Conversion du token en cours...-------------" -ForegroundColor green
$token = ($tokenRequest.Content | ConvertFrom-Json).access_token
#
if ($? -eq $true){
write-host "-------------Token genere >> securisation en cours-------------" -ForegroundColor green
}
else{
write-host "-------------Erreur sur la recuperation du token-------------" -ForegroundColor red
break
}
$tokensecure = ConvertTo-SecureString -string $token -AsPlainText -Force -verbose
#
if ($? -eq $true){
write-host "-------------Token sécurisé obtenu, connexion...-------------" -ForegroundColor green
try{
Connect-MgGraph -NoWelcome -AccessToken $tokensecure
"---------------------------------------"
"------------#CONNEXION OK!#------------"
"---------------------------------------"
Clear-Host
}catch{
write-host "-------------Connexion impossible avec le token specifie-------------" -ForegroundColor red
break
}
}
#Fin de connexion
########################################Creation contact##################
New-MgUserContactFolder -UserId $person -DisplayName Sync-Opac
start-sleep 5
$folder = Get-MgUserContactFolder -UserID $person | ? {$_.DisplayName -eq"Sync-Opac"}
$folderid = $folder.Id
./pwsh_graph_contacts.ps1
write-host "----------Contact importé && Dossier Contacts créé pour $person------------" -ForegroundColor Green
Clear-Host
continue
#si compte deja peuplé alors connexion et suppression
}else{
##Connexion###
$uri = "https://login.microsoftonline.com/4f232a97-8219-4450-9bec-410e6d0472d0/oauth2/v2.0/token"
#
$body = @{
client_id = $clientId
scope = "https://graph.microsoft.com/.default"
client_secret = $clientSecret
grant_type = "client_credentials"
}
#
$tokenRequest = Invoke-WebRequest -Method Post -Uri $uri -ContentType "application/x-www-form-urlencoded" -Body $body -UseBasicParsing -verbose
#
write-host "-------------Obtention & Conversion du token en cours...-------------" -ForegroundColor green
$token = ($tokenRequest.Content | ConvertFrom-Json).access_token
#
if ($? -eq $true){
write-host "-------------Token genere >> securisation en cours-------------" -ForegroundColor green
}
else{
write-host "-------------Erreur sur la recuperation du token-------------" -ForegroundColor red
break
}
$tokensecure = ConvertTo-SecureString -string $token -AsPlainText -Force -verbose
#
if ($? -eq $true){
write-host "-------------Token sécurisé obtenu, connexion...-------------" -ForegroundColor green
try{
Connect-MgGraph -NoWelcome -AccessToken $tokensecure
"---------------------------------------"
"------------#CONNEXION OK!#------------"
"---------------------------------------"
Clear-Host
}catch{
write-host "-------------Connexion impossible avec le token specifie-------------" -ForegroundColor red
break
}
}
#Fin de connexion
########################################Creation contact##################
.\suppression_graph_contacts.ps1
Clear-Host
start-sleep 10
New-MgUserContactFolder -UserId $person -DisplayName Sync-Opac
$folder = Get-MgUserContactFolder -UserID $person | ? {$_.DisplayName -eq"Sync-Opac"}
$folderid = $folder.Id
./pwsh_graph_contacts.ps1
write-host "----------Contacts importés pour $person-------------------" -ForegroundColor Green
continue
}
}
我清楚地了解我的部分,但实际上我只使用了第一个部分的 50%。
答案1
您可以使用 HTTP 请求,这是调用 Microsoft Graph API 的直接方式,可让您更灵活地控制请求和响应。您可以使用 GET 方法获取联系人文件夹的增量更改,并使用 PATCH 方法更新联系人文件夹的属性,例如:
// Get the incremental changes of the contact folders
GET /me/contactFolders/delta
// Iterate through the delta collection
for each deltaFolder in response
{
// Check if it is your default folder
if (deltaFolder.displayName == "Default Folder")
{
// Modify the folder's properties
PATCH /me/contactFolders/{id}
Content-type: application/json
{
"displayName": "Updated Folder"
}
}
}
答案2
从脚本中删除New-MgUserContactFolder
命令。否则,它应该可以按原样运行,将您的 CSV 导入每个人的个人联系人。它不会覆盖整个文件夹或删除不在 CSV 中的联系人。
在单个用户上进行测试。
如果你想减少所需时间,你可以过滤掉已经从 CSV 中添加的联系人,或者使用获取 MgUserContact查询现有联系人并仅根据需要进行更新。
一般来说,你应该只对那些更新频率不高的重要联系人(如 IT 服务台、人力资源和其他内部服务)执行此操作,因为更新速度太慢。如果列表太大,可以考虑使用中央共享联系人文件夹。