chris123
Goto Top

Anzahl Mails nach Datum in öffentlichen Ordnern finden

Hallo zusammen,

ich möchte in unseren öffentlichen Ordnern die Anzahl an Mails finden die vor dem 21.05.201 in den jeweiligen Ordner erstellt (DateTimeCreated) wurden. Im Idealfall wird das Ergebins in einer CSV mit den Ordnern und der Anzahl an Mails ausgegeben.

Kann mir jemand dabei behiflich sein? Ich bekomme das leider nicht hin.

Es handelt sich um einen Exchange 2016.

Vielen Dank
Chris

Content-Key: 1898980268

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

Printed on: April 19, 2024 at 12:04 o'clock

Member: colinardo
Solution colinardo Feb 12, 2022 updated at 17:20:03 (UTC)
Goto Top
Hi Chris,
mal schnell zusammen gelötet ...
#Requires -Version 3

<#
   Count mail messages older than specific date from pubilc folder structure (recursive)
#>

# ================ Variables ================
# Credentials to use
$CREDENTIAL = (new-Object PSCredential('USERNAME',(ConvertTo-SecureString 'PASSWORD' -AsPlainText -Force)))  
# Exchange Server FQDN
$SERVER = 'server.domain.tld'  
# Messages older than will be counted
$OLDERTHANDATE = '21.05.2021'  
# folder path from public folder root
$PUBLICFOLDERPATH = ''  
# path to logfile
$LOGPATH = "$PSScriptRoot\report.csv"  

