PSTインポート後にメール日付が今日になる原因

1 min

症状:インポートしたメールが全て今日の日付になっている

OutlookでPSTファイルのインポートが完了しました。プログレスバーは100%に達し、エラーも出ていません。ところが受信トレイを開いてみると...インポートした全てのメールに今日の日付が表示されています。2019年のメッセージも、2021年のメッセージも、5年前のアーカイブも、全てインポートした日付になっているのです。

これは表示のバグではありません。タイムゾーンの問題でもありません。IMAPがメタデータを管理する仕組みに起因する、完全にドキュメント化された動作です。とはいえ、古いメールを日付で探したい人にとっては深刻な問題です。

ローカルPSTとIMAP:全く異なる二つの世界

日付が壊れる理由を説明する前に、PSTファイルが日付管理という観点でどういうものかを理解する必要があります。

PST(Personal Storage Table)ファイルはMicrosoft独自のフォーマットです。送信日、受信日、添付ファイル、カテゴリ、既読フラグなど、メールのメタデータを完全な形で保存します。これらのメタデータはOutlookが直接管理するもので、メールプロトコルとは無関係です。サーバーに接続せずにOutlookでPSTを開く場合、表示される日付はPSTファイル内部のフィールドから直接取得されます。ここまでは問題ありません。

問題が起きるのは、このコンテンツをIMAP対応のメールサーバーに転送しようとしたときです。Microsoft 365であれGoogle Workspaceであれ、一般的なホスティングサービスであれ同じです。PST の世界を出てIMAP の世界に入った瞬間、ルールが根本から変わります。

IMAP APPENDとINTERNALDATE:問題の核心

IMAPでは、サーバーに保存された各メッセージには二種類の日付データが存在します。

  • メッセージ本体に含まれるDate:ヘッダー(RFC 2822)。送信者がメッセージに記した日付です。
  • INTERNALDATE:IMAPサーバーが管理するメタデータで、メッセージがサーバーに保存された時刻を表します。Outlookが「受信日時」ビューでメッセージを並べ替えるのに使う値がこれです。

(メールの生のヘッダーを読もうとしたことがある方なら分かると思いますが、あれは砂浜で読む小説とはかなり趣が違います。それでも、全てはそこで起きているのです。)

通常のメール受信時、メールサーバーは受信した瞬間のタイムスタンプを自動的にINTERNALDATEに設定します。そのためOutlookに表示される日付は、実際にメッセージを受信した日時と一致します。

OutlookがPSTファイルをIMAPメールボックスにインポートする際、IMAP APPENDコマンドを使って各メッセージをサーバーに送信します。IMAPの仕様では、APPEND時に明示的なINTERNALDATEを指定できます。しかしOutlookはそれをしません。INTERNALDATEを指定せずにメッセージを送信するため、IMAPサーバーはデフォルトのルールを適用します。つまりINTERNALDATEをその瞬間、すなわちインポートした時刻に設定します。

結果:8,000件インポートしたら、8,000件全てに今日の日付がつきます。

なぜOutlookはこのように動作するのか

これはMicrosoftの見落としではありません。当時は合理的に見えた実装上の選択です。PSTインポートの本来のユースケースでは、ユーザーがメッセージをローカルにアーカイブして現在のメールボックスに「インポート」するというものでした。並べ替えに使う日付としては元の受信日時が適切なはずですが、Microsoftはインポート操作時にINTERNALDATEを引き継がない設計を選びました。

正確に言うと、この動作はOutlookのネイティブインポートウィザード(「ファイル」>「開く/エクスポート」>「インポート/エクスポート」)を使った場合に該当します。サードパーティ製ツールやExchange管理センター経由の移行など、別のインポート方法ではIMAP APPENDの実装次第で動作が異なる場合があります。

この動作はMicrosoftのフォーラムで何年も前から報告されています。Outlook 2016でも変わらず、Outlook 2019でも変わらず、現在のMicrosoft 365バージョンでも同じです。今日PSTをインポートしても、2015年と全く同じ問題に直面します。

通常のIMAP移行との違い

ここが興味深いところです。PSTインポートは日付が壊れる通常のIMAP移行と似た結果をもたらしますが、メカニズムが異なります。

BitTitan MigrationWizやimapsyncを使った典型的なIMAP移行では、メールが送信元IMAPサーバーから送信先IMAPサーバーに転送されます。移行ツールはメッセージを取得してIMAP APPENDで再挿入します。INTERNALDATEを正しく保持するツールもあれば、そうでないものもあります。いずれにせよ、移行時に追加されたReceived:ヘッダーが存在し、INTERNALDATEとは別にOutlookの表示に影響することがあります。

PSTインポートの場合、仕組みはよりシンプルです。移行時のReceived:ヘッダーは追加されません(PSTファイルは中間メールサーバーを経由しないためです)。ただINTERNALDATEが正しい値に設定されないだけです。見た目の結果は同じですが、根本的な原因は微妙に異なります。

