Симптом, знакомый каждому
Вы только что завершили миграцию IMAP в Microsoft 365 или Google Workspace. В понедельник утром посыпались заявки: «У всех писем одна дата», «История сломана», «Я ничего не могу найти в почтовом ящике». Открываете Outlook, и действительно: тысячи писем показывают дату прошлых выходных. Не дату отправки. Дату, когда проходила миграция.
Это не баг Outlook. Это прямое следствие того, как работает протокол IMAP и инструменты миграции. Но чтобы понять, почему так происходит, нужно заглянуть под капот.
Три даты в одном письме
Письмо устроено сложнее, чем кажется. Заголовки, тело сообщения, вложения... и несколько разных временных меток, которые существуют одновременно. (Если Вы когда-нибудь пробовали читать сырые заголовки письма, знаете: это не пляжное чтиво.)
Заголовок Date: (RFC 2822)
Это дата, которую отправитель поставил в момент отправки. Определена в RFC 2822 и выглядит примерно так:
Date: Tue, 14 Mar 2023 09:42:17 +0100
Этот заголовок вписан в тело сообщения намертво. Он не меняется никогда, если только кто-то не редактирует сырое содержимое письма. Это и есть «дата отправки» в строгом смысле слова.
Заголовок Received: (добавляется на каждом сетевом узле)
Каждый сервер, через который проходит письмо в пути, добавляет заголовок Received: в начало сообщения со своей датой. Письмо, прошедшее через три сервера, накапливает три таких заголовка. Самый свежий всегда первый. Выглядит это так:
Received: from mail.example.com ([93.184.216.34])
by mx.google.com with ESMTPS
id x1234abcd.2024.06.15.08.31.02;
Sat, 15 Jun 2024 08:31:02 +0000 (UTC)
В результате, когда инструмент миграции вроде BitTitan MigrationWiz, CloudM, imapsync или GSMMO переносит письмо с исходного сервера на целевой, он тоже ведёт себя как «сетевой узел». Он вставляет новый заголовок Received: в самый верх цепочки с датой и временем миграции.
INTERNALDATE в IMAP
Это третья дата, и именно она создаёт проблему. INTERNALDATE, это метаданные на стороне IMAP-сервера, не зависящие от содержимого письма. Они показывают, когда письмо было доставлено (или вставлено) в почтовый ящик. Когда инструмент миграции вставляет письмо, именно он решает, какое значение присвоить INTERNALDATE. И во многих случаях инструменты используют текущее время миграции. Не оригинальную дату.
Вот здесь всё и ломается.
Почему Outlook показывает дату миграции
Outlook использует INTERNALDATE для отображения колонки «Получено». Это поведение по умолчанию, и оно соответствует спецификации IMAP: INTERNALDATE должна представлять дату получения в ящике. В нормальном потоке (когда приходит настоящее письмо) INTERNALDATE близка к дате в заголовке Date:. Обе согласованы между собой.
После неудачной миграции INTERNALDATE всех импортированных писем указывает на ночь с 14 на 15 июня 2024 года (или какую бы дату миграции ни была). Outlook читает это значение, отображает его в колонке «Получено», и результат катастрофический: 45 000 писем как будто пришли в один вечер.
Если быть точным, первый заголовок Received: (самый свежий в цепочке) тоже влияет на отображение в некоторых конфигурациях. Но INTERNALDATE остаётся главным определяющим фактором для колонки «Получено» в Outlook в режиме синхронизации по IMAP.
Обходной путь «Добавить колонку Отправлено» в Outlook
Первое, что делают большинство IT-администраторов при обнаружении проблемы, это ищут обходное решение на стороне клиента. Оно существует, это правда.
В Outlook можно изменить отображение колонок в папке: заменить (или дополнить) колонку «Получено» колонкой «Дата» или «Отправлено». Колонка «Дата» читает непосредственно заголовок Date: сообщения, а не INTERNALDATE. Поскольку заголовок Date: не был затронут миграцией, оригинальные даты снова появятся.
В настольном Outlook (версия Microsoft 365) это делается так: правый клик на заголовке колонки в списке сообщений, «Параметры просмотра», затем изменить колонки, убрав «Получено» и добавив «Дата». Это можно развернуть через GPO для массового применения.
Хорошо. На бумаге это решает визуальную проблему. На практике, это пластырь на артериальное кровотечение.
Конкретные ограничения этого обходного пути
Мобильные и веб-клиенты
Outlook для iOS, Android и Outlook Web App (OWA) не предлагают тех же возможностей кастомизации. Изменение вида, развёрнутое на Windows-машинах, не распространяется на них. Пользователи, читающие почту с телефона, продолжат видеть дату миграции. А в компании среднего размера это, скорее всего, половина сотрудников.
Поиск
Поиск в Outlook использует индекс Windows Search (или индекс Exchange/Microsoft 365 на стороне сервера). Этот индекс строится на основе INTERNALDATE, а не заголовка Date:. Если пользователь ищет «письма за январь 2022 года», поиск вернёт письма, INTERNALDATE которых относится к январю 2022. Не те, у которых заголовок Date: указывает на январь 2022. Итог: старые письма перестают появляться в фильтрах по дате. Изменение отображаемой колонки этого не исправит.
Правила обработки почты
Правила Outlook («если письмо получено до...», «если письмо получено после...») тоже используют INTERNALDATE. Правило сортировки или архивирования, основанное на диапазонах дат, перестанет корректно работать после миграции, если INTERNALDATE не исправлена.
Соответствие требованиям и eDiscovery
Это, пожалуй, самый серьёзный момент. Инструменты контроля соответствия, юридического архивирования и eDiscovery (например, Microsoft Purview) используют INTERNALDATE как опорную дату для юридических запросов. Если Ваша компания обязана соблюдать требования по хранению данных или отвечать на запросы об электронном раскрытии информации (что в российской практике актуально при работе с иностранными партнёрами или требованиями регуляторов), повреждённые значения INTERNALDATE могут создать серьёзные юридические проблемы. Запрос «все письма за такой-то период» просто не вернёт нужные результаты.
Сторонние инструменты
CRM-системы, тикет-системы, архиваторы... всё, что подключается к почтовому серверу через IMAP или API Microsoft 365/Google Workspace, читает INTERNALDATE. Изменение вида в Outlook для них не меняет ничего.
Единственное настоящее решение: исправление на уровне сервера
Сортировка по дате отправки в Outlook, это не решение. Это пластырь. Настоящее исправление должно затрагивать метаданные на сервере, а не отображение на стороне клиента.
Конкретно это означает исправление INTERNALDATE каждого письма так, чтобы она соответствовала оригинальной дате из заголовка Date:. Оригинальный заголовок Date: всегда присутствует в сообщении (миграция его не удалила), поэтому исправление технически возможно. Именно там хранится информация о реальной дате.
В Google Workspace API Gmail открывает доступ к параметру internalDate, который позволяет напрямую работать с этими метаданными. В Microsoft 365 механизм отличается, но ожидаемый результат тот же. На стандартном IMAP-сервере спецификация предусматривает, что дата может быть задана при вставке сообщения.
На практике провести эту операцию на десятках тысяч писем в продакшне, без потери данных, без дублей, без нарушения цепочек переписки и меток, с учётом крайних случаев (сообщения с подписью S/MIME, сложные структуры MIME, кодировки non-ASCII по RFC 2047, объёмные вложения)... это совсем другая история. Скрипт, который работает на 50 тестовых письмах, не выдержит боевого ящика с 40 000 сообщений. Обработка ошибок 429 (превышение квоты API), таймауты сети в 2 часа ночи, письма с уже повреждённой после миграции MIME-структурой... всё это требует серьёзной инженерной работы.
Именно это и делает Redate.io. Проприетарный движок коррекции анализирует цепочку заголовков каждого письма, определяет надёжную оригинальную дату и применяет точечное исправление метаданных без изменения содержимого сообщения. Каждое исправленное письмо проверяется индивидуально. Оригиналы сохраняются в резервной папке 30 дней, что даёт возможность отката в любой момент. Ни один самодельный скрипт такого не предложит.
Определить инструмент миграции, который виноват
Проблема проявляется одинаково вне зависимости от источника миграции, но детали варьируются в зависимости от использованного инструмента. BitTitan MigrationWiz, CloudM, imapsync и GSMMO, у каждого своя сигнатура в заголовках Received:, которые они вставляют. Конвейер анализа Redate.io поддерживает базу из сотен сигнатур известных инструментов миграции, чтобы отличить заголовок миграции от остальной цепочки легитимного транзита.
Если Вы не знаете, какой инструмент использовался при миграции (такое бывает, особенно когда принимаете инфраструктуру от другого MSP), бесплатное сканирование Redate.io определит затронутые ящики и даст оценку объёма до начала каких-либо действий.
Для конкретных сценариев есть подробные руководства: исправление дат imapsync в Outlook, исправление дат BitTitan в Outlook и исправление дат CloudM в Outlook.
Что делать сейчас
Если Вы читаете эту статью после миграции, хорошая новость состоит в том, что оригинальный заголовок Date: нетронут в каждом Вашем письме. Информация о реальной дате есть, она присутствует в каждом сообщении. Проблема в метаданных, а не в содержимом. А метаданные поддаются исправлению.
Также рекомендуем статью IMAP INTERNALDATE: почему ломаются даты для более глубокого погружения в механику проблемы, или полное руководство по неправильным датам в Outlook после миграции для общего обзора возможных ситуаций.
Готовы исправить даты в своих почтовых ящиках? Запустите бесплатное сканирование на Redate.io, чтобы определить затронутые письма и оценить объём до начала исправления.