Как читать файлы Outlook Express (DBX)Delphi , Интернет и Сети , Почтовый клиент
Автор: Samum Структура файла Сообщения хранятся в таблицах, расположенных друг за другом, по порядку. Каждая таблица состоит из двух частей - заголовка и _входа_. Смещение первой таблицы от начала файла располагается со смещением $30 от начала файла и представляет собой знаковое 32-х битное число (тип integer или longint). Общее же количество записей (т.е. этих самых таблиц) расположено со смещением $C4 от начала файла, и представляет собой число типа integer (longint). Заголовок таблицы содержит количество _входов_, собственное смещение, а так же смещения предыдущей и следующей таблиц (все смещения, разумеется, от начала файла). Для чтения заголовка таблицы я использую такую структуру: Toe5_IndexHeader = record FilePos: longint; {Это смещение структуры, используется для контроля} Unknown1: longint; { ??? } PrevIndex: longint; {Смещение предыдущей таблицы} NextIndex: longint; {Смещение следующей таблицы} Count: longint; {Количество _входов_, реальное количество находится так: count shr 8} Unknown2: longint; { ??? } end; Чтобы получить реальное количество _входов_, значение поля count надо конвертировать . Каждый _вход_ содержит смещение (всегда от начала файла) заголовка письма (Message Header) и позицию другой индексной таблицы (эта таблица используется, чтобы обеспечить поддержку наследования (или связывания) сообщения, то есть любой заголовок сообщения, на который ссылается эта таблица - ребенок текущего сообщения). Вот структура входа: Toe5_IndexItem = record HeaderPos: longint; {Смещение (от начала файла) заголовка письма} ChildIndex: longint; {Смещение (от начала файла) дочерней индексной таблицы} Unknown: longint; end; На мой взгляд, лучшим методом чтения таблиц является рекурсивная функция (см. пример). Заголовок сообщения содержит некоторую информацию, которую Outlook Express использует, чтобы избежать доступа к сообщению, пока в этом нет особой необходимости. Эта структура разделена на три части: заголовок структуры, таблицу параметров типа DWORD и блок данных.
Flags = 16 80: 00000074 81: 00000081 02: 00000000 84: 0002ECA0 05: 00000008 06: 00000025 07: 0000002D 08: 0000006E 0D: 0000008B 0E: 000000A5 90: 00000003 91: 0000376F 12: 000000D4 13: 000000DC 14: 00000102 1C: 0000012A Data Block: 00 72 F3 E4 58 22 C0 01 41 63 74 69 76 65 57 65 r o a X " A _ A c t i v e W e 62 20 44 65 76 65 6C 6F 70 65 72 20 65 58 54 52 b D e v e l o p e r e X T R 41 20 23 38 00 60 E2 F2 9C 90 35 C0 01 3C 4F 46 A # 8 ` a o ? ? 5 A _ < O F 45 31 44 36 35 46 38 37 2E 32 39 39 31 37 34 31 E 1 D 6 5 F 8 7 . 2 9 9 1 7 4 1 42 2D 4F 4E 38 35 32 35 36 39 35 46 2E 30 30 35 B - O N 8 5 2 5 6 9 5 F . 0 0 5 43 33 46 41 36 40 70 69 6E 6E 61 63 6C 65 70 75 C 3 F A 6 @ p i n n a c l e p u 62 6C 69 73 68 69 6E 67 2E 63 6F 6D 3E 00 41 63 b l i s h i n g . c o m > A c 74 69 76 65 57 65 62 20 44 65 76 65 6C 6F 70 65 t i v e W e b D e v e l o p e 72 20 65 58 54 52 41 20 23 38 00 41 63 74 69 76 r e X T R A # 8 A c t i v 65 57 65 62 20 44 65 76 65 6C 6F 70 65 72 20 65 e W e b D e v e l o p e r e 58 54 52 41 00 61 63 74 69 76 65 77 65 62 64 65 X T R A a c t i v e w e b d e 76 65 6C 6F 70 65 72 65 78 74 72 61 40 70 69 6E v e l o p e r e x t r a @ p i n 6E 61 63 6C 65 70 75 62 6C 69 73 68 69 6E 67 2E n a c l e p u b l i s h i n g . 63 6F 6D 00 00 23 5E 0F 8B 22 C0 01 41 63 74 69 c o m # ^ _ ‹ " A _ A c t i 76 65 57 65 62 20 44 65 76 65 6C 6F 70 65 72 20 v e W e b D e v e l o p e r 65 58 54 52 41 20 53 75 62 73 63 72 69 62 65 72 e X T R A S u b s c r i b e r 20 00 3C 41 63 74 69 76 65 57 65 62 20 44 65 76 < A c t i v e W e b D e v 65 6C 6F 70 65 72 20 65 58 54 52 41 20 53 75 62 e l o p e r e X T R A S u b 73 63 72 69 62 65 72 20 3E 00 88 00 00 00 01 00 s c r i b e r > ? _ 02 4E 00 00 00 00 F9 37 00 00 02 4E 00 00 01 00 _ N u 7 _ N _ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 40 05 00 00 F9 37 00 00 00 00 @ _ u 7 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 _ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 6D 70 m p Теперь давайте разберёмся, что означает каждый флаг. Для файла Folders.dbx:
Для других файлов:
Сообщения: Каждое письмо или сообщение групп новостей хранятся в блоках по 512 байт, у каждого блока есть заголовок. То есть каждое сообщение делится на части, и к каждой части добавляют заголовок (в котором содержится размер блока, размер занятой части блока, а так же положение следующего блока). Я использую такую структуру для чтения блоков (вместе с их заголовками): Toe5_MsgItem = record FilePos: longint; {смещение структуры от BOF, используется для контроля верности операций} Unknown: longint; {я думаю, это размер блока данных} ItemSize: longint; {использованная часть блока} NextItem: longint; {смещение следующего блока от BOF, и 0, если это последний блок} MsgContent: array[0..511] of Char; {блок, содержащий непосредственно данные} end; Удаление сообщений Когда какое либо сообщение удаляется, оно сначала помещается в папку "Удаленные", а физически - в соответствующий этой папке файл. Место же, которое занимало сообщение в прежнем файле, добавляется в список пустого пространства, и когда приходит новое сообщение, Outlook Express использует сначала это место. Смещение первого элемента в списке сободного места сохранено по смещению $48 от начала файла. Каждый элемент этого списка разделен на две части: заголовок и блок свободного пространства. Вот структура заголовка: Toe5_FreeSpace = record FilePos: longint; {это смещение всей структуры от начала файла BOF, используется для контроля} ElementSize: longint; {размер структуры - заголовок и свободное место} FreeSpaceSize: longint; {Размер свободного пространства} PreviousElement: longint; {смещение (от начала файла) предыдущего элемента} NextElement: longint; {смещение следующего элемента} end; Даты Все даты в заголовке сообщения сохранены в формате TFileTime, и основаном на UTC. Перед использованием это значение надо перевести в местное время. Вот небольшой пример того, как это можно сделать: function FiletimeToDatetime(const date: TFileTime): TDateTime; var st: TSystemTime; localft: TFileTime; begin FileTimeToLocalFileTime(date, localft); FileTimeToSystemTime(localft, st); Result := SystemTimeToDateTime(st); end; Статус сообщения Для получения статуса сообщения можно использовать значение флага $81 следующим образом: ... x := < значение флага $81 > if (x and constant) <> 0 then ... И на последок, некоторые константы:
Эти константы надо проверить:
Модули к статье можно взять здесь Все дополнения, модификации, предложения, благодарности и т.п. просьба присылать на Samum2000@mail15.com (особенно к русскому переводу) или на walther_e@yahoo.com (на английском языке, касательно оригинала). Walther Estergaard Walther_e@yahoo.com
Перевод: Как читать файлы Outlook Express (DBX) в одном предложении В статье описывается процесс чтения файлов Outlook Express с помощью программирования, где автор использует структуру файла DBX, состоящую из таблиц и блоков данных, а также рек Комментарии и вопросыПолучайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта. :: Главная :: Почтовый клиент ::
|
||||
©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007 |