Powershell : extraction des adresses du champ "To" d'une entête SMTP

J'ai développé en Powershell un script permettant d'extraire les adresses mail d'une en-tête SMTP. Mon but était de récupérer dans un fichier CSV une liste d'adresses pour effectuer sur ces adresses un traitement supplémentaire.

Dans Outlook, il suffit donc d'ouvrir l'entête SMTP du mail en question, de copier-coller le champ "To" dans un fichier texte et de le passer en paramètre lors de l'exécution du script pour obtenir la liste des adresses dans l'output console Powershell ainsi que dans le fichier CSV passé en paramètre. On peut donc l'appeler ainsi :

.\regex-to-smtp-header.ps1 -Header to.txt -CsvOutput addresses.csv

Voici le script, la version commentée est disponible après celui-ci.

param([Parameter(Mandatory=$true)][string]$Header, [Parameter(Mandatory=$true)][string]$CsvOutput)
$CsvExport = @()
$smtpheader = Get-Content -Path $Header -Raw -ErrorAction stop
while($smtpheader.IndexOf("<") -ne -1) {
    $ls = $smtpheader.IndexOf("<")
    $rs = $smtpheader.IndexOf(">")
    $adrlgt = $rs-$ls
    $adr = $smtpheader.SubString(($ls+1),($adrlgt-1))
    echo $adr
    $adrcsv=@{Address=$adr}
    $adrexp = New-Object PSObject -Property $adrcsv
    $CsvExport+=$adrexp
    $smtpheader = $smtpheader.Substring($rs+1,(($smtpheader.Length-$rs)-1))
}
$CsvExport | Export-CSV $CsvOutput -NoTypeInformation

Powershell : repadmin sur tous les DC du domaine

Je vais partager aujourd'hui un snippet qui va me servir de base pour implémenter un contrôle des réplications qui fonctionne aujourd'hui uniquement sur base d'un appel de dcdiag.

Ce snippet récupère donc les contrôleurs de domaine et récupère les timestamp des dernières réplications. Ensuite, pour chaque DC, il affiche en vert celles qui date de moins d'une heure et en rouge celles qui datent de plus d'une heure.

$dc = (Get-AdDomain).ReplicaDirectoryServers
$csvpath = "C:\temp\replications.csv"
$dc | Foreach { 
	if(Test-Path $csvpath) { Remove-Item $csvpath }
	Add-Content -Path $csvpath -Value (repadmin /showrepl $_ -csv)
	$csvcontent = Import-CSV $csvpath
	Write-Host -ForegroundColor Cyan `r`n$_
	$csvcontent | foreach {
        if(([datetime]$_.'Last Success Time').AddHours(1) -gt (Get-Date)) { Write-Host -ForegroundColor Green ($_.'Source DSA')($_.'Naming Context')($_.'Last Success Time') }
        else {  Write-Host -ForegroundColor Red ($_.'Source DSA')($_.'Naming Context')($_.'Last Success Time') }
    }
} 
if(Test-Path $csvpath) { Remove-Item $csvpath }

Si, au départ, je pensais avoir à manipuler le texte renvoyé par la commande pour extraire les bonnes informations, la commande repadmin avec l'argument showrepl accepte le paramètre -csv pour réaliser un export qui est ensuite facilement interprétable par Powershell.

Vous pouvez trouver toute la documentation nécessaire à l'utilisation de la commande repadmin sur le site de Microsoft.

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.

Powershell : rapport d'état d'occupation des disques locaux de serveurs

