Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2011.07.10;
Скачать: CL | DM;

Вниз

чтение писем из eml формата..   Найти похожие ветки 

 
istok20 ©   (2009-11-25 13:34) [0]

какие компоненты умеют читать содержимое.eml с пониманием кодировки utf-8 и вытаскиванием from\to\subject\body\attachments и тд?   пробовал mail2000, но он кодировки не понимает...


 
Игорь Шевченко ©   (2009-11-25 14:07) [1]


> пробовал mail2000, но он кодировки не понимает...


а я себе подправил. там несложно


 
Игорь Шевченко ©   (2009-11-25 14:12) [2]

Где-то так:

// Get the subject

function TMailMessage2000.GetSubject: String;
begin
//See changelog.txt
 Result := DecodeLine7BitEx(GetLabelValue("Subject"));
end;

// Get file name of attachment

function TMailPart.GetFileName: String;
var
 Name: String;
begin
 Name := "";
 if LabelParamExists(_C_T, "name") then
   Name := GetLabelParamValue(_C_T, "name")
 else if LabelParamExists(_C_D, "filename") then
   Name := GetLabelParamValue(_C_D, "filename")
 else if LabelExists(_C_ID) then
   Name := GetLabelValue(_C_ID)
 else if LabelExists(_C_T) then
   Name := GetLabelValue(_C_T)+GetMimeExtension(GetLabelValue(_C_T))
 else
   Name := "unknown";
 Name := DecodeLine7BitEx(Name); //see changelog.txt
 if Pos(".", Name) = 0 then
   Name := Name + GetMimeExtension(GetLabelValue(_C_T));
 Result := ValidFileName(Name);
end;

function DecodeLine7BitEx(const Text: string): string;
//текстом является строка, окруженная разделителями =? и ?=
var
 Worker: string;
 I, J, Q: Integer;
begin
 Result := "";
 Worker := Text;
 while true do
 begin
   I := Pos("=?", Worker);
   if I = 0 then
   begin
   { Строка не содержит закодированного текста }
     Result := Result + DecodeLine7Bit(Worker);
     Exit;
   end;
   Result := Result + Copy(Worker, 1, I-1); //Незакодированная часть
   Worker := Copy(Worker, I, Length(Text));
   J := Pos("?=",Worker); //Ищем окончание кодированной части
   Q := Pos("?Q?=", Worker); //Если имя файла закодировано в Quoted-printable,
                             // то окончание кодированного текста следует
                             // искать после кодировки
   if Q > 0 then
   begin
     J := Pos("?=", Copy(Worker, Q+4, Length(Worker)));
     if J > 0 then
       Inc(J, Q+3);
   end;
   if J > 0 then
   begin
     Result := Result + DecodeLine7Bit(Copy(Worker, 1, J+1));
     Worker := Copy(Worker, J+2, Length(Worker));
   end;
 end;
end;

function DecodeString (const SourceCharset, DestCharSet, Source: string): string;
var
 Worker: string;
begin
 Result := Source;
 if SameText(DestCharSet, "windows-1251") then
 begin
   // Для Windows-1251 ничего не делаем
   if SameText(SourceCharset, "windows-1251") or (SourceCharset = "") then
   begin
     //Do nothing
   end
   // Для ISO-8859-1 ничего не делаем
   else if SameText(SourceCharset, "ISO-8859-1") then
   begin
     //Do nothing
   end
   // Для utf-8
   else if SameText(SourceCharset, "utf-8") then
   begin
     Result := Utf8ToAnsi(Result);
   end
   // Для koi8-r пытаемся перевести в Windows-1251
   else if SameText(SourceCharset, "koi8-r") then
     Result := Koi_WinConvert(Result)
   // Для koi8-u пытаемся перевести в Windows-1251
   else if SameText(SourceCharset, "koi8-u") then
     Result := Koi8u_WinConvert(Result)
   else if Assigned(CharsetDecoder) then
   begin
     Worker := CharsetDecoder(SourceCharset, DestCharSet, Result);
     if (Length(Worker) > 0) or (Length(Result) = 0)  then
       Result := Worker
     else
       raise Exception.CreateFmt("Unknown source encoding %s", [SourceCharset]);
   end
   else
     raise Exception.CreateFmt("Unknown source encoding %s", [SourceCharset]);
 end
 else
   if Assigned(CharsetDecoder) then
   begin
     Worker := CharsetDecoder(SourceCharset, DestCharSet, Result);
     if (Length(Worker) > 0) or (Length(Result) = 0)  then
       Result := Worker
     else
       raise Exception.CreateFmt("Unknown source encoding %s", [SourceCharset]);
   end;
