Untitled Document
Библиотека synapse. Открытие файла письма *.msg .
Вотя и созрел для второй статьи, на этот раз речь пойдет о чтении файлов стандарта
MIME . Использовать будем все ту же библиотеку Synapse. Мне это пригодилось в клиент - серверной программе, с помощью которой я отправляю письмо на сервер, который отправляет письмо через Thebat, таким образом я решил проблему с выделением интернета каждому пользователю, он им просто не нужен, такова уж политика моей организации. Вся корреспонденция идет с одного официального адреса, централизованное слежение за перепиской и т.п., вообщем, кто как заморачивается.
Прочитать, как устанавливать библиотеку Synapse, можно в статье
Библиотека synapse. Создание файла письма *.msg.
В этот раз, я решил начать с теоретического вступления.
Стандарт MIME описывает структуру почтового сообщения, что, в отличии от стандарта RFC822, позволяет обмениваться сообщениями с использованием различных типов информации, а не только текстовой.
В стандарте зарезервировано несколько способов представления разнородной информации. Для этой цели используются специальные поля заголовка почтового сообщения:
MIME-Version: поле версии MIME, указывает что сообщение подготовлено с использованием нового формата
Content-type: описания типа информации, что позволяет почтовой программе правильно понять, какой тип имеет информация. Стандарт MIME описывает семь типов инфомации, которые можно передавать в теле письма: текст (text); смешанный тип (multipart); почтовое сообщение (message); графический образ (image); аудио информация (audio); фильм или видео (video); приложение (application).
Content-Transfer-Encoding: Описывает какой метод кодирования используетв представлении информации.Используются следующие типы кодирования: "base64","quotes-printable", "8bit", "7bit", "binary" , x-token.
Дополнительные необязательные поля: Content-ID и Content-Description. Поле Content-ID описывает уникальный идентификатор содержания. Поле Content-Description коментирует содержание.
Не стоит беспокоиться, весь стандарт описан в библиотеке Syanpse, нам останеться лишь воспользоваться нужными функциями и процедурами.
Допустим, мы имеем такое сообщение, которое создано с помощью Outlook Express.
так сообщение выглядит в текстовом виде.
To: "post@host.com"
Subject: test e-mail
Date: Sun, 8 Nov 2009 01:05:09 +0700
MIME-Version: 1.0
Content-Type: multipart/mixed;
boundary="----=_NextPart_000_0023_01CA600F.85DB5400"
X-Priority: 3
X-MSMail-Priority: Normal
X-Unsent: 1
X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.5512
This is a multi-part message in MIME format.
------=_NextPart_000_0023_01CA600F.85DB5400
Content-Type: multipart/alternative;
boundary="----=_NextPart_001_0024_01CA600F.85DB5400"
------=_NextPart_001_0024_01CA600F.85DB5400
Content-Type: text/plain;
charset="koi8-r"
Content-Transfer-Encoding: quoted-printable
=F4=C5=D3=D4=CF=D7=CF=C5 =D3=CF=CF=C2=DD=C5=CE=C9=C5.
=F3 =D5=D7=C1=D6=C5=CE=C9=C5=CD post!
------=_NextPart_001_0024_01CA600F.85DB5400
Content-Type: text/html;
charset="koi8-r"
Content-Transfer-Encoding: quoted-printable
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META http-equiv=3DContent-Type content=3D"text/html; charset=3Dkoi8-r">
<META content=3D"MSHTML 6.00.2900.5512" name=3DGENERATOR>
<STYLE></STYLE>
</HEAD>
<BODY bgColor=3D#ffffff>
<DIV><FONT face=3DArial size=3D2>=F4=C5=D3=D4=CF=D7=CF=C5 =
=D3=CF=CF=C2=DD=C5=CE=C9=C5.</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2>=F3 =D5=D7=C1=D6=C5=CE=C9=C5=CD =
post!</FONT></DIV></BODY></HTML>
------=_NextPart_001_0024_01CA600F.85DB5400--
------=_NextPart_000_0023_01CA600F.85DB5400
Content-Type: text/plain;
name="file2.txt"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename="file2.txt"
seryeryerty
erye
ryerty
------=_NextPart_000_0023_01CA600F.85DB5400
Content-Type: text/plain;
name="file1.txt"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
filename="file1.txt"
4O3j7uvt4w0K7eUNCuP4DQrl7eMNCml0DQp5dQ0KaXR5
------=_NextPart_000_0023_01CA600F.85DB5400--
|
Разберем подробнее это сообщение.
Сообщение |
Описание в mimepart.pas |
Описание |
To: "post@host.com"
Subject: test e-mail
Date: Sun, 8 Nov 2009 01:05:09 +0700
MIME-Version: 1.0
Content-Type: multipart/mixed;
X-Priority: 3
X-MSMail-Priority: Normal
X-Unsent: 1
X-MimeOLE: Produced By ... |
Header.ToList
Header.Subject
Header.Date
Не описан
part.Primary/part.Alternative
Header.Priority
Header.Priority
Header.CustomHeaders
Header.CustomHeaders |
Получатель
Тема сообщения
Дата сообщения, время
Версия MIME
Тип данных
Приоритет сообщения
Приоритет сообщения
Дополнительное поле
Дополнительное поле |
Content-Type: multipart/alternative - определяет что сообщение состоит из нескольких фрагментов, которые разделены между собой границей _NextPart_000_0023_01CA600F.85DB5400, задаваемой в качестве параметра подтипа. "Multipart" определяет что тело почтового сообщения состоит из нескольких разных типов. Подтип "alternative" указывает что у нас есть выбор между методом отображения информации.
------=_NextPart_001_0024_01CA600F.85DB5400
Content-Type: text/plain;
charset="koi8-r"
Content-Transfer-Encoding: quoted-printable
=F4=C5=D3=D4=CF=D7=CF=C5 =D3=CF=CF=C2=DD=C5=CE=C9=C5.
=F3 =D5=D7=C1=D6=C5=CE=C9=C5=CD post!
------=_NextPart_001_0024_01CA600F.85DB5400
Content-Type: text/html;
charset="koi8-r"
Content-Transfer-Encoding: quoted-printable
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META http-equiv=3DContent-Type content=3D"text/html; charset=3Dkoi8-r">
<META content=3D"MSHTML 6.00.2900.5512" name=3DGENERATOR>
<STYLE></STYLE>
</HEAD>
<BODY bgColor=3D#ffffff>
<DIV><FONT face=3DArial size=3D2>=F4=C5=D3=D4=CF=D7=CF=C5 =
=D3=CF=CF=C2=DD=C5=CE=C9=C5.</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2>=F3 =D5=D7=C1=D6=C5=CE=C9=C5=CD =
post!</FONT></DIV></BODY></HTML>
------=_NextPart_001_0024_01CA600F.85DB5400-- |
В первом блоке между_NextPart_001_0024_01CA600F.85DB5400 мы видим:
Content-Type: text/plain указывает на то, что текст сообщения представлен в текстовом виде (планарный текст - без разметки).
charset="koi8-r" - указывает в какой кодировке было исходное соощение, в mimepart.pas определяется какpart.Charset.
Content-Transfer-Encoding - метод шифрования сообщения, определяется как part.EncodingCode.
Во втором блоке то же самое сообщение представлено в виде текста с разметкой, html. C помошью part.Alternative можно определить какой тип имеет сообщение и обработать его соответствующим образом в программе. Можно, как в TheBat, использовать два типа, как мы и сделаем в примере.
Следующий блок определяет вложения к сообщению.
------=_NextPart_000_0023_01CA600F.85DB5400
Content-Type: text/plain;
name="file2.txt"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename="file2.txt"
seryeryerty
erye
ryerty
------=_NextPart_000_0023_01CA600F.85DB5400
Content-Type: text/plain;
name="file1.txt"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
filename="file1.txt"
4O3j7uvt4w0K7eUNCuP4DQrl7eMNCml0DQp5dQ0KaXR5
------=_NextPart_000_0023_01CA600F.85DB5400-- |
Обратите внимание, Content-Type в обоих блоках совпадает, хотя первый блок определяет текст сообщения, а второй вложения. Отличие, которое нужно испльзовать для различия это поле filename, т.к. поле Content-Disposition является необязательным, определить что данный блок содержит вложение можно использовать их в паре. В Synapse поле filename определяется как part.FileName, Content-Disposition - part.Disposition.
Теперь приступим к разработке программы, которая позволит разобрать по "косточкам" файл формата MIME.
Я не буду полностью описывать программу, просто приведу исходный код, считаю что выше все было разобрано.
unit Unit1;
interface
uses
... mimemess, mimepart, ActiveX;
type
TForm1 = class(TForm)
...
procedure Button1Click(Sender: TObject);
procedure GetParts(const part: TMimepart);
private
public
end;
var
Form1: TForm1;
IdMes:TMimeMess;
implementation
{$R *.dfm}
procedure TForm1.GetParts(const part: TMimepart);
var
s: string;
i: integer;
begin
if (LowerCase(part.Primary)='text') and (LowerCase(part.FileName)='') then begin
part.DecodePart;
if LowerCase(part.Secondary)='plain' then Memo1.Lines.LoadFromStream(part.DecodedLines) else begin
WebBrowser1.Navigate('html.htm');
while WebBrowser1.ReadyState < READYSTATE_INTERACTIVE do
Application.ProcessMessages;
(WebBrowser1.Document as
IPersistStreamInit).Load(TStreamAdapter.Create(part.DecodedLines));
end;
end;
if LowerCase(part.FileName)<>'' then begin part.DecodePart;
part.DecodedLines.SaveToFile('c:\'+part.FileName) ;
Memo3.Lines.Add('Сохранено в '+'c:\'+part.FileName)
end;
for i := 0 to part.GetSubPartCount - 1 do
GetParts( part.getsubpart(i)); end;
procedure TForm1.Button1Click(Sender: TObject);
var
i:integer;
begin
if OpenDialog1.Execute then
begin
IdMes:=TMimeMess.Create;
IdMes.Lines.LoadFromFile(OpenDialog1.FileName);
end;
IdMes.DecodeMessage; LabeledEdit2.Text:=IdMes.Header.From;
LabeledEdit1.Text:=trim(IdMes.Header.ToList.Text); LabeledEdit3.Text:=IdMes.Header.Subject;
Memo2.Lines.Assign(IdMes.Header.CustomHeaders); GetParts(IdMes.MessagePart); end;
end.
|
Теперь можно выгружать письма из TheBat или других почтовых программ и разбирать почту. Я делаю это так, экспортирую письма из почтовика, загружаю в программу, разбираю и работаю дальше уже с структурированными данными.
Материал к статье
Автор neusro
|