# ================ SCRIPT-Prefs ================
# stop on error
$ErrorActionPreference = 'Stop'  
# Accept all TLS protocols
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::GetNames([System.Net.SecurityProtocolType]) 
# ================== HELPER FUNCTIONS ===================
# Connect to exchange service
function ConnectTo-EWS {
    param(
        [parameter(mandatory=$true)][bool]$UseScriptCredentials = $true,
        [parameter(mandatory=$false)][pscredential]$Credential,
        [parameter(mandatory=$true,ParameterSetName='A')][string]$server,  
        [parameter(mandatory=$true,ParameterSetName='B')][string]$email  
    )

    # trust all certificates
    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;
                }
            }
        '  
        # assign policy to ServicePointManager
        [System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
    }catch{}

    # load ews dll
    Load-EWSLibrary

    # EWS-Service Objekt erstellen
    $ews = new-object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2010)
    if ($server){
        $ews.Url = "https://$server/ews/exchange.asmx"  
    }else{
        $ews.AutodiscoverUrl($email)
    }
    $ews.UseDefaultCredentials = $UseScriptCredentials
    if (!$UseScriptCredentials){
        $ews.Credentials = $Credential.GetNetworkCredential()
    }
    return $ews
}
# Function to load EWS assemblies from nuget if not found in current folder or temp
function Load-EWSLibrary {
    if($psscriptroot -ne ''){  
        $localpath = join-path $psscriptroot 'Microsoft.Exchange.WebServices.dll'  
    }else{
        $localpath = join-path $env:TEMP 'Microsoft.Exchange.WebServices.dll'  
    }
    $tmp = '';$zip = $null  
    try{
        if(!(Test-Path $localpath)){
            Add-Type -A System.IO.Compression.FileSystem
            $tmp = "$env:TEMP\$([IO.Path]::GetRandomFileName())"  
            write-host "Downloading and extracting required 'Microsoft.Exchange.WebServices.dll' ... " -F Green -NoNewline  
            (New-Object System.Net.WebClient).DownloadFile('https://www.nuget.org/api/v2/package/Exchange.WebServices.Managed.Api', $tmp)  
            $zip = [System.IO.Compression.ZipFile]::OpenRead($tmp)
            $zip.Entries | ?{$_.Fullname -eq 'lib/net35/Microsoft.Exchange.WebServices.dll'} | %{  
                [System.IO.Compression.ZipFileExtensions]::ExtractToFile($_,$localpath)
            }
            Unblock-File -Path $localpath
            write-host "OK" -F Green  
        }
        Add-Type -Path $localpath
    }catch{
        write-error "Error downloading required EWS Library / Error: $($_.Exception.Message)"  
    }finally{
        if ($zip){$zip.Dispose()}
        if($tmp -ne ''){del $tmp -Force -EA SilentlyContinue}  
    }
}
# function to bind to a specific folder
function Get-EWSFolder{
    param(
        [parameter(mandatory=$true)][Microsoft.Exchange.WebServices.Data.WellKnownFolderName]$storeroot,
        [parameter(mandatory=$false)][string]$mailbox,
        [parameter(mandatory=$false)][string]$path = "",  
        [parameter(mandatory=$true)][ValidateNotNullOrEmpty()][Microsoft.Exchange.WebServices.Data.ExchangeService]$service
    )
    $path = $path -replace '^\\'  
    # rekusiver Skriptblock zum Suchen eines Ordnerpfades
    $findfolder = {
        param(
            [string]$mailbox,
            $id,
            [string]$subpath
        )
        # bind folder to specific mailbox only when parameter is not empty and not public folder root
        if($mailbox -ne "" -and $id -ne [Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::PublicFoldersRoot){  
            $id = New-Object Microsoft.Exchange.WebServices.Data.FolderId $id,$mailbox
        }

        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 -mailbox $mailbox -id $storeroot -subpath $path)
}
# function to load/filter items from folder
function Get-EWSFolderItems{
    param(
        [parameter(mandatory=$true,ValueFromPipelineByPropertyName=$true)][Microsoft.Exchange.WebServices.Data.FolderId[]]$id,
        [parameter(mandatory=$false)][int]$maxitems = 10000,
        [parameter(mandatory=$false)][Microsoft.Exchange.WebServices.Data.PropertySet]$propset = $null,
        [parameter(mandatory=$false)][Hashtable]$filter = $null,
        [parameter(mandatory=$false)][ValidateSet('And','Or')][Microsoft.Exchange.WebServices.Data.LogicalOperator]$filterLogicalOperator = 'And',  
        [parameter(mandatory=$true,ValueFromPipelineByPropertyName=$true)][ValidateNotNullOrEmpty()][Microsoft.Exchange.WebServices.Data.ExchangeService]$service
    )
    begin{
        $resultSet = @()
        $view = New-Object Microsoft.Exchange.WebServices.Data.ItemView($maxitems)
    }
    process{
        foreach($i in $id){
            $result = $null
            $moreItems = $true    
            if ($propset -ne $null){
                $view.PropertySet = $propset
            }else{
                $view.PropertySet = New-Object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties)
            }
            if ($filter -ne $null){
                $filterCollection = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+SearchFilterCollection
                $filterCollection.LogicalOperator = $filterLogicalOperator
                $filter.GetEnumerator() | %{
                    $itm = $_
                    if ($itm.Value -is [hashtable]){
                        switch($itm.Value.Operator){
                            ">" {$filterCollection.Add((New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+IsGreaterThan($itm.Key,$itm.Value.Value)))}  
                            "<" {$filterCollection.Add((New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+IsLessThan($itm.Key,$itm.Value.Value)))}  
                            "<=" {$filterCollection.Add((New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+IsLessThanOrEqualTo($itm.Key,$itm.Value.Value)))}  
                            ">=" {$filterCollection.Add((New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+IsGreaterThanOrEqualTo($itm.Key,$itm.Value.Value)))}  
                            "!=" {$filterCollection.Add((New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+IsNotEqualTo($itm.Key,$itm.Value.Value)))}  
                            "=" {$filterCollection.Add((New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo($itm.Key,$itm.Value.Value)))}  
                            "contains" {$filterCollection.Add((New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+ContainsSubstring($itm.Key,$itm.Value.Value)))}  
                        }
                    }else{
                        $filterCollection.Add((New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo($_.Key,$_.Value)))
                    }
                }
                while($moreItems){
                    $result = $service.FindItems($i,$filterCollection,$view)
                    if ($result.TotalCount -gt 0){
                        $resultSet += $result.Items
                    }
                    $view.Offset = $result.NextPageOffset
                    $moreItems = $result.MoreAvailable
                }
            }else{
                while($moreItems){
                    $result = $service.FindItems($i,$view)
                    if ($result.TotalCount -gt 0){
                        $resultSet += $result.Items
                    }
                    $view.Offset = $result.NextPageOffset
                    $moreItems = $result.MoreAvailable
                }
            }
        }
    }
    end{
        if ($resultSet.Count -gt 0){
            return $resultSet
        }else{
            return $null
        }
    }  
}
# get all public folders recursive
function Get-EWSAllPublicFolders {
    param(
        [parameter(mandatory=$false,ValueFromPipeline=$true)]$folder,
        [parameter(mandatory=$true,ValueFromPipelineByPropertyName=$true)][ValidateNotNullOrEmpty()][Microsoft.Exchange.WebServices.Data.ExchangeService]$service
    )
    if (!$folder){
        $folder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,[Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::PublicFoldersRoot)
    }
    $view = New-Object Microsoft.Exchange.WebServices.Data.FolderView([int]::MaxValue)
    $view.Traversal = [Microsoft.Exchange.WebServices.Data.FolderTraversal]::Shallow
    $view.PropertySet = New-Object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties)
    $resultset = @()
    $moreItems = $true
    while($moreItems){
        $result = $service.FindFolders($folder.id,$view)
        if ($result.Count -gt 0){
            $resultset += $result.Folders
            foreach($f in $result.Folders){
                $resultset += Get-EWSAllPublicFolders $f -service $service
            }
        }
        $view.Offset = $result.NextPageOffset
        $moreItems = $result.MoreAvailable
    }
    return $resultset
}
# ==========================================================

# connect to service
write-host "Connecting to service on '$SERVER'." -F Green  
$svc = ConnectTo-EWS -Server $SERVER -UseScriptCredentials $false -Credential $CREDENTIAL
# get object of specific folder in public folder root
$root = Get-EWSFolder -storeroot PublicFoldersRoot -path $PUBLICFOLDERPATH -service $svc
# parse date string from variable
$dt = [datetime]::Parse($OLDERTHANDATE,[cultureinfo]'de')  
# filter old items from root and all sub folders
write-host "Find matching items, this could take some time please wait ... " -F Green -NoNewline  
$result = foreach ($folder in ($root | Get-EWSAllPublicFolders)){
    $itemcount = (Get-EWSFolderItems -id $folder.id -filter @{[Microsoft.Exchange.WebServices.Data.ItemSchema]::DateTimeCreated = @{Operator="<";Value=$dt}} -service $svc | ?{$_.ItemClass -in 'IPM.Note'}).Count  
    [pscustomobject]@{
        Folder = $folder.DisplayName
        ItemCount = $itemcount
    }
}
write-host "Done" -F Green  
$result | export-csv -LiteralPath $LOGPATH -Delimiter ";" -NoType -Encoding UTF8  

Schönen Abend
Grüße Uwe
Member: chris123
chris123 Feb 12, 2022 at 19:36:27 (UTC)
Goto Top
Ich bin sprachlos! Vielen Dank!

Grüße
Chris