jojo0411
Goto Top

Exchange 2010 - Auslesen von der Anzahl der gespeicherten Kontakte pro Mailbox

Hallo Leute,

Ich bin auf der Suche nach einem Powershell Befehl der mir für jede Mailbox sagt wieviele Kontakte gespeichert sind.

Ich bin auf den Befehl Get-MailboxStatistics gestossen komme aber damit nicht weiter... geht das mit dem Befehl überhaupt?

nice greetz jojo

Content-Key: 389009

Url: https://administrator.de/contentid/389009

Printed on: April 16, 2024 at 09:04 o'clock

Member: YotYot
YotYot Oct 10, 2018 at 14:57:26 (UTC)
Goto Top
Moin!

Ich will mich da nicht bis aufs Letzte festlegen, aber vor drei, vier Jahren hatte ich eine ähnliche Idee (es gibt um Termine) und musste feststellen, dass das nicht per Powershell machbar ist, jedenfalls nicht auf Seite der Exchange-Administration.

Ich bin damals den Weg gegangen, mir für alle 50 User, die das bei mir betroffen hat, Vollzugriff auf die Postfächer zu geben und das Ganze dann per VBA innerhalb von Outlook abzufragen. Datenschutzrechtlich nicht nur bedenklich, sondern schlicht verboten, ohne explizite Einwilligung jedes einzelnen Benutzers ist das ein Grund für eine Kündigung, fristlos wäre verhandelbar. Arbeitsrechtsschutz hat sich dann auch erledigt.

Sicher gibt es elegantere Möglichkeiten, aber Du kommst ohne erweiterte Rechte immer nur bis ans Postfach und dessen Eigenschaften und auf die Eigenschaften von Ordnern, nicht aber an die einzelnen Elemente. Würde das gehen, wäre Exchange nicht DSGVO- oder BSDG-konform. Oder Du bräuchtest von jedem User das vollste Vertrauen, schriftlich fixiert und alles.

Gruß

Jörg
Member: colinardo
Solution colinardo Oct 10, 2018, updated at Oct 11, 2018 at 07:39:27 (UTC)
Goto Top
Servus
Zitat von @YotYot:
Ich will mich da nicht bis aufs Letzte festlegen, aber vor drei, vier Jahren hatte ich eine ähnliche Idee (es gibt um Termine) und musste feststellen, dass das nicht per Powershell machbar ist, jedenfalls nicht auf Seite der Exchange-Administration.
Doch, das ist definitiv mit Powershell machbar! face-smile

Vorraussetzungen für das Skript ist das es in der Exchange Management Shell ausgeführt wird, die EWS 2.2 DLL die ins Skriptverzeichnis gepackt werden muss und der Name des EX-Servers angepasst wird. Zusätzlich muss dem Account der das Skript ausführt die Impersonation RBAC Rolle zugewiesen werden, damit dieser Account sich als jede Mailbox ausgeben kann. Wie das geht steht hier.

Weitere Hinweise zu den Vorraussetzungen auch in diesem Thread:
Script odgl ausführen, wenn E-Mail eingeht

<#
   Anzahl der Kontakte jeder Mailbox ermitteln
   Vor dem Start des Skript ist dem User welcher das Skript später ausführt die Impersonation-Berechtigungzu erteilen:
   In diesem Beispiel der User 'Administrator' (Bitte einmalig in einer EMS ausführen)  
   New-ManagementRoleAssignment -Name:impersonationAssignmentName -Role:ApplicationImpersonation -User:Administrator
#>
if ($PSVersionTable.PSVersion.Major -lt 3){write-host "ERROR: Minimum Powershell Version 3.0 is required!" -F Yellow; return}  

# FQDN des Exchange Servers
$EXCHANGESERVER = 'ex.domain.tld'  