end;

// Decode an encoded field e.g. =?iso-8859-1?x?xxxxxx=?=

//Шевченко. FIX FIX FIX
// Боремся с кодировкой имен файлов для русских имен
// Полагаем, что если указана кодировка Windows-1251, то после перекодировки
// из base64 или Quoted-Printable у нас уже хорошее русское имя.
// Если указана кодировка KOI-8, то русское имя у нас неправильное
// и его надо преобразовать

function DecodeLine7Bit(Texto: String): String;
var
 Buffer: PChar;
 Encoding: Char;
 Size: Integer;
 nPos0: Integer;
 nPos1: Integer;
 nPos2: Integer;
 nPos3: Integer;
 nPosEndCharset: Integer;
 Found: Boolean;
 Charset: string;
begin
 Result := TrimSpace(Texto);
 repeat
   Charset := "";
   nPos0 := Pos("=?", Result);
   Found := False;
   if nPos0 > 0 then
   begin
     nPosEndCharSet := Pos("?", Copy(Result, nPos0+2, Length(Result)));
     if nPosEndCharset > 0 then
       Charset := Copy(Result, nPos0+2, nPosEndCharset-nPos0);
     nPos1 := Pos("?", Copy(Result, nPos0+2, Length(Result)))+nPos0+1;
     nPos2 := Pos("?=", Copy(Result, nPos1+1, Length(Result)))+nPos1;
     nPos3 := Pos("?", Copy(Result, nPos2+1, Length(Result)))+nPos2;
     if nPos3 > nPos2 then
       if Length(Result) > nPos3 then
         if Result[nPos3+1] = "=" then
           nPos2 := nPos3;
     if (nPos1 > nPos0) and (nPos2 > nPos1) then
     begin
       Texto := Copy(Result, nPos1+1, nPos2-nPos1-1);
       if (Length(Texto) >= 2) and (Texto[2] = "?") and (UpCase(Texto[1]) in ["B", "Q", "U"]) then
         Encoding := UpCase(Texto[1])
       else
         Encoding := "Q";
       Texto := Copy(Texto, 3, Length(Texto)-2);
       case Encoding of
       "B":
         begin
           GetMem(Buffer, Length(Texto));
           Size := DecodeLineBASE64(Texto, Buffer);
           Buffer[Size] := #0;
           Texto := String(Buffer);
         end;
       "Q":
         begin
           while Pos("_", Texto) > 0 do
             Texto[Pos("_", Texto)] := #32;
           Texto := DecodeQuotedPrintable(Texto);
         end;
       "U":
         begin
           GetMem(Buffer, Length(Texto));
           Size := DecodeLineUUCODE(Texto, Buffer);
           Buffer[Size] := #0;
           Texto := String(Buffer);
         end;
       end;
       Result := Copy(Result, 1, nPos0-1)+Texto+Copy(Result,nPos2+2,Length(Result));
       Found := True;
       //
       Result := DecodeString(CharSet, DefaultDecodeCharset, Result);
     end;
   end;
 until not Found;
end;


 
istok20 ©   (2009-11-25 14:26) [3]

ой, боольшое спасибо!


 
istok20 ©   (2009-11-25 15:08) [4]

не нашел реализации DefaultDecodeCharset

может, проще будет скинуть Mail2000.pas на email  (alex_for_chat@mail.ru)  ?

спасибо!


 
Игорь Шевченко ©   (2009-11-25 15:23) [5]


> проще будет скинуть Mail2000.pas на email  


Нет, не проще. Там изменений больше и часть из них является коммерческим секретом.

type
 TCharsetDecoder = function (const SourceCharSet, DestCharSet,
   Source: string): string;
