Три даты внутри каждого письма
Каждое письмо на IMAP-сервере несёт как минимум три различных значения даты. Понимание того, как они работают и как почтовые клиенты выбирают, какую показывать, это ключ к пониманию, почему миграция ломает даты. Эта статья - углублённый технический разбор системы дат IMAP для IT-администраторов и всех, кто хочет понять корневую причину пост-миграционных проблем с датами.
1. Заголовок "Date" RFC 2822
Заголовок "Date" определён в RFC 2822 (формат интернет-сообщений). Он устанавливается почтовым клиентом отправителя в момент составления и отправки. Этот заголовок является частью тела сообщения, он путешествует с письмом и никогда не изменяется серверами на пути доставки. Типичный заголовок Date:
Date: Mon, 15 Jan 2024 09:32:17 +0100
Заголовок Date представляет "дату отправки". Это самая надёжная дата, так как устанавливается однократно и не изменяется. Однако он отражает часы отправителя, которые могут быть настроены неправильно. В редких случаях заголовок Date может полностью отсутствовать (особенно в автоматических системных уведомлениях или некорректных сообщениях).
2. IMAP INTERNALDATE
INTERNALDATE определена в RFC 3501 (протокол IMAP4rev1). Это серверное значение метаданных, представляющее дату и время доставки сообщения на сервер. В отличие от заголовка Date, INTERNALDATE не является частью самого письма. Она хранится отдельно IMAP-сервером как метаданные.
При нормальной доставке (не миграция) IMAP-сервер устанавливает INTERNALDATE на текущее время доставки. Это значение близко к заголовку Date, обычно с разницей в секунды или минуты. Почтовые клиенты часто используют INTERNALDATE как "дату получения", так как она отражает реальный момент поступления на сервер.
А теперь становится интересно. Когда сообщение вставляется командой IMAP APPEND (что используют инструменты миграции), APPEND позволяет клиенту явно указать INTERNALDATE. Хорошие инструменты миграции используют эту возможность для сохранения исходной INTERNALDATE с сервера-источника. Но даже при корректной INTERNALDATE проблема с "Received" (описанная ниже) может всё равно перекрыть отображаемую дату во многих клиентах.
3. Цепочка заголовков "Received"
Каждый раз, когда письмо проходит через почтовый сервер, тот добавляет заголовок "Received" в начало сообщения. Это создаёт цепочку Received, документирующую путь от отправителя к получателю. Самый верхний (первый) показывает последний обработавший сервер, самый нижний - первый.
Обычное письмо может иметь 3-6 заголовков Received, документируя маршрут от исходящего сервера отправителя через ретрансляторы до входящего сервера получателя. Каждый включает метку времени. Упрощённый пример:
Received: from mx.recipient.com; Mon, 15 Jan 2024 09:32:22 +0000
Received: from relay.sender.com; Mon, 15 Jan 2024 09:32:20 +0000
Received: from smtp.sender.com; Mon, 15 Jan 2024 09:32:18 +0000
Date: Mon, 15 Jan 2024 09:32:17 +0100
Как клиенты выбирают, какую дату показать
Outlook (десктоп, веб, мобильный)
Microsoft Outlook использует комбинацию INTERNALDATE и самого свежего "Received" для определения "Получено". На практике Outlook приоритизирует метку самого верхнего Received для колонки "Получено". Колонка "Отправлено" использует заголовок Date. Так как Outlook по умолчанию сортирует по "Получено", именно метку из Received пользователи видят первой.
Apple Mail
Apple Mail на macOS и iOS использует преимущественно IMAP INTERNALDATE. Если INTERNALDATE корректно сохранена при миграции, Apple Mail может показать правильную дату, но только если INTERNALDATE была явно установлена при APPEND. Если инструмент этого не сделал, сервер использует время вставки (дату миграции). Подробности для Apple Mail см. Apple Mail: неправильная дата после миграции.
Thunderbird
Mozilla Thunderbird предлагает наибольшую гибкость. Он может показывать и "Дату" (из заголовка Date), и "Получено" (из Received). По умолчанию показывает значение Date, поэтому даты могут выглядеть правильно даже когда в Outlook они неправильные. Колонка "Получено" в Thunderbird всегда показывает дату миграции. См. Thunderbird: неправильная дата после миграции.
Веб-интерфейс Gmail
Gmail веб использует заголовок Date для основного отображения. Это значит, что Gmail веб часто показывает корректные даты даже после миграции. Но IMAP INTERNALDATE на сервере Gmail всё равно неправильна, что влияет на каждый IMAP-клиент, подключённый к аккаунту. Разница между Gmail веб и Outlook или Apple Mail - частый источник путаницы, съедающий много часов на диагностику у администраторов.
Почему IMAP APPEND ломает даты
Что происходит при миграции
Когда инструмент миграции переносит письмо с Сервера А на Сервер Б, он подключается к Серверу А через IMAP, скачивает сырое сообщение, затем подключается к Серверу Б и вставляет через APPEND. При вставке Сервер Б обрабатывает входящее сообщение и добавляет новый Received с текущей меткой: датой миграции. Это стандартное поведение IMAP по протоколу. Сервер обрабатывает каждый APPEND как новую доставку.
Результат: загрязнённая цепочка заголовков
После миграции заголовки Received выглядят так:
Received: from migration-tool; Fri, 11 Apr 2025 14:22:08 +0000
Received: from mx.recipient.com; Mon, 15 Jan 2024 09:32:22 +0000
Received: from relay.sender.com; Mon, 15 Jan 2024 09:32:20 +0000
Date: Mon, 15 Jan 2024 09:32:17 +0100
Received от инструмента миграции теперь является самым верхним. Любой клиент, использующий самый верхний Received для определения даты (Outlook особенно), покажет "11 апреля 2025" вместо "15 января 2024". Оригинальный Date и оригинальные Received по-прежнему целы ниже, но уже не на позиции, которую клиенты приоритизируют.
Даже хорошая обработка INTERNALDATE не предотвращает это
Некоторые инструменты корректно устанавливают INTERNALDATE при APPEND. Например, imapsync явно сохраняет INTERNALDATE с источника. Но Received добавляется целевым сервером, а не инструментом миграции. Инструмент не контролирует это поведение. Даже при идеальном сохранении INTERNALDATE самый верхний Received содержит дату миграции, и клиенты вроде Outlook показывают неправильную дату.
Так что же конкретно с этим делать?
Какие инструменты добавляют заголовки Received
Все инструменты IMAP-миграции вызывают эту проблему, так как Received добавляется целевым сервером, а не инструментом. Содержание добавленного заголовка различается.
BitTitan MigrationWiz добавляет Received с "mx.migrationwiz.com". CloudM Migrate добавляет заголовки с "cloudm.io". imapsync вызывает общий Received от целевого сервера. GSMMO добавляет заголовки с "gmailapi.google.com".
Исправление: восстановление правильных дат
Хорошая новость: правильная информация о дате по-прежнему существует в каждом письме. Оригинальный Date не тронут. Оригинальные Received не тронуты. Проблема в том, что загрязняющий заголовок сидит поверх них.
Проприетарный движок коррекции Redate.io анализирует полную цепочку заголовков каждого затронутого письма, сопоставляя сигнатуры сотен профилей миграции для точного определения заголовков, требующих коррекции. Многоступенчатый конвейер обрабатывает краевые случаи: подписи S/MIME, шифрование PGP, multipart/alternative, Content-Transfer-Encoding, не-ASCII заголовки (RFC 2047), крупные вложения и повреждённые MIME-границы.
После коррекции каждое письмо проходит верификацию целостности: структура, содержимое и вложения сохранены без изменений. Оригиналы хранятся в видимой папке бэкапа 30 дней.
Можно ли написать скрипт самостоятельно? Технически да. Но разница между "работает на 95% писем" и "работает на 100% без единого повреждения" - месяцы разработки. А когда речь о полном ящике, 5% ошибок означают сотни бесшумно повреждённых сообщений без способа проверить, что пошло не так.
Хотите узнать, сколько писем в Вашем ящике с неправильными датами? Запустите бесплатный анализ с Redate.io для мгновенного подсчёта затронутых писем, без оплаты.