# Funktion zum Verbinden mit dem Exchange EWS Dienst
function ConnectTo-EWS {
    param(
        [parameter(mandatory=$false)][bool]$UseScriptCredentials = $true,
        [parameter(mandatory=$false)][pscredential]$Credential,
        [parameter(mandatory=$false)][ValidateScript({Test-Path $_})][string]$ewsdll = "$psscriptroot\Microsoft.Exchange.WebServices.dll",  
        [parameter(mandatory=$false)][string]$mailbox = $null,
        [parameter(mandatory=$true)][string]$server
    )

    # Allen Zertifikaten vertrauen
    try{
        Add-Type '  
            using System.Net;
            using System.Security.Cryptography.X509Certificates;
            public class TrustAllCertsPolicy : ICertificatePolicy {
                public bool CheckValidationResult(
                    ServicePoint srvPoint, X509Certificate certificate,
                    WebRequest request, int certificateProblem) {
                    return true;
                }
            }
        '  
        # Trust all certs policy dem ServicePointManager zuweisen
        [System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
    }catch{}

    # EWS DLL laden
    Add-Type -Path $ewsdll

    # EWS-Service Objekt erstellen
    $ews = new-object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2010)
    $ews.Url = "https://$server/ews/exchange.asmx"  
    $ews.UseDefaultCredentials = $UseScriptCredentials
    if (!$UseScriptCredentials){
        $ews.Credentials = $Credential.GetNetworkCredential()
    }
    if($mailbox){
        $ews.ImpersonatedUserId = New-Object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress, $mailbox)
    }
    return $ews
}

# Funktion um eine Ordnerhierarchie nach einem Ordner zu durchsuchen
function Get-EWSFolder{
    param(
        [parameter(mandatory=$true)][Microsoft.Exchange.WebServices.Data.WellKnownFolderName]$storeroot,
        [parameter(mandatory=$false)][string]$path = "",  
        [parameter(mandatory=$true)][Microsoft.Exchange.WebServices.Data.ExchangeService]$service
    )
    # rekusiver Skriptblock zum Suchen eines Ordnerpfades
    $findfolder = {
        param(
            $id,
            [string]$subpath
        )
        if ($subpath -ne ""){  
            $parts = $subpath.Split("\")  
            $view = New-Object Microsoft.Exchange.WebServices.Data.FolderView(1)
            $view.Traversal = [Microsoft.Exchange.WebServices.Data.FolderTraversal]::Shallow
            $view.PropertySet = New-Object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties)
 
            $f = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.FolderSchema]::DisplayName,$parts)
            $result = $service.FindFolders($id,$f,$view)
            
            if ($result.TotalCount -gt 0){
                if ($parts.Count -gt 1 ){
                    & $findfolder -id $result.Folders.Id -subpath $subpath.Split("\",2)[-1]  
                }else{
                    return $result.Folders
                }        
            }else{
                throw "Search returned no results for path subpart '$($parts)'."  
            }
        }else{
            return ([Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$id))
        }

    }
    return (& $findfolder -id $storeroot -subpath $path)
}

# Funktion um Elemente eines Ordners zurückkzugeben
function Get-EWSFolderItems{
    param(
        [parameter(mandatory=$true,ValueFromPipelineByPropertyName=$true)]$id,
        [parameter(mandatory=$false)][int]$pageSize = 1000,
        [parameter(mandatory=$false)][Microsoft.Exchange.WebServices.Data.PropertySet]$propset = (New-Object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties)),
        [parameter(mandatory=$false)][Hashtable]$filter = $null,
        [parameter(mandatory=$false)][ValidateSet('And','Or')][Microsoft.Exchange.WebServices.Data.LogicalOperator]$filterLogicalOperator = 'And',  
        [parameter(mandatory=$true)][Microsoft.Exchange.WebServices.Data.ExchangeService]$service
    )
    $result = $null
    $view = New-Object Microsoft.Exchange.WebServices.Data.ItemView($pageSize)
    $view.PageSize = $pageSize
    $view.Traversal = [Microsoft.Exchange.WebServices.Data.ItemTraversal]::Shallow
    $view.PropertySet = $propset
    $filterCollection = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+SearchFilterCollection
    $filterCollection.LogicalOperator = $filterLogicalOperator
    
    if ($filter -ne $null){    
        $filter.GetEnumerator() | %{
            $filterCollection.Add((New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo($_.Key,$_.Value)))
        }
    }

    $moreItems = $true
    $resultSet = @()
    while($moreItems){
        $result = $service.FindItems($id,$filterCollection,$view)
        if ($result.TotalCount -gt 0){
            $resultSet += $result.Items
        }
        $view.Offset = $result.NextPageOffset
        $moreItems = $result.MoreAvailable
    }
    
    if ($resultSet.Count -gt 0){
        return $resultSet
    }else{
        return $null
    }
}

