Exchange et Powershell : nettoyage des références caduques dans les ACL

Les ACL des boîtes aux lettres Exchange ne sont pas en synchronisation permanente avec l'ActiveDirectory, ce qui signifie que si l'on ajoute par exemple sur la boîte scranton@dundermifflin.inc l'utilisateur DUNDERMIFFLIN\jhalpert et que ce compte vient à disparaître de l'ActiveDirectory, alors cette boîte aura dans ses ACL une référence de type "S-1-5-***". Il se produit par exemple la même chose côté Windows si un compte de domaine est ajouté dans les profils locaux du système et que ce compte de domaine vient à disparaître.

Afin de faire un peu de nettoyage sur des boîtes aux lettres partagées, j'ai donc développé un script pour l'Exchange Management Shell (EMS) permettant de lister toutes les références à ces comptes qui n'existent plus. Cette liste est ensuite exportée au format CSV, ce qui permet ensuite de passer ce fichier si besoin dans un script supprimant ces références.

$Output = @()
$mailboxes = Get-Mailbox -ResultSize Unlimited
foreach($mailbox in $mailboxes){
	$acls = Get-MailboxPermission $mailbox | where-object { $_.User -like "S-1-5-21*" -and $_.IsInherited -eq $false -and $_.AccessRights -contains "FullAccess" }
	if($acls -ne $null){
		foreach ($acl in $acls) { 
			$obj = New-Object PSCustomObject
			$obj | Add-Member -MemberType NoteProperty -Name "Mailbox" -Value $mailbox.Name
			$obj | Add-Member -MemberType NoteProperty -Name "SID" -Value $acl.User
			$Output += $obj 
		}
	}
}
$Output | Export-CSV s1521-acl.csv -Encoding UTF8

Dans cet exemple, je ne touche qu'aux permissions qui ont été rajoutées manuellement (IsInherited -eq $false) et aux droits complets (FullAccess). Si je ne recommande pas de changer le premier critère, il est possible de changer FullAccess pour un autre valeur si besoin. Je vous renvoie vers la documentation Microsoft concernant la commande Get-MailboxPermission pour plus d'informations sur le sujet.

Une fois le fichier CSV obtenu, je peux me servir de ce snippet pour le parcourir et procéder à la suppression des entrées relevées :

$acls = Import-CSV s1521-acl.csv
foreach($acl in $acls){
	Write-Host "Processing"$acl.Mailbox"with SID"$acl.SID
	Remove-MailboxPermission -Identity $acl.Mailbox -User $acl.SID -AccessRights FullAccess -Confirm:$false
}

Ce premier script est disponible dans une version commentée à télécharger.

Exchange et Powershell : uniformisation des adresses mail

Ce script Powershell récupère la liste des mailbox présentes pour les utilisateurs membres de l'OU spécifiée et ajoute comme adresse mail principale une adresse au format prenom.nom@domaine.tld.

Ce script permet donc d'uniformiser les adresses mail en gérant les divers caractères spéciaux et accents, tout en conservant les anciennes adresses qui peuvent servir comme alias, évitant d'avoir à communiquer par rapport à sa nouvelle adresse.

function process {
	Param([string] $name)
	$specials = @("- '","âä","éèëê","ïîì","ôö","üûù","ÿ")
	for($i=0; $i -lt $specials.Length; $i++) {
		for($j=0; $j -lt $specials[$i].Length; $j++) {
			switch($i) {
				"0" { $l = "" }
				"1" { $l = "a" }
				"2" { $l = "e" }
				"3" { $l = "i" }
				"4" { $l = "o" }
				"5" { $l = "u" }
				"6" { $l = "y" }
			}
			$name = $name.Replace(($specials[$i].SubString($j,1)),$l)
		}
	}
	return $name
}
 
$mailboxes = Get-Mailbox | Where-Object { $_.OrganizationalUnit -like "dundermifflin.inc/USERS/*"}
foreach ($mailbox in $mailboxes) {
	$adUser = Get-AdUser $mailbox.Name
	$newsmtp = ((process($adUser.GivenName))+"."+(process($adUser.Surname))).ToLower()+"@dundermifflin.inc"
	Set-Mailbox $mailbox -PrimarySmtpAddress $newsmtp
}

Comme toujours, vous pouvez télécharger le script dans une version commentée grâce au lien suivant.

Quelques snippets pour Exchange Management Shell

