Класичний сценарій понеділкового ранку
Ви щойно завершили IMAP-міграцію на Exchange Online. Batch-завдання завершилося без помилок у центрі адміністрування Exchange, скриньки синхронізовані, користувачі можуть підключатися. У п'ятницю ввечері ви закриваєте ноутбук із відчуттям виконаної роботи.
У понеділок вранці починають надходити заявки. "Всі мої листи датовані п'ятницею." "Моя папка Вхідні стала непридатною." "Зникли старі листи." Насправді нічого не зникло: листи на місці, але Outlook відображає їх із датою міграції замість оригінальної дати відправлення. Лист із 2019 року з'являється з датою минулої п'ятниці. Результат: вся скринька виглядає так, ніби містить лише нещодавні повідомлення.
Це один із найбільш неприємних наслідків IMAP-міграції на Exchange Online, і Microsoft його майже не документує.
Чому міграція через EAC псує дати
Коли Ви використовуєте центр адміністрування Exchange (EAC) для налаштування IMAP-міграції з локального сервера (Dovecot, Courier, Cyrus, UW-IMAP тощо), Exchange Online підключається до вихідного сервера через IMAP, отримує повідомлення та вставляє їх у цільові скриньки через власний внутрішній транспортний pipeline.
Саме тут і виникає проблема.
Кожен лист, який проходить через транспортний pipeline Exchange, автоматично отримує заголовок Received: із позначкою часу. Це стандартна поведінка SMTP і IMAP-серверів протягом десятиліть: кожен сервер, який торкається повідомлення, додає свій часовий штамп. Проблема в тому, що Outlook (зокрема Outlook для Windows у нових версіях) використовує найновіший заголовок Received: як орієнтир для відображення, коли інші метадані неоднозначні.
Оригінальний заголовок Date: (той, що вказує, коли лист насправді було надіслано, відповідно до RFC 2822) завжди присутній у повідомленні. Його не видалено. Але він опиняється "у тіні" нового заголовка Received:, доданого Exchange під час вставки.
Паралельно INTERNALDATE у IMAP (метадані, які IMAP-сервери використовують для внутрішнього датування повідомлень і які керують сортуванням у більшості клієнтів) встановлюється на дату вставки, а не на оригінальну дату листа. Exchange Online не має жодного вбудованого механізму збереження INTERNALDATE із вихідного сервера під час пакетної міграції через EAC.
EAC проти сторонніх інструментів: важлива різниця
Тут треба розрізняти дві ситуації. Із такими інструментами, як BitTitan MigrationWiz або CloudM Migrate, проблема теж існує, але ці інструменти іноді мають параметри конфігурації (частково задокументовані, часто приховані в розширених налаштуваннях), які намагаються зберегти певні метадані дати.
Нативна міграція через EAC не надає жодних подібних параметрів. Microsoft не надає налаштування для керування збереженням INTERNALDATE у pipeline пакетної міграції. Це чорна скринька: Ви налаштовуєте batch, запускаєте його, а Exchange робить із повідомленнями що хоче. А робить він одне й те саме систематично: датує повідомлення моментом їх вставки.
(До речі, якщо Вам доводилося читати сирі заголовки листа, мігрованого через EAC, Ви знаєте, що заголовок Received:, доданий Exchange, впізнається з першого погляду: він містить посилання на внутрішні сервери Microsoft на кшталт *.protection.outlook.com або *.prod.exchangelabs.com із позначкою часу, що точно збігається з вікном міграції.)
Чому повторне створення batch нічого не змінить
Інстинктивна реакція багатьох IT-адміністраторів така: "Якщо видалити мігровані скриньки і перезапустити batch із нуля, може цього разу дати будуть правильними."
Це зрозуміло. Але це не працює.
Проблема не в конфігурації batch і не в параметрі, який забули встановити. Вона закладена в архітектурі самого транспортного pipeline Exchange, який однаковий при кожній міграції. Повторний запуск дасть точно такий самий результат: ті самі заголовки Received: із новою датою міграції та ті самі неправильні INTERNALDATE. Ви витратите час, а користувачів потурбують вдруге, без жодного сенсу.
Деякі адміністратори намагаються також змінити параметри сортування в Outlook («сортувати за датою відправлення» замість «дати отримання»). Сортування за датою відправлення не є рішенням. Це пластир. Заголовок Date: та INTERNALDATE залишаються неправильними для клієнтів, які не мають такого налаштування, для OWA, для Outlook Mobile і для будь-якого стороннього додатка, що звертається до скриньки через IMAP або EWS.
Що насправді відбувається в заголовках
Ось спрощений приклад того, що містить лист після міграції через EAC. Оригінальний заголовок:
Date: Thu, 14 Mar 2019 09:23:11 +0100
From: alice@olddomain.com
Subject: Звіт Q1 2019
Після міграції на початку ланцюга заголовків з'являється щось на кшталт:
Received: from DB7PR0101MB3304.eurprd01.prod.exchangelabs.com
by DB7PR0101MB3305.eurprd01.prod.exchangelabs.com
with HTTPS; Fri, 7 Jun 2024 22:41:03 +0000
Outlook бачить цей заголовок Received: першим (він додається на початку блоку заголовків), інтерпретує його як найновішу дату обробки повідомлення та відображає як дату отримання. Оригінальний заголовок Date: із 2019 року залишається на місці, у кількох рядках нижче. Але Outlook не використовує його для відображення в списку повідомлень.
Якщо бути точним: поведінка дещо відрізняється залежно від версії Outlook. Версії після 2021 року (і особливо новий Outlook для Windows, що розгортається з кінця 2023 року) особливо чутливі до цієї проблеми, оскільки вони більше покладаються на метадані Exchange Graph, ніж на сирий заголовок Date:. Тобто міграції, які не спричиняли помітних проблем в Outlook 2016, тепер можуть давати збої в новому Outlook.
Кого це стосується насправді
Найпоширеніші вихідні IMAP-сервери в таких міграціях - Dovecot (широко розповсюджений у Linux/cPanel-середовищах) та Courier. Обидва надають INTERNALDATE через IMAP, яку EAC не зберігає. Якщо Ви мігруєте з локального Exchange на Exchange Online (гібридна міграція або cutover), поведінка інша, бо Microsoft використовує внутрішній транспортний протокол (MAPI/EWS), який краще зберігає метадані. Проблемою є саме загальна IMAP-міграція через EAC.
Найбільше страждають користувачі зі скриньками із тривалою історією (5 років і більше) та великим обсягом повідомлень. Користувач із 300 листами швидко впорається. А комерційний директор із 12 000 листів, відсортованих за датою, на які він щодня спирається для пошуку переписки з клієнтами, просто паралізований.
Чому власний скрипт тут - погана ідея
Деякі IT-адміністратори, які розуміють технічну сторону проблеми, спокушаються написати скрипт PowerShell або Python для ручного виправлення заголовків. Базова ідея може здатися простою, щойно механізм виявлено. Але реальність виправлення в продакшні - зовсім інша справа.
По-перше, граничні випадки. Листи, підписані S/MIME, і повідомлення, зашифровані PGP, мають структуру, яка не терпить змін заголовків без анулювання підпису. Повідомлення multipart/alternative із неправильно сформованими MIME-межами (типово для старих серверів Courier) можуть бути пошкоджені скриптом, який модифікує повідомлення без коректного відновлення структури. Заголовки non-ASCII, закодовані відповідно до RFC 2047 (імена відправників із символами кирилиці або японськими символами, наприклад), - класичне джерело помилок.
По-друге, обсяг. Скрипт, який працює на 50 тестових листах у середовищі розробки, не справляється з обмеженнями швидкості API Exchange Online у продакшні. Помилка 429 Too Many Requests о 2-й ночі під час обробки batch із 8 000 повідомлень без механізму відновлення - це безсонна ніч і потенційно дублікати або втрачені листи.
І головне: як перевірити, що кожен виправлений лист є цілим? Що жоден вкладений файл не обрізано, жодна гілка обговорення не зламана, що мітки та папки збережено? Без механізму індивідуальної перевірки залишається лише сподіватися, що все пройшло добре.
Виправлення дат після міграції - це задача, що виглядає як 50 рядків коду, але для надійної роботи в продакшні вимагає тисяч.
Що Redate.io робить інакше
Redate.io підключається до Exchange Online через API Microsoft 365 (Azure Active Directory, дозволи делегування на рівні тенанту) і сканує відповідні скриньки для виявлення листів, метадані дат яких були пошкоджені під час міграції. Цей етап сканування безкоштовний і дає точне уявлення про масштаб проблеми: кількість уражених повідомлень, задіяні скриньки, діапазон пошкоджених дат.
Власний механізм виправлення Redate.io обробляє кожен лист окремо через багатоетапний pipeline аналізу, що включає зіставлення шаблонів із сигнатурами відомих інструментів міграції (зокрема транспортного pipeline Exchange Online), перевірку відповідності RFC та верифікацію структурної цілісності повідомлення до і після виправлення. Підписані S/MIME листи, складні MIME-структури, нестандартні кодування - все це обробляється спеціальними шляхами.
Кожне виправлене повідомлення перевіряється індивідуально. Оригінали зберігаються у видимій резервній папці протягом 30 днів. Якщо з якимось конкретним повідомленням щось не так, його не змінюють: Redate.io повідомляє про аномалію замість того, щоб ризикувати пошкодженням.
Тарифікація базується на обсязі, у вигляді одноразового платежу за скриньку. Без підписки, без регулярних платежів. Проблему виправляють один раз - і все.
Для міграцій Exchange Online зокрема, Redate.io підтримує підключення через дозволи додатка Azure AD (без необхідності створювати окремі облікові дані для кожної скриньки), що значно спрощує обробку великих парків скриньок для IT-адміністратора або MSP.
Якщо Ви обслуговуєте кількох клієнтів, які зазнали такого типу міграції, ознайомтеся також із повним посібником із виправлення дат після міграції Microsoft 365 для огляду різних сценаріїв.
Листи на місці, оригінальні дати - теж. Запустіть безкоштовне сканування на Redate.io, щоб побачити точну кількість уражених повідомлень у Ваших скриньках Exchange Online - перш ніж вирішувати, що робити далі.