简体   繁体   中英

EWS Powershell Exchange 2013 FindFolders returns 0 results

I am currently trying to make this script run on exchange 2013 to convert folder types from IPF.IMAP to IPF.NOTE as the folders are not showing on mobile devices after being imported from Imap. This script returns 0 results after running and multiple Doesnt Exist. If I output the folder names they are coming through, so i am not sure why the FindFolders is not returning any results.

I tried turning on impersonation (commented out here) but get an error saying I do not have permissions to impersonate even though I am logged in as administrator and running on powershell as admin. I am not sure if this is even necessary as the script works fine and returns the folder names for both $mbxfolder.Name and $SfSearchFilter, but only until it hits the FindFolders line, then the TotalCount is always 0.

Import-Module -Name "C:\Program Files\Microsoft\Exchange\Web Services\1.2\Microsoft.Exchange.WebServices.dll"
$exchService = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService 
$exchService.UseDefaultCredentials = $true
$exchService.AutodiscoverUrl('email@domain.com', {$true})

$MBXID = "email@domain.com" #Define mailboxID
foreach ($MailboxIdentity in $MBXID) {
    Write-Host "Searching for $MailboxIdentity"
    $mailbox = (Get-Mailbox -Identity $MailboxIdentity)
    $MailboxName = (Get-Mailbox -Identity $MailboxIdentity).PrimarySmtpAddress.ToString()
    $MailboxRootid = new-object  Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Root,$MailboxName) #MsgFolderRoot selection and creation of new root
    $MailboxRoot = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($exchService,$MailboxRootid)
    #$exchService.ImpersonatedUserId = New-Object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId -ArgumentList ([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress),$MailboxName #Define impersonation
    $folderid = $MailboxRootid
    $f1 = $MailboxRoot
    $fold = get-mailboxfolderstatistics $MailboxIdentity #Getting complete list of selected mailbox 


foreach ($mbxfolder in $fold){
        #Define Folder View Really only want to return one object  
        $fvFolderView = new-object Microsoft.Exchange.WebServices.Data.FolderView(100) #page size for displayed folders
        $fvFolderView.Traversal = [Microsoft.Exchange.WebServices.Data.FolderTraversal]::Deep; #Search traversal selection Deep = recursively
        #Define a Search folder that is going to do a search based on the DisplayName of the folder  
        $SfSearchFilter = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.FolderSchema]::Displayname,$MBXFolder.name) #for each folder in mailbox define search
        $findFolderResults = $MailboxRoot.FindFolders($SfSearchFilter,$fvFolderView) #for each folder in mailbox define folder view (this is online task for store.exe) and perform search

        if ($findFolderResults.TotalCount -eq 0){ "Folder Doesn't Exist"  } #Info if folder still exist
        else {"Folder Exist"  
        ForEach ($Folder in $findFolderResults.Folders) { #for each folder in folder results perform check of folder class
            $folder.folderclass #Info about folder class
            if ($Folder.folderclass -eq "IPF.Imap"){ #If folder class is target type, do change and update
                    $Folder.folderclass = "IPF.Note" #Folder class change in variable
                    Write-Host "Updating folder $folder.name to correct type IPF.Note. Folder will  start to be visible in OWA"
                    $Folder.update() #Folder class update in mailbox via EWS
                }
        }
        }
        }

}

It doesn't really make much sense to enumerate the the folders using Get-MailboxFolderStatistics and then search for each folder in EWS. This is going to really slow and unnecessary (you have the folderId anyway from Get-MailboxFolderStatistics so you can just convert that and bind to it). However I would Get rid of Get-MailboxFolderStatistics altogether and just use straight EWS to enumerate the Folders in the Mailbox and do your fixes as this will be much quicker eg

    ## Get the Mailbox to Access from the 1st commandline argument

$MailboxName = $args[0]

## Load Managed API dll  
###CHECK FOR EWS MANAGED API, IF PRESENT IMPORT THE HIGHEST VERSION EWS DLL, ELSE EXIT
$EWSDLL = (($(Get-ItemProperty -ErrorAction SilentlyContinue -Path Registry::$(Get-ChildItem -ErrorAction SilentlyContinue -Path 'Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Exchange\Web Services'|Sort-Object Name -Descending| Select-Object -First 1 -ExpandProperty Name)).'Install Directory') + "Microsoft.Exchange.WebServices.dll")
if (Test-Path $EWSDLL)
    {
    Import-Module $EWSDLL
    }
else
    {
    "$(get-date -format yyyyMMddHHmmss):"
    "This script requires the EWS Managed API 1.2 or later."
    "Please download and install the current version of the EWS Managed API from"
    "http://go.microsoft.com/fwlink/?LinkId=255472"
    ""
    "Exiting Script."
    exit
    } 