J'ai développé un script Powershell utilisant WMI pour adresser à tous les ordinateurs d'une sélection d'OU ActiveDirectory une requête pour connaître l'état de leurs disques. Le but de ce script est de pouvoir générer des rapports d'état (au format CSV ou XML) pour prévoir l'occupation de certaines plateformes et tracer une évolution, afin de pouvoir agir en conséquence (libération d'espace disque, augmentation du disque...)

Bien que la requête soit identique pour les deux scripts, le traitement pour un export CSV est différent de celui qui génère un fichier XML.

Le script permettant de réaliser le rapport en CSV :

function dothemaths {
	param($Disk)
	$Size = $Disk.Size
	$FS = $Disk.FreeSpace
	$DiskPerc = [math]::Round(($FS/$Size)*100,0)
	return $DiskPerc
}

$Output = @()
$SearchBases = @('OU=APP','OU=FILERS','OU=PRINT','OU=ADMIN')
foreach($SearchBase in $SearchBases){
	$Comps = Get-AdComputer -filter * -SearchBase "$SearchBase,OU=SERVERS,DC=dundermifflin,DC=inc" | select name
	foreach($Comp in $Comps){
		$DiskList = Get-WmiObject Win32_LogicalDisk -ComputerName $Comp.name
		foreach ($Disk in $DiskList){
			if($Disk.DriveType -ne 3){ continue }
			$Temp = New-Object PSCustomObject
			Add-Member -InputObject $Temp -Type NoteProperty -Name 'ComputerName' -Value $Comp.name
			Add-Member -InputObject $Temp -Type NoteProperty -Name 'DiskLetter' -Value $Disk.DeviceID
			Add-Member -InputObject $Temp -Type NoteProperty -Name 'DiskName' -Value $Disk.VolumeName
			Add-Member -InputObject $Temp -Type NoteProperty -Name 'Size' -Value $Disk.Size
			Add-Member -InputObject $Temp -Type NoteProperty -Name 'FreeSpace' -Value $Disk.FreeSpace
			Add-Member -InputObject $Temp -Type NoteProperty -Name 'FreeSpacePercentage' -Value (dothemaths($Disk))
			$Output+=$Temp
		}
	}
}
$Output | Export-CSV DiskReport.csv

Le format CSV peut ensuite être ouvert et exploité dans Excel. Afin de convertir les valeurs exprimées en octet en Mo ou en Go par exemple, il suffira de réaliser un collage spécial sur les colonnes pour faire une division par le nombre correspondant (1073741824 par exemple pour un affichage en Go).

Le script permettant de réaliser un rapport au format XML :

function dothemaths {
	param($Disk)
	$Size = $Disk.Size
	$FS = $Disk.FreeSpace
	$DiskPerc = [math]::Round(($FS/$Size)*100,0)
	return $DiskPerc
}

$XML = New-Object System.Xml.XmlDocument
$XMLd = $XML.CreateXmlDeclaration("1.0","UTF-8",$null)
$XML.AppendChild($XMLd) | out-null
$XMLn = $XML.CreateNode("element","Servers",$null)
$SearchBases = @('OU=APP','OU=FILERS','OU=PRINT','OU=ADMIN')
foreach($SearchBase in $SearchBases){
	$Comps = Get-AdComputer -filter * -SearchBase "$SearchBase,OU=SERVERS,DC=dundermifflin,DC=inc" | select name
	foreach($Comp in $Comps){
		$DiskList = Get-WmiObject Win32_LogicalDisk -ComputerName $Comp.name
		$CompNode = $XML.CreateNode("element","Server",$null)
		$CompNode.SetAttribute("Name",$Comp.name)
		foreach ($Disk in $DiskList){
			if($Disk.DriveType -ne 3){ continue }			
			$XMLe = $XML.CreateElement("DiskLetter")
			$XMLe.InnerText = $Disk.DeviceID
			$CompNode.AppendChild($XMLe) | out-null
			$XMLe = $XML.CreateElement("DiskName")
			$XMLe.InnerText = $Disk.VolumeName
			$CompNode.AppendChild($XMLe) | out-null
			$XMLe = $XML.CreateElement("Size")
			$XMLe.InnerText = $Disk.Size
			$CompNode.AppendChild($XMLe) | out-null
			$XMLe = $XML.CreateElement("FreeSpace")
			$XMLe.InnerText = $Disk.FreeSpace
			$CompNode.AppendChild($XMLe) | out-null
			$XMLe = $XML.CreateElement("FreeSpacePercentage")
			$XMLe.InnerText = dothemaths($Disk)
			$CompNode.AppendChild($XMLe) | out-null
		}
		$XMLn.AppendChild($CompNode) | out-null
	}
}
$XML.AppendChild($XMLn) | out-null
$XML.Save("DiskReport.xml")

Ensuite, le fichier XML pourra être importé et exploité dans un objet Powershell, comme je l'ai expliqué dans ce tutoriel.