Blogbeitrag

16 | 01 | 2016

Exchange: Kein Drag & Drop in Outlook – Ursache und Lösung

Geschrieben von um 0:00 Uhr

Nach einer Migration von Exchange 2010 auf Exchange 2013, die mit dem DELL Migration Manager for Exchange durchgeführt wurde, haben sich Nutzer beschwert, dass sie in Outlook keine Elemente per Drag & Drop in einen bestimmten Unterordner des Posteingangs und dessen Unterordner verschieben können. Da dieser Ordner der e-Mail-Archivierung im Unternehmen diente, betraf es alle Nutzer und war auch beliebig reproduzierbar. Eine weitere Untersuchung ergab, dass:

  • auch keine neuen Elemente in diesen Ordnern erstellt werden können,
  • das Verschieben per Rechtsklick –> Verschieben nach… funktioniert
  • in OWA auch Drag & Drop funktioniert
  • nur diese archivierungsbezogenen Ordner betroffen sind
  • es keine Unterschiede in den Zugriffsrechten zwischen funktionierenden und nicht funktionierenden Ordnern gibt.

Der Blick auf die MAPI-Properties der Ordner per MFCMAPI ergab folgendes Bild, das auch schnell zur Lösung führte:

  • in Exchange 2010 fehlt in den betroffenen Ordner die Property PR_CONTAINER_CLASS komplett
  • in Exchange 2013 haben die „defekten“ Ordner zwar diese Property, sie ist aber leer
  • in beiden Systemen haben die Default-Ordner und solche, die von Hand angelegt wurden (und wo Drag & Drop ausnahmslos funktioniert) die Property auf den korrekten Wert „IPF.Note“ gesetzt.

Der Versuch, manuell den Wert für PR_CONTAINER_CLASS auf IPF.Note in einem der „defekten“ Ordner zu setzen, brachte sofort die Linderung für den betreffenden Ordner. Da 1.200 Postfächer betroffen waren und die Unterordner-Strukturen überall unterschiedlich waren, habe ich das folgende Skript geschrieben, das die Angelegenheit global heilt:


$ex_ps_url = "http://EXCHANGE01/PowerShell/"
$ex_ews_path = “C:\Program Files\Microsoft\Exchange\Web Services\2.2\Microsoft.Exchange.WebServices.dll”
$log_file = "C:\temp\folder_class.log"
$res_file = "C:\temp\folder_class_set.log"

################################################################
#                 F U N C T I O N S
################################################################

Function WriteLog ($text, $uname) {
    if ($uname) {
        $xname = $uname + " | "
    } else {
        $xname = "######## | "
    }
    ((Get-Date -Format "dd.MM.yyyy hh:mm:ss").ToString() + " | " + $xname + $text) | Out-File -FilePath $log_file -Append
}

Function DoSubFolder ($folder, $path) {
    $folderView = new-object Microsoft.Exchange.WebServices.Data.FolderView(2147483647)
    $subfolders = $folder.FindFolders($folderView)
    if (!$path) { $path = $folder.DisplayName }
    foreach ($subfolder in $subfolders) {
        if ($subfolder.SearchParameters -ne $null) {
            # If it's a search folder, just skip it
            continue
        }
        $xpath = $path + "\" + $subfolder.DisplayName
        if (!($subfolder.folderClass)) {
            WriteLog ($xpath + " has no FolderClass set! Setting FolderClass to IPF.Note") $name
            ($name + " --> " + $xpath) | Out-File -FilePath $res_file -Append
            $subfolder.FolderClass = "IPF.Note"
            $subfolder.Update()
        } else {
            WriteLog ($xpath + " has FolderClass property of " + $subfolder.folderClass) $name
        }
        DoSubfolder $subfolder $xpath
    }
}

################################################################
#                         S T A R T
################################################################

Add-Type -Path $ex_ews_path
$ExchangeVersion = [Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2013
$Service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService($ExchangeVersion)

if (!(Get-Command "Get-ExchangeServer" -EA SilentlyContinue)) {
    WriteLog "Connecting to Exchange using $ex_ps_url"
    $ex_rem_session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri $ex_ps_url -Authentication Kerberos -EA SilentlyContinue -WA SilentlyContinue
    Import-PSSession $ex_rem_session -DisableNameChecking -EA SilentlyContinue -WA SilentlyContinue > $null
} else {
    WriteLog "Exchange environment already established"
}

$mbxs = @(Get-Mailbox -ResultSize Unlimited)
$nmbx = $mbxs.Count
WriteLog ($nmbx.ToString() + " mailboxes to process...")
$i = 0
foreach ($mbx in $mbxs) {
    $mail = $mbx.PrimarySMTPAddress
    $name = $mbx.SamAccountName
    $i++
    WriteLog "Processing mailbox $i of $nmbx ..." $name
    Write-Host ([math]::Round((($i / $nmbx) * 100),2)).ToString() " % $name"
    if ($mail) {
        WriteLog "Primary email address is: $mail" $name
        $Service.AutodiscoverUrl($mail,{$true})
        WriteLog ("Autodiscover URL: " + $Service.Url.OriginalString) $name
        $Service.ImpersonatedUserId = new-object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress, $mail)
        $fldInbox = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($Service, [Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox)
        WriteLog ("Default Inbox folder: " + $fldInbox.DisplayName + " contains " + $fldInbox.TotalCount + " item(s)") $name
        DoSubFolder $fldInbox
    } else {
        WriteLog "Primary email address NOT SPECIFIED! Skipping mailbox..." $name
    }
}

if ($ex_rem_session) {
    Remove-PSSession $ex_rem_session -EA SilentlyContinue -WA SilentlyContinue
}

Damit dieser Code ausgeführt werden kann, benötigt das ausführende User-Account mindestens das Recht, alle Postfächer aufzulisten und deren SAMAccountName und PrimarySMTPAddress zu lesen (also: Mitgliedschaft in irgendeiner Exchange-Administratorrolle) sowie die ApplicationImpersonation-Berechtigung. Da alle Postfächer zu bearbeiten waren, war das Zuweisen dieser Berechtigung denkbar einfach:

New-ManagementRoleAssignment –Name "adminuser_may_impersonate" –Role ApplicationImpersonation –User: "DOMAIN\adminuser"

Noch ein wenig Hinergrund: Die Unterordner im Quellsystem wurden mit einem Skript angelegt, welches EWS Managed API 2.0 und ebenfalls ApplicationImpersonation nutzt. Dabei wurde denkbar einfach vorgegangen:

$oFolder = new-object Microsoft.Exchange.WebServices.Data.Folder($exchService)
$oFolder.DisplayName = "Mailarchiv"
$oFolder.Save([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::inbox)

Die FolderClass-Eigenschaft wurde nicht explizit gesetzt. Offensichtlich erstellt dabei EWS Managed API auch keine Property PR_CONTAINER_CLASS. DELL Migrator hingegen erstellt diese Property offenbar standardmäßig, bestückt sie jedoch strikt mit dem Wert, den sie im Quellsystem hatte. In diesem Fall also: mit keinem.

Happy troubleshooting!

Beitragsdetails

Tags » «

gravatar

Kategorie » DELL, Exchange & Lync, Microsoft, Migration, PowerShell, Server «

Trackback: Trackback-URL |  Kommentar-Feed: RSS 2.0 | 853 Worte

Beitrag kommentieren

Kommentar schreiben ...

Deine E-Mail-Adresse wird nicht veröffentlicht.

(X)HTML Tags zur Formatierung der Kommentare

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>