var
 DefaultDecodeCharset: string;
 CharsetDecoder: TCharsetDecoder;

type
 TConvertChars = array [ #128..#255] of char;

const
 Win_KoiChars: TConvertChars = (
 #128,#129,#130,#131,#132,#133,#134,#135,#136,#137,#060,#139,#140,#141,#142,#143,
 #144,#145,#146,#147,#148,#169,#150,#151,#152,#153,#154,#062,#176,#157,#183,#159,
 #160,#246,#247,#074,#164,#231,#166,#167,#179,#169,#180,#060,#172,#173,#174,#183,
 #156,#177,#073,#105,#199,#181,#182,#158,#163,#191,#164,#062,#106,#189,#190,#167,
 #225,#226,#247,#231,#228,#229,#246,#250,#233,#234,#235,#236,#237,#238,#239,#240,
 #242,#243,#244,#245,#230,#232,#227,#254,#251,#253,#154,#249,#248,#252,#224,#241,
 #193,#194,#215,#199,#196,#197,#214,#218,#201,#202,#203,#204,#205,#206,#207,#208,
 #210,#211,#212,#213,#198,#200,#195,#222,#219,#221,#223,#217,#216,#220,#192,#209) ;

 Koi_WinChars: TConvertChars = (
 #128,#129,#130,#131,#132,#133,#134,#135,#136,#137,#138,#139,#140,#141,#142,#143,
 #144,#145,#146,#147,#148,#149,#150,#151,#152,#153,#218,#155,#176,#157,#183,#159,
 #160,#161,#162,#184,#186,#165,#166,#191,#168,#169,#170,#171,#172,#173,#174,#175,
 #156,#177,#178,#168,#170,#181,#182,#175,#184,#185,#186,#187,#188,#189,#190,#185,
 #254,#224,#225,#246,#228,#229,#244,#227,#245,#232,#233,#234,#235,#236,#237,#238,
 #239,#255,#240,#241,#242,#243,#230,#226,#252,#251,#231,#248,#253,#249,#247,#250,
 #222,#192,#193,#214,#196,#197,#212,#195,#213,#200,#201,#202,#203,#204,#205,#206,
 #207,#223,#208,#209,#210,#211,#198,#194,#220,#219,#199,#216,#221,#217,#215,#218) ;

 koi8u_Winchars: TConvertChars = (
 #128,#129,#130,#131,#132,#133,#134,#135,#136,#137,#138,#139,#140,#141,#142,#143,
#144,#145,#146,#147,#148,#149,#150,#151,#152,#153,#154,#155,#156,#157,#158,#159,
#160,#161,#162,"ё" ,"є" ,#165,"_" ,"ї" ,#168,#169,#170,#171,#172,#173,#174,#175,
#176,#177,#178,"Ё" ,"Є" ,#181,"_" ,"Ї" ,#184,#185,#186,#187,#188,#189,#190,#191,
"ю" ,"а" ,"б" ,"ц" ,"д" ,"е" ,"ф" ,"г" ,"х" ,"и" ,"й" ,"к" ,"л" ,"м" ,"н" ,"о" ,
"п" ,"я" ,"р" ,"с" ,"т" ,"у" ,"ж" ,"в" ,"ь" ,"ы" ,"з" ,"ш" ,"э" ,"щ" ,"ч" ,"ъ" ,
"Ю" ,"А" ,"Б" ,"Ц" ,"Д" ,"Е" ,"Ф" ,"Г" ,"Х" ,"И" ,"Й" ,"К" ,"Л" ,"М" ,"Н" ,"О" ,
"П" ,"Я" ,"Р" ,"С" ,"Т" ,"У" ,"Ж" ,"В" ,"Ь" ,"Ы" ,"З" ,"Ш" ,"Э" ,"Щ" ,"Ч" ,"Ъ"
 );

 iso88595_winchars: TConvertChars = (
 #128,#129,#130,#131,#132,#133,#134,#135,#136,#137,#138,#139,#140,#141,#142,#143,
#144,#145,#146,#147,#148,#149,#150,#151,#152,#153,#154,#155,#156,#157,#158,#159,
#160,"Ё" ,#162,#163,"Є" ,#165,"_" ,"Ї" ,#168,#169,#170,#171,#172,#173,#174,#175,
"А" ,"Б" ,"В" ,"Г" ,"Д" ,"Е" ,"Ж" ,"З" ,"И" ,"Й" ,"К" ,"Л" ,"М" ,"Н" ,"О" ,"П" ,
"Р" ,"С" ,"Т" ,"У" ,"Ф" ,"Х" ,"Ц" ,"Ч" ,"Ш" ,"Щ" ,"Ъ" ,"Ы" ,"Ь" ,"Э" ,"Ю" ,"Я" ,
"а" ,"б" ,"в" ,"г" ,"д" ,"е" ,"ж" ,"з" ,"и" ,"й" ,"к" ,"л" ,"м" ,"н" ,"о" ,"п" ,
"р" ,"с" ,"т" ,"у" ,"ф" ,"х" ,"ц" ,"ч" ,"ш" ,"щ" ,"ъ" ,"ы" ,"ь" ,"э" ,"ю" ,"я" ,
#240,"ё" ,#242,#243,"є" ,#245,"_" ,"ї" ,#248,#249,#250,#251,#252,#253,#254,#255
);

function Win_KoiConvert(const St: string): string;
var
 i: integer;
begin
 Result:=St;
 for i:=1 to Length(St) do
   if St[i]>#127 then
     Result[i]:=Win_KoiChars[St[i]];
end;

function Koi_WinConvert(const St: string): string;
var
 i: integer;
begin
 Result:=St;
 for i:=1 to Length(St) do
   if St[i]>#127 then
     Result[i]:=Koi_WinChars[St[i]];
end;

function Koi8u_WinConvert(const St: string): string;
var
 i: integer;
begin
 Result:=St;
 for i:=1 to Length(St) do
   if St[i]>#127 then
     Result[i]:=koi8u_Winchars[St[i]];
end;

function DecodeQuotedPrintable(const Texto: string): string;
var
 P, Q: PChar;
 B: Byte;
begin
 SetLength(Result, Length(Texto));
 P := PChar(Texto);
 Q := PChar(Result);
 if (P^ = #13) and ((P + 1)^ = #10) then
   Inc(P, 2); // Bugfix for incorrect detection of the body beginning
 while P^ <> #0 do
 begin
   if P^ = "=" then
   begin
     Inc(P);
     if P^ = #13 then
     begin
       Inc(P);
       if P^ = #10 then
         Inc(P);
     end
     else if P^ = #10 then
     begin
       Inc(P);
       if P^ = #13 then
         Inc(P);
     end
     else if (P^ in ["0".."9", "A".."F"]) and ((P + 1)^ in ["0".."9", "A".."F"]) then
     begin
       if (P^ >= "0") and (P^ <= "9") then
         B := (Ord(P^) - Ord("0")) * 16
       else
         B := (Ord(P^) - Ord("A") + 10) * 16;
       if ((P + 1)^ >= "0") and ((P + 1)^ <= "9") then
         B := B + (Ord((P + 1)^) - Ord("0"))
       else
         B := B + (Ord((P + 1)^) - Ord("A") + 10);
       Inc(P, 2);
       Q^ := Chr(B);
       Inc(Q);
     end;
   end
   else
   begin
     Q^ := P^;
     Inc(P);
     Inc(Q);
   end
 end;
 SetLength(Result, Q - PChar(Result));
end;



 
Игорь Шевченко ©   (2009-11-25 15:24) [6]

initialization
 DefaultDecodeCharset := "windows-1251";



Страницы: 1 вся ветка

Текущий архив: 2011.07.10;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.007 c
15-1301076925
TStas
2011-03-25 21:15
2011.07.10
Что делать с ноутбуком


2-1301402564
Eugene1501
2011-03-29 16:42
2011.07.10
Что значит подобная конструкция


15-1301188320
Германн
2011-03-27 05:12
2011.07.10
Автоматический переход


15-1300692093
brother
2011-03-21 10:21
2011.07.10
Старый ноутбук


2-1301675364
Gu
2011-04-01 20:29
2011.07.10
PhysicalDrive