# Mit Service verbinden
$svc = ConnectTo-EWS -Server $EXCHANGESERVER

$mailboxes = Get-Mailbox -Filter "IsMailBoxEnabled -eq 'True'" -ResultSize unlimited | select -Expand PrimarySmtpAddress  


# Mailboxen durchlaufen
foreach($mailbox in $mailboxes){
    # Im Kontext des Benutzers in seiner Mailbox arbeiten
    $svc.ImpersonatedUserId = New-Object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress, [string]$mailbox)
    # Extended property für Spezial-Ordner 'AllItems' erzeugen  
    $allFoldersType = New-Object Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(13825,[Microsoft.Exchange.WebServices.Data.MapiPropertyType]::Integer)
    # Root der Mailbox holen
    $root = Get-EWSFolder -storeroot ([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Root) -service $svc
    # AllItems Ordner Ordner suchen
    $view = New-Object Microsoft.Exchange.WebServices.Data.FolderView(1)
    $view.Traversal = [Microsoft.Exchange.WebServices.Data.FolderTraversal]::Shallow
    $filterCollection = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+SearchFilterCollection
    $filterCollection.LogicalOperator = [Microsoft.Exchange.WebServices.Data.LogicalOperator]::And
    $filterCollection.Add((New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo($allFoldersType,"2")))  
    $filterCollection.Add((New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.FolderSchema]::DisplayName,"allitems")))  
    $result = $svc.FindFolders($root.Id,$filterCollection,$view)
    # Anzahl der Kontakte initialisieren
    $count = 0
    if ($result.TotalCount -gt 0){
        # Filter out items in DeletedItems Folder
        #$contacts = $result | Get-EWSFolderItems -service $svc -filter @{[Microsoft.Exchange.WebServices.Data.ItemSchema]::ItemClass = 'IPM.Contact'} -filterLogicalOperator And | ?{$_.ParentFolderId -ne [Microsoft.Exchange.WebServices.Data.Folder]::Bind($svc,[Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::DeletedItems).Id.UniqueId}  
        # Kontaktitems aus dem Spezialordner ausfiltern
        $contacts = $result | Get-EWSFolderItems -service $svc -filter @{[Microsoft.Exchange.WebServices.Data.ItemSchema]::ItemClass = 'IPM.Contact'} -filterLogicalOperator And -propset (New-Object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.ItemSchema]::ItemClass))  
        # Anzahl zuweisen
        $count = $contacts.Count
    }
    # Custom Object mit dem Ergebnis ausgeben
    [pscustomobject]@{Mailbox = $mailbox; ContactItems = $count}
}
Gezählt werden wirklich alle Kontakte in allen Ordnern, auch dem Papierkorb (kann man anpassen).

Grüße Uwe
Member: YotYot
YotYot Oct 10, 2018 at 15:27:38 (UTC)
Goto Top
@colinardo
Ach Mist, jetzt, wo Du den impersonated Account nennst - jaja, hätte mir auch auffallen können, ist bei E-Mail-Archivierung ja auch nichts anderes, wenn man die vorhandenen Postfächer importieren will.
Gut, dass ich mich nicht ganz festgelegt habe face-big-smile
Member: jojo0411
jojo0411 Oct 16, 2018 at 13:54:42 (UTC)
Goto Top
Danke für eure Antworten... hat mir sehr geholfen!

nice greetz jojo