## Set Exchange Version  
$ExchangeVersion = [Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2007_SP1  

## Create Exchange Service Object  
$service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService($ExchangeVersion)  

## Set Credentials to use two options are availible Option1 to use explict credentials or Option 2 use the Default (logged On) credentials  

#Credentials Option 1 using UPN for the windows Account  
$psCred = Get-Credential  
$creds = New-Object System.Net.NetworkCredential($psCred.UserName.ToString(),$psCred.GetNetworkCredential().password.ToString())  
$service.Credentials = $creds      
#$service.TraceEnabled = $true
#Credentials Option 2  
#service.UseDefaultCredentials = $true  

## Choose to ignore any SSL Warning issues caused by Self Signed Certificates  

## Code From http://poshcode.org/624
## Create a compilation environment
$Provider=New-Object Microsoft.CSharp.CSharpCodeProvider
$Compiler=$Provider.CreateCompiler()
$Params=New-Object System.CodeDom.Compiler.CompilerParameters
$Params.GenerateExecutable=$False
$Params.GenerateInMemory=$True
$Params.IncludeDebugInformation=$False
$Params.ReferencedAssemblies.Add("System.DLL") | Out-Null

$TASource=@'
  namespace Local.ToolkitExtensions.Net.CertificatePolicy{
    public class TrustAll : System.Net.ICertificatePolicy {
      public TrustAll() { 
      }
      public bool CheckValidationResult(System.Net.ServicePoint sp,
        System.Security.Cryptography.X509Certificates.X509Certificate cert, 
        System.Net.WebRequest req, int problem) {
        return true;
      }
    }
  }
'@ 
$TAResults=$Provider.CompileAssemblyFromSource($Params,$TASource)
$TAAssembly=$TAResults.CompiledAssembly

## We now create an instance of the TrustAll and attach it to the ServicePointManager
$TrustAll=$TAAssembly.CreateInstance("Local.ToolkitExtensions.Net.CertificatePolicy.TrustAll")
[System.Net.ServicePointManager]::CertificatePolicy=$TrustAll

## end code from http://poshcode.org/624

## Set the URL of the CAS (Client Access Server) to use two options are availbe to use Autodiscover to find the CAS URL or Hardcode the CAS to use  

#CAS URL Option 1 Autodiscover  
$service.AutodiscoverUrl($MailboxName,{$true})  
"Using CAS Server : " + $Service.url   

#CAS URL Option 2 Hardcoded  

#$uri=[system.URI] "https://casservername/ews/exchange.asmx"  
#$service.Url = $uri    

## Optional section for Exchange Impersonation  

#$service.ImpersonatedUserId = new-object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress, $MailboxName) 



#Define Function to convert String to FolderPath  
function ConvertToString($ipInputString){  
    $Val1Text = ""  
    for ($clInt=0;$clInt -lt $ipInputString.length;$clInt++){  
            $Val1Text = $Val1Text + [Convert]::ToString([Convert]::ToChar([Convert]::ToInt32($ipInputString.Substring($clInt,2),16)))  
            $clInt++  
    }  
    return $Val1Text  
} 

#Define Extended properties  
$PR_FOLDER_TYPE = new-object Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(13825,[Microsoft.Exchange.WebServices.Data.MapiPropertyType]::Integer);  
$folderidcnt = new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::MsgFolderRoot,$MailboxName)  
#Define the FolderView used for Export should not be any larger then 1000 folders due to throttling  
$fvFolderView =  New-Object Microsoft.Exchange.WebServices.Data.FolderView(1000)  
#Deep Transval will ensure all folders in the search path are returned  
$fvFolderView.Traversal = [Microsoft.Exchange.WebServices.Data.FolderTraversal]::Deep;  
$psPropertySet = new-object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties)  
$PR_Folder_Path = new-object Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(26293, [Microsoft.Exchange.WebServices.Data.MapiPropertyType]::String);  
#Add Properties to the  Property Set  
$psPropertySet.Add($PR_Folder_Path);  
$fvFolderView.PropertySet = $psPropertySet;  
#The Search filter will exclude any Search Folders  
$sfSearchFilter = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo($PR_FOLDER_TYPE,"1")  
$fiResult = $null  
#The Do loop will handle any paging that is required if there are more the 1000 folders in a mailbox  
do {  
    $fiResult = $Service.FindFolders($folderidcnt,$sfSearchFilter,$fvFolderView)  
    foreach($ffFolder in $fiResult.Folders){  
        $foldpathval = $null  
        #Try to get the FolderPath Value and then covert it to a usable String   
        if ($ffFolder.TryGetProperty($PR_Folder_Path,[ref] $foldpathval))  
        {  
            $binarry = [Text.Encoding]::UTF8.GetBytes($foldpathval)  
            $hexArr = $binarry | ForEach-Object { $_.ToString("X2") }  
            $hexString = $hexArr -join ''  
            $hexString = $hexString.Replace("FEFF", "5C00")  
            $fpath = ConvertToString($hexString)  
        }  
        "FolderPath : " + $fpath  
        "Folder Class : " + $ffFolder.FolderClass
    } 
    $fvFolderView.Offset += $fiResult.Folders.Count
}while($fiResult.MoreAvailable -eq $true)  

Cheers Glen

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM