Error – move Mailbox from Exchange 2003 to Exchange 2010
Bei einer Migration von einer Exchange 2003 Umgebung auf Exchange 2010 bin ich auf ein ungewöhnlichen Fehler gestoßen. Als die ersten Mailboxen von Exchange 2003 auf die neue Exchange 2010 Umgebung verschoben wurden, kam es bei einigen Mailboxen zu Fehlern wie folgendes Log zeigt:
Log Name: Application Source: MSExchange Mailbox Replication Date: 17.6.2011. 11:29:28 Event ID: 1110 Task Category: Request Level: Warning Keywords: Classic User: N/A Computer: ExDB01.testing.local Description: The Microsoft Exchange Mailbox Replication service was unable to apply search criteria to a search folder. The error was ignored. Request: Primary (48706c9c-ad51-40d6-98b1-eb11039385e5) Folder name:/To-Do-Search Error: MapiExceptionInvalidEntryId: Unable to SetSearchCriteria. (hr=0x80040107, ec=-2147221241) Diagnostic context: Lid: 26926 Lid: 22830 StoreEc: 0x80040107 Lid: 32558 Lid: 18222 StoreEc: 0x80040107 Lid: 26414 Lid: 19246 StoreEc: 0x80040107 Lid: 18094 Lid: 27310 StoreEc: 0x80040107 Lid: 32382 Lid: 31358 StoreEc: 0x80040107 Lid: 16510 Lid: 31358 StoreEc: 0x80040107 Lid: 16510 Lid: 31358 StoreEc: 0x80040107 Lid: 26750 Lid: 22654 StoreEc: 0x80040107 Lid: 22161 Lid: 19089 StoreEc: 0x80040107 Lid: 18065 Lid: 26257 StoreEc: 0x80040107 Context: -------- Operation: IDestinationFolder.SetSearchCriteria OperationSide: Target Primary (48706c9c-ad51-40d6-98b1-eb11039385e5) Restriction: Restriction: AND[AND[PROPERTY[ptag:ParentEntryId, NotEqual, val:[Tag:ParentEntryId, Value:cb = 22, lpb = 0001020000000001A268000000000000000000000000]]; PROPERTY[ptag:ParentEntryId, NotEqual, val:[Tag:ParentEntryId, Value:cb = 22, lpb = 00010A00000005B10002000000000000000000000000]]; PROPERTY[ptag:ParentEntryId, NotEqual, val:[Tag:ParentEntryId, Value:cb = 22, lpb = 0001020000000007DC6E000000000000000000000000]]; PROPERTY[ptag:ParentEntryId, NotEqual, val:[Tag:ParentEntryId, Value:cb = 22, lpb = 0001020000000001A266000000000000000000000000]]; PROPERTY[ptag:ParentEntryId, NotEqual, val:[Tag:ParentEntryId, Value:cb = 22, lpb = 00010400000002548DCA000000000000000000000000]]; PROPERTY[ptag:ParentEntryId, NotEqual, val:[Tag:ParentEntryId, Value:cb = 22, lpb = 00010400000002548DCB000000000000000000000000]]; PROPERTY[ptag:ParentEntryId, NotEqual, val:[Tag:ParentEntryId, Value:cb = 22, lpb = 00010400000002548DCC000000000000000000000000]]; PROPERTY[ptag:ParentEntryId, NotEqual, val:[Tag:ParentEntryId, Value:cb = 22, lpb = 00010400000002548DC9000000000000000000000000]]]; AND[EXIST[ptag:237764866]; BITMASK[ptag:MessageFlags, EqualToZero, mask:0xC]]] EntryIDs: [[len=46, data=0000000020EAD2782070D3118CB000105AF14FD70100712D5DEA935BD3118CA900105AF14FD700000001A2620000]] Flags: Restart, Recursive, NonContentIndexed, FailOnForeignEID -------- Search folder: '/To-Do-Search', entryId [len=46, data=0000000020EAD2782070D3118CB000105AF14FD701008A7E0BD32E921449A8B66F31569AEBF10000002E58E60000], parentId [len=46, data=0000000020EAD2782070D3118CB000105AF14FD70100712D5DEA935BD3118CA900105AF14FD700000001A2610000] Event Xml: <Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event"> <System> <Provider Name="MSExchange Mailbox Replication" /> <EventID Qualifiers="32772">1110</EventID> <Level>3</Level> <Task>2</Task> <Keywords>0x80000000000000</Keywords> <TimeCreated SystemTime="2010-09-23T09:29:28.000000000Z" /> <EventRecordID>55259</EventRecordID> <Channel>Application</Channel> <Computer>ExDB01.testing.local</Computer> <Security /> </System> <EventData> <Data>Primary (48706c9c-ad51-40d6-98b1-eb11039385e5)</Data> <Data>/To-Do-Search</Data> <Data>MapiExceptionInvalidEntryId: Unable to SetSearchCriteria. (hr=0x80040107, ec=-2147221241) Diagnostic context: Lid: 26926 Lid: 22830 StoreEc: 0x80040107 Lid: 32558 Lid: 18222 StoreEc: 0x80040107 Lid: 26414 Lid: 19246 StoreEc: 0x80040107 Lid: 18094 Lid: 27310 StoreEc: 0x80040107 Lid: 32382 Lid: 31358 StoreEc: 0x80040107 Lid: 16510 Lid: 31358 StoreEc: 0x80040107 Lid: 16510 Lid: 31358 StoreEc: 0x80040107 Lid: 26750 Lid: 22654 StoreEc: 0x80040107 Lid: 22161 Lid: 19089 StoreEc: 0x80040107 Lid: 18065 Lid: 26257 StoreEc: 0x80040107</Data> <Data>-------- Operation: IDestinationFolder.SetSearchCriteria OperationSide: Target Primary (48706c9c-ad51-40d6-98b1-eb11039385e5) Restriction: Restriction: AND[AND[PROPERTY[ptag:ParentEntryId, NotEqual, val:[Tag:ParentEntryId, Value:cb = 22, lpb = 0001020000000001A268000000000000000000000000]]; PROPERTY[ptag:ParentEntryId, NotEqual, val:[Tag:ParentEntryId, Value:cb = 22, lpb = 00010A00000005B10002000000000000000000000000]]; PROPERTY[ptag:ParentEntryId, NotEqual, val:[Tag:ParentEntryId, Value:cb = 22, lpb = 0001020000000007DC6E000000000000000000000000]]; PROPERTY[ptag:ParentEntryId, NotEqual, val:[Tag:ParentEntryId, Value:cb = 22, lpb = 0001020000000001A266000000000000000000000000]]; PROPERTY[ptag:ParentEntryId, NotEqual, val:[Tag:ParentEntryId, Value:cb = 22, lpb = 00010400000002548DCA000000000000000000000000]]; PROPERTY[ptag:ParentEntryId, NotEqual, val:[Tag:ParentEntryId, Value:cb = 22, lpb = 00010400000002548DCB000000000000000000000000]]; PROPERTY[ptag:ParentEntryId, NotEqual, val:[Tag:ParentEntryId, Value:cb = 22, lpb = 00010400000002548DCC000000000000000000000000]]; PROPERTY[ptag:ParentEntryId, NotEqual, val:[Tag:ParentEntryId, Value:cb = 22, lpb = 00010400000002548DC9000000000000000000000000]]]; AND[EXIST[ptag:237764866]; BITMASK[ptag:MessageFlags, EqualToZero, mask:0xC]]] EntryIDs: [[len=46, data=0000000020EAD2782070D3118CB000105AF14FD70100712D5DEA935BD3118CA900105AF14FD700000001A2620000]] Flags: Restart, Recursive, NonContentIndexed, FailOnForeignEID -------- Search folder: '/To-Do-Search', entryId [len=46, data=0000000020EAD2782070D3118CB000105AF14FD701008A7E0BD32E921449A8B66F31569AEBF10000002E58E60000], parentId [len=46, data=0000000020EAD2782070D3118CB000105AF14FD70100712D5DEA935BD3118CA900105AF14FD700000001A2610000]</Data> </EventData> </Event>
Als ersten Schritt wurde dem "move request" die Option "Skip the corrupted messages" mit dem Wert von 5 mitgegeben. In der Regel waren im Durchschnitt nur 3 korrupte Objekte betroffen. Dadurch wurden die Mailboxen erfolgreich übertragen.
Bei näherer Untersuchung stellte ich fest, dass der Fehler nur bei Nutzern auftritt, die ihr Outlook im "Cache Mode" betreiben und die Aufgabenliste (To-Do Bar) verwenden. Wenn der "Cache Mode" bei den betroffenen Nutzern in den Outlook Optionen abgeschalten wird, ist die Aufgabenliste leer bzw. wird nicht angezeigt. Wenn der "move-Mailbox" Prozess bei 10% abbricht, so handelt es sich bei den korrupten Objekten um Standard Ordner oder Such-Ordner, wie in diesem Fall beschrieben. Sollte der Prozess bei einer höheren Prozentzahl abbrechen, so handelt es sich um individuelle korrupte Objekte.
Das Problem kann auf zwei Arten gelöst werden, entweder mit Outlook Commandline-Switches oder mit dem Tool "MFCMAPI".
Die Outlook Variantre:
Bei den meisten Nutzern reichte es aus Outlook mit folgenden "Switches" zu starten, um die korrupten Objekte zu bereinigen:
outlook.exe /cleanfinders
Bei einige Nutzern reichte das leide nicht aus um alle korrupten Objekte zu bereinigen, dazu wurde Outlook dann mit folgenden "Switches" aufgerufen:
outlook.exe /cleanreminders /resettodobar
Damit wurden nahe zu alle Mailboxen bereinigt und konnten dann problemlos verschoben werden. Bei den ganz hartnäckigen Fällen half dann nur noch "MFCMAPI".
Die MFCMAPI Variante:
Bei den hartnäckigen Fällen verbindet man sich mit MFCMAPI und löscht den “Reminders” oder “Tracked Mail Processing” Ordner (kein permanente Löschung vornehmen!). Danach konnten alle Nutzer verschoben werden, ohne dass weitere korrupte Objekte gemeldet wurden.
Sollte es darüber hinaus weitere Probleme mit fehlenden Aufgabenbereichen (To-Do Bar) geben, dann öffnet man die Mailbox mit MFCMAPI und löscht (permanent/unrecoverable) den Ordner "To-Do Search" aus dem Root der Mailbox.
Links:
http://www.msxfaq.de/tools/mfcmapi.htm
disable Mailbox Script
In vielen Unternehmen wird das Usermanagement von der Unternehmenssoftware (z.B. SAP) zum Teil automatisiert übernommen. Dabei werden die Daten der Mitarbeiter aus der Personalabteilung über die Unternehmenssoftware in das Active Directory eingetragen. Dafür gibt es unter anderem den Identity Manager von Microsoft, was aber nicht jetzt Thema sein soll. Beim Ausscheiden von Mitarbeitern tun sich da unter Umständen aber ein paar Lücken auf die man eigentlich vermeiden will.
In einigen Unternehmen gibt es die Policy, dass die Useraccounts nach dem Ausscheiden deaktiviert aufbewahrt werden und erst nach einer bestimmten Frist (z.B. 90 Tage) gelöscht werden. Wenn ein Useraccount deaktiviert wurde, hat der Mitarbeiter eigentlich kein Zugriff auf Daten und Dienste mehr.
Wenn wir uns in der Situation einmal nur auf Exchange und die User Mailbox konzentrieren, müssen wir leider feststellen, dass die Aussage nicht ganz zutrifft. Der Mitarbeiter hat in der Tat nach seinem Ausscheiden mit deaktiviertem Useraccount kein direkten Zugriff mehr auf seine Mails, aber seine Mailbox existiert weiterhin und stellt den gesamten Funktionsumfang bereit. Hat der Mitarbeiter vor seinem Ausscheiden eine Weiterleitung an eine externe Mailadresse eingerichtet, so erhält er nach dem Ausscheiden auch weiterhin jede interne Mail an seine externe Adresse.
Wie kann das vermieden werden?
Ich haben seit einiger Zeit ein Script im Einsatz, welches alle Mailboxen trennt, dessen Mitarbeiter ausgeschieden sind. Aus der Unternehmenssoftware (z.B. SAP) heraus wird der Account des Mitarbeiters deaktiviert wenn dessen Vertragsverhältnis endet. An jeden 1. des Monats läuft das Script durch und überprüft alle Accounts nach diesen deaktivierten Mitarbeitern. Dazu ist in der Abfrage von "get-qaduser" die zu durchsuchende OU vorgegeben und es werden alle Resource Mailbox (Räume und Geräte) heraus gefiltert. Dieser Filter kann mit der Variable $filter in Zeile 36 beliebig angepasst werden. Bei den zurückgegebenen Accounts wird dann noch geprüft, welcher Account eine Mailbox hat. Dazu habe ich den Wert im Feld "SamAccountName" verwendet und an "get-user" übergeben. Das Ergebnis wird dann dazu verwendet, um mit "disable-mailbox" die Mailbox zu trennen.
Systemvoraussetzungen
Für den Einsatz dieses Scriptes ist die PowerShell und das entsprechende Exchange Management PowerShell Snapin der Serverversion von Nöten. Darüber hinaus wird die Quest ActiveRoles Management Shell for Active Directory 1.3 oder höher benötigt. Dieses Snapin ist noch aus älteren Zeiten, als es noch kein Active Directory Support für die PowerShell von Microsoft gab. Wer eine Domain auf Windows Server 2008 R2 betreibt kann auch das Active Directory Snapin von Microsoft verwenden. Und nicht vergessen, es müssen auch die entsprechenden Rechte vorhanden sein, um eine Mailbox trennen zu können.
Das Script sieht dann so aus:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | ############################################################## # # # Script to disable all Mailboxes of disabled Useraccounts # # # # Nico Wieczorek 02.02.2009 # # # ############################################################## #First, findout if Exchange Management Shell is loaded: $snapins = Get-PSSnapin |select name $snapincount = 0; $found = $false do { $founDName = $snapins[$snapincount].name switch ($founDName) { "Microsoft.Exchange.Management.PowerShell.Admin" {$found = $True; break} "Quest.ActiveRoles.ADManagement" {$found = $True; break} #Exchange Shell already loaded } $snapincount ++ } while ($snapincount -lt $snapins.Count) $date = ( get-date ).ToString('dd-MM-yyyy') $file = New-Item -type file "E:\Exchange\Scripts\output\$date-DisabledMailbox.csv" -force if ($found -ne $True) { Add-PSSnapin "Microsoft.Exchange.Management.PowerShell.Admin" Add-PSSnapin "Quest.ActiveRoles.ADManagement" } $AllUsers = @() $filter = "(!(|(mailnickname=confroom*)(mailnickname=car*)(mailnickname=handy*)(mailnickname=beamer*)))" $ou = "berlin.testing.local/Accounts" foreach ($objItem in Get-QADUser -Disabled -SearchRoot $ou -LdapFilter $filter) { foreach ($User in Get-User -Identity $objItem.SamAccountName -OrganizationalUnit $ou | where {$_.RecipientType -eq "UserMailbox"}) { $Datenbank = Get-Mailbox -Identity $User.Name Disable-Mailbox -Identity $User.DistinguishedName -confirm:$false $ReturnedObj = New-Object PSObject $ReturnedObj | Add-Member NoteProperty -Name "Nutzer" -Value $User $ReturnedObj | Add-Member NoteProperty -Name "Datenbank" -Value $Datenbank.Database $ReturnedObj | Add-Member NoteProperty -Name "Ablaufdatum" -Value $objItem.AccountExpires $AllUsers += $ReturnedObj } } $AllUsers function sendmail([string] $body) { $SmtpClient = new-object system.net.mail.smtpClient $MailMessage = New-Object system.net.mail.mailmessage $SmtpClient.Host = "mail.testing.local" $mailmessage.from = "exchange@testing.local" $mailmessage.To.add("support@testing.local") $mailmessage.Subject = "Disabled Mailbox Report" $mailmessage.Body = $body $MailMessage.IsBodyHtml = $TRUE $smtpclient.Send($mailmessage) } $AllUsers |export-csv $file -NoTypeInformation $body = "Disabled Mailbox report for $date <br><br><br> folgende Mailboxen wurden deaktiviert: " $bodydetail = $AllUsers |sort-object "Nutzer" |convertto-html $body = $body + $bodydetail sendmail $body |
alle Mailboxen weg, was tun?
Man stelle sich vor, von einer Minute zur anderen sind alle Postfächer nicht mehr vorhanden. Das klingt nach dem Supergau, aber es muss nicht immer so schlimm sein, wie es auf den ersten Blick aussieht.
Es kann sein, dass durch ein Bedienfehler oder falsches Skript alle Mailboxen deaktiviert oder getrennt werden, aber in der Datenbank noch vorhanden sind. Leider sind in größeren Umgebungen die Mailboxen anfangs (noch) nicht als deaktiviert sichtbar und man fängt an zu glauben, dass die Mailboxen ganz verloren sind. Das ist bei Exchange aber relativ unwarscheinlich, viel realistischer ist die Warscheinlichkeit, dass die Datenbanktransaktion noch nicht vollständig gelaufen ist. Dabei kann es vorkommen, dass nicht alle Mailboxen als getrennt (disconnect) gekennzeichnet werden. Dies kann mittels dem Cmdlet 'Clean-MailboxDatabase' erzwungen werden. Danach sind alle getrennten Mailboxen in der Datenbank auffindbar und man kann sie wieder verbinden.
Sollten durch irgend einen Fehler alle Mailboxen getrennt werden, so kann man mit folgenden Befehlen den Feierabend retten:
Get-MailboxDatabase | Clean-MailboxDatabase $getback = Get-MailboxStatistics -Server <ServerName> | where { $_.DisconnectDate -ne $null } Enable-Mailbox -Identity $getback.DisplayName -Database $getback.Database
Exchange Log Analyser

Das Microsoft Exchange Team hat in seinem gleichnamigen Blog ein guten Artikel über den ExLogAnalyzer veröffentlicht. Der ExLogAnalyzer ist ein Tool zur Analyse von verschiedene Logfiles (z.B.: Message Tracking Logs) von Exchange 2007 und Exchange 2010, mit dem Auswertungen über Mails und Verbindungen angefertigt werden können, um einmal zu bewerten wie der Emailverkehr eigentlich wirklich aussieht.
Ein Beispiel für die Mailgröße sieht dann so aus:
kostenloses Exchange 2010 Buch
Jaap Wesselius, MVP für Exchange Server, hat ein englisches E-Book für Exchange 2010 herrausgegeben. Wenn man sich registriert kann man es im PDF-Format kostenlos herunterladen:
http://www.red-gate.com/specials/Exchange/esa_exchange2010.htm