Travaillant de plus en plus sur Exchange ces derniers temps, j'essaye de maximiser mon utilisation courante du Exchange Management Shell. Je vais partager quelques snippets permettant de récupérer des informations qu'il est plus difficile voire impossible de récupérer via la console graphique. Ces snippets peuvent être de bonnes bases pour ensuite peaufiner une recherche, ou simplement avoir la syntaxe pour obtenir une autre information, ou encore pour être intégrés dans un script. A noter que j'ai utilisé ce code sur un Exchange on Premise, il est possible que certaines commandes soient à adapter pour un usage sur Exchange Online.


Liste des mailbox n'ayant pas OWA activé

Get-CasMailbox | Where-Object { $_.OWAEnabled -eq $false }

Liste des mailbox n'ayant pas ActiveSync activé

Get-CasMailbox | Where-Object { $_.ActiveSyncEnabled -eq $false }

La commande Get-CasMailbox permet de retourner d'autres informations, il suffit donc de modifier la propriété que l'on utilise comme critère pour obtenir un nouveau filtre.


Récupération de la taille des mailbox

Get-Mailbox | Get-MailboxStatistics | sort TotalItemSize | ft DisplayName, TotalItemSize, Database

Liste des mailbox n'étant pas sous la règle du quota par défaut de la database

Get-Mailbox | Where-Object {$_.UseDatabaseQuotaDefaults -eq $false} | sort ProhibitSendQuota | ft DisplayName, Database, ProhibitSendQuota

Vérifier les permissions d'un utilisateur sur les mailbox

Get-Mailbox | Get-MailboxPermission | Where-Object {$_.User -like "DOMAINE\enguerrand"} | ft AccessRights, IsInherited, Deny -GroupBy identity

Pour ce snippet, il suffit d'ajouter un paramètre à l'instruction Get-Mailbox pour cibler une boîte particulière.


Lister toutes les mailbox par type

Get-Mailbox | sort RecipientTypeDetails | ft DisplayName, Alias, PrimarySmtpAddress -GroupBy RecipientTypeDetails

Visualiser le trafic sur une mailbox

Get-TransportServer | Get-MessageTrackingLog -Start "01/01/1990 02:00:00" -End "02/01/1990 03:00:00" -Recipients enguerrand@domaine.local

Il est possible de remplacer le paramètre -Recipients par -Sender si l'on souhaite avoir un autre point de vue. Les deux paramètres sont cumulables, permettant de centrer la recherche sur un émetteur et un destinataire. Le paramètre -EventID pouvant prendre les valeurs SEND ou RECEIVE par exemple offre la possibilité de n'afficher uniquement les mails effectivement reçus ou envoyés.

Lister les mails reçus sur une mailbox

Get-TransportServer | Get-MessageTrackingLog -Start "01/01/1990 02:00:00" -End "02/01/1990 03:00:00" -Recipients enguerrand@domaine.local -EventID Receive

Vérifier si une mailbox a des éléments supprimés récupérables

Get-Mailbox enguerrand | Get-MailboxFolderStatistics | Where-Object { $_.Name -like "Recoverable Items" -and $_.ItemsInFolder -gt 0 }

Lister les mailbox attachées à des utilisateurs présents dans une OU

Get-Mailbox | Where-Object {$_.DistinguishedName -like "*OU=Sales*"} | select alias

Exchange et Powershell : usage des databases

Ce script renvoie le nombre de boîtes aux lettres stockées dans une database Exchange ainsi que sa taille.

Le script peut s'appeler avec le nom de la database en paramètre ; si aucun paramètre n'est spécifié, alors le script parcourt toutes les databases.

Par exemple, pour récupérer les informations sur la database DBEXCHFR1, il suffira d'appeler le script de cette manière :

.\exch_dbusage.ps1 -db dbexchfr1

Le script est téléchargeable dans une version commentée.

Param([string]$db)
if($db -eq $null) { $mbxdbs = Get-MailboxDatabase -status | select Name,DatabaseSize }
else { $mbxdbs = Get-MailboxDatabase -status | select Name,DatabaseSize | Where-Object { $_.Name -eq $db } }
foreach($mbxdb in $mbxdbs){
$mbxindb = Get-Mailbox | Where-Object { $_.Database -eq $mbxdb.Name }
Write-Host "Database"$mbxdb.Name
Write-Host "Number of mailboxes on that database:"$mbxindb.Count
Write-Host "Size:"$mbxdb.DatabaseSize`r`n
}