Exchange Online : connexion, boîtes partagées et délégations en PowerShell
Introduction
Faitza_Exchange.ps1 regroupe les fonctions PowerShell pour administrer
Exchange Online : audit des permissions, gestion des boîtes partagées, conversions et
délégations. La connexion est gérée par Connect-Faitza_Modul_ExchangeOnline
via le module ExchangeOnlineManagement et Azure CLI — les cmdlets Exchange
ne sont pas disponibles via REST Graph, d'où l'utilisation du module PowerShell dédié.
- Module
ExchangeOnlineManagementinstallé :Install-Module ExchangeOnlineManagement - Azure CLI connecté avec un compte ayant les droits Exchange Admin
- Appeler
Connect-Faitza_Modul_ExchangeOnlineavant toute autre fonction
Connect — Se connecter à Exchange Online
Établit la connexion à Exchange Online via un token obtenu depuis Azure CLI
(az account get-access-token). Détecte automatiquement si une session
est déjà active pour éviter les doubles connexions. Le switch -deco
déconnecte proprement la session en cours.
function Connect-Faitza_Modul_ExchangeOnline {
[CmdletBinding()]
param(
[string]$organization = "faitza.onmicrosoft.com",
[switch]$deco
)
Write-Host "$($PSStyle.Background.Red)>>> Connect-Faitza_Modul_ExchangeOnline <<<$($PSStyle.Reset)"
try {
if ($deco) {
Disconnect-ExchangeOnline -Confirm:$false -ErrorAction SilentlyContinue | Out-Null
Write-Host "Déconnexion Exchange effectuée."
return
}
$oldErrPref = $ErrorActionPreference
$ErrorActionPreference = 'SilentlyContinue'
try { Import-Module ExchangeOnlineManagement -ErrorAction SilentlyContinue } catch {}
$ErrorActionPreference = $oldErrPref
if (Get-ConnectionInformation -ErrorAction SilentlyContinue) {
Write-Host "Déjà connecté à Exchange Online."
return "Connect : OK"
}
$Token = az account get-access-token --resource "https://outlook.office365.com/" --query accessToken -o tsv
if ([string]::IsNullOrWhiteSpace($Token)) { throw "Le jeton retourné par Azure CLI est vide." }
Connect-ExchangeOnline -Organization $organization -AccessToken $Token -ShowBanner:$false -ErrorAction Stop
$domain = Get-AcceptedDomain | Where-Object { $_.Default -eq $true }
Write-Host "$($PSStyle.Foreground.BrightGreen)Connexion Exchange réussie : $($domain.Name)$($PSStyle.Reset)"
return "Connect : $($domain.Name)"
} catch {
throw "Erreur connexion ExchangeOnline : $_"
} finally {
Write-Host "$($PSStyle.Background.Red)<<< Connect-Faitza_Modul_ExchangeOnline >>>$($PSStyle.Reset)"
}
}
# Connexion (tenant par défaut)
Connect-Faitza_Modul_ExchangeOnline
# Connexion sur un autre tenant
Connect-Faitza_Modul_ExchangeOnline -organization "contoso.onmicrosoft.com"
# Déconnexion propre
Connect-Faitza_Modul_ExchangeOnline -deco
Right — Permissions d'une boîte aux lettres
Consolide toutes les permissions d'une boîte aux lettres en un seul objet : droits
SendOnBehalfTo, FullAccess, SendAs, accès
calendrier et transferts automatiques (forwarding). Conçue pour être appelée en boucle
sur un inventaire complet — les paramètres -Cache,
-MailboxPermIndex et -RecipientPermIndex sont des indexes
pré-construits pour éviter une requête API par boîte.
function Get-Faitza_Exchange_Right {
[CmdletBinding()]
param (
$user_mail,
$Cache,
$MailboxPermIndex,
$RecipientPermIndex
)
try {
Write-Host "$($PSStyle.Background.Red)>>> Get-Faitza_Exchange_Right <<<$($PSStyle.Reset)"
if (-not $user_mail) { throw "Il manque l'utilisateur Exchange (-user_mail)" }
if (-not $Cache) { throw "Il manque le cache destinataires (-Cache)" }
if (-not $MailboxPermIndex) { throw "Il manque l'index MailboxPermission (-MailboxPermIndex)" }
if (-not $RecipientPermIndex) { throw "Il manque l'index RecipientPermission (-RecipientPermIndex)" }
$list_retour = [System.Collections.Generic.List[PSObject]]::new()
$identity = $user_mail.PrimarySmtpAddress
$identityKey = $identity.ToString().ToLower()
function Resolve-RecipientCache {
param ($id)
if (-not $id) { return $null }
$cleanId = $id.ToString().ToLower().Trim()
if ($Cache.ContainsKey($cleanId)) { return $Cache[$cleanId] }
return $null
}
$user_mail.GrantSendOnBehalfTo | ForEach-Object {
$delegant_user = $_
$delegant = Resolve-RecipientCache $delegant_user
if ($delegant) { $actif = $true } else { $delegant = $delegant_user; $actif = $false }
if ($delegant -and ($delegant -ne $identity)) {
$list_retour.Add([pscustomobject]@{
User = $identity
Permission = "SendOnBehalfTo"
Delegant = $delegant
Actif = $actif
Type = $user_mail.RecipientTypeDetails
})
}
}
if ($MailboxPermIndex.ContainsKey($identityKey)) {
$MailboxPermIndex[$identityKey] | ForEach-Object {
$delegant_user = $_.User
$delegant = Resolve-RecipientCache $delegant_user
if ($delegant) { $actif = $true } else { $delegant = $delegant_user; $actif = $false }
if ($delegant -and ($delegant -ne $identity)) {
$list_retour.Add([pscustomobject]@{
User = $identity
Permission = $_.AccessRights[0]
Delegant = $delegant
Actif = $actif
Type = $user_mail.RecipientTypeDetails
})
}
}
}
if ($RecipientPermIndex.ContainsKey($identityKey)) {
$RecipientPermIndex[$identityKey] | ForEach-Object {
$delegant_user = $_.Trustee
$delegant = Resolve-RecipientCache $delegant_user
if ($delegant) { $actif = $true } else { $delegant = $delegant_user; $actif = $false }
if ($delegant -and ($delegant -ne $identity)) {
$list_retour.Add([pscustomobject]@{
User = $identity
Permission = $_.AccessRights[0]
Delegant = $delegant
Actif = $actif
Type = $user_mail.RecipientTypeDetails
})
}
}
}
if ($user_mail.RecipientTypeDetails -eq "UserMailbox") {
foreach ($folder in @("Calendrier", "Calendar")) {
Get-EXOMailboxFolderPermission "$($identity):\$folder" -ErrorAction SilentlyContinue |
Where-Object { $_.User.DisplayName -notmatch $user_mail.DisplayName -and $_.User.DisplayName -notmatch "Default|Anonymous" } |
ForEach-Object {
$delegant_user = $_.User.DisplayName
$delegant = Resolve-RecipientCache $delegant_user
if ($delegant) { $actif = $true } else { $delegant = $delegant_user; $actif = $false }
if ($delegant -and ($delegant -ne $identity)) {
$list_retour.Add([pscustomobject]@{
User = $identity
Permission = $_.AccessRights[0]
Delegant = $delegant
Actif = $actif
Type = "Calendrier $($user_mail.RecipientTypeDetails)"
})
}
}
}
}
if ($user_mail.ForwardingSmtpAddress -or $user_mail.ForwardingAddress) {
$delegant = $null
if ($user_mail.ForwardingAddress) { $delegant = Resolve-RecipientCache $user_mail.ForwardingAddress }
if (-not $delegant -and $user_mail.ForwardingSmtpAddress) { $delegant = ($user_mail.ForwardingSmtpAddress -split "smtp:", 2, "IgnoreCase")[1] }
if (-not $delegant) { $delegant = $user_mail.ForwardingAddress }
$list_retour.Add([pscustomobject]@{
User = $identity
Permission = "Forwarding"
Delegant = $delegant
Actif = $true
Type = $user_mail.RecipientTypeDetails
})
}
return $list_retour
} catch {
throw "Erreur Get-Faitza_Exchange_Right : $_"
} finally {
Write-Host "$($PSStyle.Background.Red)<<< Get-Faitza_Exchange_Right >>>$($PSStyle.Reset)"
}
}
# Construction des indexes (une seule fois pour tout le tenant)
$allMailboxes = Get-EXOMailbox -ResultSize Unlimited -Properties GrantSendOnBehalfTo, ForwardingAddress, ForwardingSmtpAddress, RecipientTypeDetails
$Cache = @{}
foreach ($m in $allMailboxes) { $Cache[$m.PrimarySmtpAddress.ToLower()] = $m.PrimarySmtpAddress }
$MailboxPermIndex = @{}
Get-MailboxPermission -ResultSize Unlimited | Where-Object { $_.AccessRights -contains "FullAccess" -and -not $_.IsInherited } |
ForEach-Object { $key = $_.Identity.ToLower(); if (-not $MailboxPermIndex[$key]) { $MailboxPermIndex[$key] = @() }; $MailboxPermIndex[$key] += $_ }
$RecipientPermIndex = @{}
Get-RecipientPermission -ResultSize Unlimited | Where-Object { -not $_.IsInherited } |
ForEach-Object { $key = $_.Identity.ToLower(); if (-not $RecipientPermIndex[$key]) { $RecipientPermIndex[$key] = @() }; $RecipientPermIndex[$key] += $_ }
# Audit de toutes les permissions du tenant
$rapport = foreach ($mbx in $allMailboxes) {
Get-Faitza_Exchange_Right -user_mail $mbx -Cache $Cache -MailboxPermIndex $MailboxPermIndex -RecipientPermIndex $RecipientPermIndex
}
$rapport | Format-Table User, Permission, Delegant, Actif, Type -AutoSize
Convert — Convertir en boîte partagée
Convertit une boîte aux lettres utilisateur en boîte partagée via
Set-Mailbox -Type Shared. Utile lors du départ d'un employé pour
conserver l'accès à son historique mail sans licence active.
function Convert-Faitza_Exchange_user_shearmb {
[CmdletBinding()]
param ([string]$UserEmail)
try {
Write-Host "$($PSStyle.Background.Red)>>> Convert-Faitza_Exchange_user_shearmb <<<$($PSStyle.Reset)"
if ([string]::IsNullOrWhiteSpace($UserEmail)) { throw "Il manque l'email de l'utilisateur -UserEmail" }
Write-Host "Email : $UserEmail"
Write-Host "Conversion de $UserEmail en Shared Mailbox"
Set-Mailbox -Identity $UserEmail -Type Shared -ErrorAction Stop
return $true
} catch {
throw "Erreur Convert-Faitza_Exchange_user_shearmb : $_"
} finally {
Write-Host "$($PSStyle.Background.Red)<<< Convert-Faitza_Exchange_user_shearmb >>>$($PSStyle.Reset)"
}
}
# Convertir la boîte d'un utilisateur parti
Convert-Faitza_Exchange_user_shearmb -UserEmail "[email protected]"
MailboxDelegation — Ajouter une délégation
Accorde simultanément les droits FullAccess (avec AutoMapping) et
SendAs à un ou plusieurs utilisateurs sur une boîte partagée existante.
Gère plusieurs délégataires en une seule commande et retourne les erreurs individuelles
sans interrompre les autres attributions.
function Add-Faitza_Exchange_MailboxDelegation {
[CmdletBinding()]
param (
$SharedMailboxEmail,
[string[]]$Delegates
)
try {
Write-Host "$($PSStyle.Background.Red)>>> Add-Faitza_Exchange_MailboxDelegation <<<$($PSStyle.Reset)"
if ([string]::IsNullOrWhiteSpace($SharedMailboxEmail)) { throw "Aucune boîte partagée cible définie (-SharedMailboxEmail)" }
if (-not $Delegates -or $Delegates.Count -eq 0) { throw "Aucun délégataire à configurer (-Delegates)" }
$erreur = @()
foreach ($Delegate in $Delegates) {
if ([string]::IsNullOrWhiteSpace($Delegate)) { continue }
$CleanDelegate = $Delegate.Trim()
Write-Host "Configuration des droits pour : $CleanDelegate"
try {
Add-MailboxPermission -Identity $SharedMailboxEmail -User $CleanDelegate -AccessRights FullAccess -InheritanceType All -AutoMapping $true -ErrorAction Stop
Add-RecipientPermission -Identity $SharedMailboxEmail -Trustee $CleanDelegate -AccessRights SendAs -Confirm:$false -ErrorAction Stop
Write-Host "Délégations FullAccess + SendAs accordées avec succès à $CleanDelegate"
} catch {
$erreur += "Erreur lors de l'attribution des droits pour $CleanDelegate : $($_.Exception.Message)"
}
}
if ($erreur) { throw ($erreur -join "`n") }
return $true
} catch {
throw "Erreur Add-Faitza_Exchange_MailboxDelegation : $_"
} finally {
Write-Host "$($PSStyle.Background.Red)<<< Add-Faitza_Exchange_MailboxDelegation >>>$($PSStyle.Reset)"
}
}
# Ajouter un délégataire
Add-Faitza_Exchange_MailboxDelegation `
-SharedMailboxEmail "[email protected]" `
-Delegates @("[email protected]")
# Plusieurs délégataires en une commande
Add-Faitza_Exchange_MailboxDelegation `
-SharedMailboxEmail "[email protected]" `
-Delegates @("[email protected]", "[email protected]")
// Commentaires
Aucun commentaire pour l'instant.