この違いは修正方法にも直接影響します。IMAP移行とPSTインポートでは、採るべきアプローチが若干異なります。INTERNALDATEが日付を壊す理由も合わせてご覧ください。

Outlookの表示オプションでは何も解決しない

問題を発見したときの典型的な反応は、Outlookの設定を探し回ることです。確かに「受信日時」ではなく「日付」で並べ替えるオプションがあり、一見有望に見えます。

送信日での並べ替えは解決策ではありません。応急処置にすぎません。

理由はこうです。「日付」列(メッセージのDate:ヘッダー、つまり元の日付に対応)に切り替えても、いくつかの問題が残ります。

  • OutlookのインデックスはINTERNALDATEを使います。「2020年1月のメール」を検索しても、そのINTERNALDATEがインポートした日付になっているため、インポートした2020年1月のメールは検索結果に出てきません。
  • Outlookインターフェースの「今日」「今週」「今月」フォルダーはINTERNALDATEに基づいており、Date:ヘッダーではありません。
  • Webインターフェース(Outlook Web App、Gmail)やモバイルクライアントでは、表示される日付と並べ替えの動作はほぼ常にサーバーのINTERNALDATEに依存します。
  • 受信日時に適用される自動ルールやフィルターが正しく機能しません。

要するに、表示を変更しても、特定のクライアントで特定のユーザーの特定の設定での見え方が変わるだけです。根本的な問題は修正されません。

OSTの再同期も意味がない

もう一つよくある対処法として、OSTキャッシュを削除してサーバーから完全再同期を強制するというものがあります。問題がサーバーではなくOutlookのローカルキャッシュにあるかもしれないという発想です。

これは見当違いです。OSTファイルはIMAPサーバーの状態を反映するローカルキャッシュです。サーバー上のINTERNALDATEが間違っていれば、再同期後のOSTも同じく間違った値になります。OSTを削除しても、Exchange OnlineやGoogle Workspace上に保存されたデータは変わりません。権威があるのはサーバーです。

日付を修正する唯一の方法は、サーバー側でメッセージごとにメタデータを修正することです。そしてこれを手作業でやろうとすると、一気に複雑になります。

規模の問題:1件は簡単、15,000件は別の話

仕組みを理解した上で、各メッセージのDate:ヘッダーを読み取ってINTERNALDATEを修正するスクリプトを書けばよいと考えるかもしれません。問題を理解することと、15,000件のメールを1件もなくさずに修正することは、全く別の話です。

現場での実態をいくつか挙げます。

  • Microsoft GraphとGmail APIにはレートリミットがあります。単純なスクリプトは429 Too Many Requestsエラーを引き起こし、修正の途中で処理が止まります。どのメールが処理済みでどれが未処理か分からないまま、中途半端に修正されたメールボックスが残ります。
  • PST内のメールの中には、Date:ヘッダーが不正だったり欠落しているものがあります。こうしたエッジケースを処理しないスクリプトは、該当メッセージを破損させるか、黙って読み飛ばします。
  • 署名済み(S/MIME)または暗号化(PGP)されたメールには、追加の整合性制約があります。メタデータを不用意に変更すると、暗号署名が無効になる可能性があります。
  • 複雑なMIMEバウンダリを持つmultipart/alternative構造は、変更操作に対して予期しない反応を示すことがあります。
  • ロールバック機能がありません。処理の途中で問題が起きた場合、元の状態に戻す方法はありません。

10件のテストメールで動くスクリプトは、50,000件のメッセージを抱える本番メールボックスでは動きません。去年、40GBのPSTアーカイブを持つあるクライアントがStack Overflowで見つけたPythonスクリプトで修正を試みました。結果:3,000件のメール重複、200件の添付ファイルが開けない状態、そして2週間の手作業によるクリーンアップ作業が発生しました。

Redate.ioがこのケースで行うこと

リデイト(Redate.io)は対象メールボックス内の各メッセージのメタデータを解析し、日付が正しくないメール(PSTインポートによるものを含む)を特定します。そして独自のプロプライエタリエンジンによって修正を適用します。マルチステージ解析パイプラインが各メッセージのヘッダーチェーンを検査し、RFCへの準拠を検証しながら元の日付を抽出して、メッセージコンテンツを変更することなく対象のメタデータのみを修正します。

修正された各メールは個別に検証されます。元のメッセージは最終的な変更が行われる前に、30日間、表示されるバックアップフォルダーに保存されます。修正は主要な3つのプラットフォームに対応しています。Microsoft 365(Azure AD経由)、Google Workspace(ドメイン委任経由)、そして一般的なホスティング向けの直接IMAPです。

最初のスキャンは無料です。何件のメールが影響を受けているか、不正な日付の分布がどうなっているかを、何かを決断する前に正確に確認できます。

関連記事:

PSTのインポートでメールの日付が全て上書きされてしまいましたか? Redate.ioで無料スキャンを実行して、対処する前に問題の規模を把握しましょう。

関連記事