1. 概要
Outlook (classic) を起動したところ、以下のエラーが表示されるようになってしまいました。
サーバーから仕分けルールを読み取り中にエラーが発生しました。
サーバーのルール形式は認識できませんでした。
起動のたびに表示され、実際に仕分けルールも大部分が消えていました。
ただWeb版Outlookを確認すると、(クライアントルール以外は) すべて残っていました。
そこで、Web版に残っているルールをExchange Online PowerShellでエクスポート・インポートすることで復旧させることにしました。
これはその作業記録です。
なお、クライアントルールはサーバに無いので復旧できません。
2. 環境
- Microsoft 365
- Web版Outlook
- Windows版 Outlook Classic
3. 復旧手順
3.1 エクスポート
Exchange Online PowerShellを使用しました。
## モジュール導入
Install-Module ExchangeOnlineManagement -Scope CurrentUser
## 認証
Import-Module ExchangeOnlineManagement
Connect-ExchangeOnline
まずルールが取得できることを確認します。
Get-InboxRule
バックアップ用のディレクトリを作成します。
New-Item -ItemType Directory -Path "$HOME\OutlookRulesBackup" -Force | Out-Null
ルールを変数に保存します。
$rules = Get-InboxRule
念のため、全情報をフルダンプします。
$rules |
Format-List * |
Out-File "$HOME\OutlookRulesBackup\InboxRules-full.txt" -Encoding utf8
最悪手動復旧する可能性もあるので、ルールの詳細をCSVでも保存しておきます。
人目で見て、比較的分かりやすいかな、と。
$rules |
Select-Object Priority,Name,Enabled,Description,StopProcessingRules |
Export-Csv "$HOME\OutlookRulesBackup\InboxRules-summary.csv" `
-NoTypeInformation `
-Encoding UTF8
本命の復旧用としてPowerShellのCLIXML形式で保存します。
$rules |
Export-Clixml "$HOME\OutlookRulesBackup\InboxRules.xml"
以下の3ファイルをバックアップしました。
InboxRules-full.txt
InboxRules-summary.csv
InboxRules.xml
3.2 ルールの削除
Outlook Classicを終了します。
プロセスが完全に停止したのを確認し、「ファイル名を指定して実行」で下記を実行します。
outlook.exe /cleanrules
これでOutlook Classic側だけでなく、Web版Outlookに残っていたルールも削除されます。
Web版の ファイル > 設定 > メール > ルール が空になっているのを確認します。
Exchange Online PowerShellでルールの件数を見たい場合は下記です。
@(Get-InboxRule).Count
3.3 インポート
Export-Clixml で保存したファイルを、そのままOutlookへインポートすることはできません。
Import-Clixml でバックアップを読み込み、New-InboxRule でルールを作り直す必要があります。
ルールに記載されている振り分け先フォルダについては、バックアップにはフォルダ名しか入っていなかったため、実際のフォルダパスとの対応を $folderMap で定義します。
以下のような形です。
$folderMap = @{
"FolderA" = "${upn}:\受信トレイ\FolderA"
"FolderB" = "${upn}:\受信トレイ\ParentFolder\FolderB"
}
実際に使用した復旧スクリプトは以下です。
upnとfolderMapを書き換えてください。
そしたら、長いですが、PowerShellに全文貼り付けてください。
$backupPath = "$HOME\OutlookRulesBackup\InboxRules.xml"
# 最初はtrueでドライランする
$DryRun = $true
$upn = "<メールアドレス>"
$rules = @(
Import-Clixml $backupPath |
Sort-Object { [int]$_.Priority }
)
# 既存ルールがある場合は停止
$currentRules = @(Get-InboxRule)
if ($currentRules.Count -ne 0) {
throw "現在 $($currentRules.Count) 件のルールがあります。復元を中止します。"
}
# バックアップ上のフォルダー名と実際のフォルダーパスを対応させる
$folderMap = @{
"FolderA" = "${upn}:\受信トレイ\FolderA"
"FolderB" = "${upn}:\受信トレイ\ParentFolder\FolderB"
# 必要なフォルダーをすべて記載
}
foreach ($r in $rules) {
$destinationName = [string]$r.MoveToFolder
if (-not $folderMap.ContainsKey($destinationName)) {
throw "移動先フォルダーのマッピングがありません: $destinationName"
}
$params = @{
Name = [string]$r.Name
Priority = [int]$r.Priority
MoveToFolder = $folderMap[$destinationName]
StopProcessingRules = [bool]$r.StopProcessingRules
}
# 送信者アドレス
$v = @(
$r.FromAddressContainsWords |
ForEach-Object { [string]$_ } |
Where-Object { $_ }
)
if ($v.Count -gt 0) {
$params["FromAddressContainsWords"] = $v
}
# 本文
$v = @(
$r.BodyContainsWords |
ForEach-Object { [string]$_ } |
Where-Object { $_ }
)
if ($v.Count -gt 0) {
$params["BodyContainsWords"] = $v
}
# 件名
$v = @(
$r.SubjectContainsWords |
ForEach-Object { [string]$_ } |
Where-Object { $_ }
)
if ($v.Count -gt 0) {
$params["SubjectContainsWords"] = $v
}
# 件名または本文
$v = @(
$r.SubjectOrBodyContainsWords |
ForEach-Object { [string]$_ } |
Where-Object { $_ }
)
if ($v.Count -gt 0) {
$params["SubjectOrBodyContainsWords"] = $v
}
# 自分の名前がToにない
if ([bool]$r.MyNameNotInToBox) {
$params["MyNameNotInToBox"] = $true
}
# 宛先
$sentTo = @()
foreach ($x in @($r.SentTo)) {
$s = [string]$x
if ($s -match '\[SMTP:([^\]]+)\]') {
$sentTo += $Matches[1]
}
elseif ($s) {
$sentTo += $s
}
}
if ($sentTo.Count -gt 0) {
$params["SentTo"] = $sentTo
}
Write-Host ""
Write-Host "Restore: Priority=$($r.Priority) Name=$($r.Name)"
New-InboxRule @params -WhatIf:$DryRun -ErrorAction Stop
}
最初は、
$DryRun = $true
で実行し、すべて以下のように WhatIf が表示されることを確認します。
Restore: Priority=1 Name=Rule1
WhatIf: 受信トレイのルール Id を作成しています...
Restore: Priority=2 Name=Rule2
WhatIf: 受信トレイのルール Id を作成しています...
...
問題なければ、
$DryRun = $false
へ変更して再実行します。
復旧後に件数を確認します。
@(Get-InboxRule).Count
各ルールの状態も確認します。
Get-InboxRule |
Format-Table Priority,Name,Enabled,InError,IsValid -AutoSize
全ルールで以下になっていることを確認します。
Enabled : True
InError : False
IsValid : True
Web版Outlookでもルールが戻っていることを確認します。
最後にOutlook Classicを起動し、起動時のエラーが出なくなったことと、仕分けルールが動くことを確認して復旧完了です。
4. 教訓
今回は仕分けルールを変更した、次の起動でエラーに遭遇しました。
仕分けルールの変更前には、バックアップを取りましょう。
Outlookで取得したバックアップ (.rwz) があれば、ファイルをインポートするだけで復旧できるはずです。