Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum. Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

MAILS AVEC INDY10, RÉSOLUTION DU PROBLÈME LORSQUE CHARSET = UTF-8


Information sur la source

Catégorie :Composants Classé sous : indy, mail, utf8, composant Niveau : Débutant Date de création : 27/07/2007 Date de mise à jour : 01/08/2007 14:55:37 Vu : 5 074

Note :
10 / 10 - par 1 personne
10,00 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

Commentaire sur cette source (9)
Ajouter un commentaire et/ou une note


Description

Indy10 est après moultes tests, (pour moi) le meilleur package de compos orienté communications réseau/internet.

Mais voilà, il subsiste un bug car la gestion des mails au format UTF-8 lors de la réception n' est pas gérée.
Ce que je vous propose, c' est de remplacer 2 fonctions pour gérer le charset UTF-8  :) pour convertir correctement le "Subject" du mail ainsi que le body lorsque celui-ci est de type text/plain .
 

Source

  • Voici la 1ere fonction à remplacer dans l' unité IdCoderHeader.pas :
  • Mes changements sont marqués par "// RHR" en commentaire pour que vous sachiez ce que j' ai fait!!!
  • function DecodeHeader(Header: string):string;
  • const
  • WhiteSpace = [LF, CR, CHAR32, TAB];
  • var
  • i, l: Integer;
  • HeaderEncoding,
  • HeaderCharSet,
  • s: string;
  • a3: array [1..3] of byte;
  • a4: array [1..4] of byte;
  • LEncodingStartPos,encodingendpos:Integer;
  • LPreviousEncodingStartPos: integer;
  • substring: string;
  • EncodingFound: Boolean;
  • OnlyWhitespace: boolean;
  • EncodingBeforeEnd: integer;
  • begin
  • // Get the Charset part.
  • EncodingBeforeEnd := -1;
  • LEncodingStartPos := PosIdx('=?ISO', UpperCase(Header), 1); {do not localize}
  • if LEncodingStartPos = 0 then begin
  • LEncodingStartPos := PosIdx('=?WINDOWS', UpperCase(Header), 1); {do not localize}
  • end;
  • if LEncodingStartPos = 0 then begin
  • LEncodingStartPos := PosIdx('=?KOI8', UpperCase(Header), 1); {do not localize}
  • end;
  • // RHR BEGIN
  • if LEncodingStartPos = 0 then begin
  • LEncodingStartPos := PosIdx('=?UTF-8', UpperCase(Header), 1); {do not localize}
  • end;
  • // RHR END
  • while LEncodingStartPos > 0 do begin
  • // Assume we will find the encoding
  • EncodingFound := True;
  • //we need 3 more question marks first and after that a '?=' {Do not Localize}
  • //to find the end of the substring, we can't just search for '?=', {Do not Localize}
  • //example: '=?ISO-8859-1?Q?=E4?=' {Do not Localize}
  • encodingendpos := PosIdx('?', UpperCase(Header),LEncodingStartPos+5); {Do not Localize}
  • if encodingendpos = 0 then begin
  • EncodingFound := False;
  • end else begin
  • // valid encoded words can not contain spaces
  • // if the user types something *almost* like an encoded word,
  • // and its sent as-is, we need to find this!!
  • for i := LEncodingStartPos to encodingendpos-1 do begin
  • if CharIsInSet(Header, i, Whitespace) then begin
  • EncodingFound := false;
  • break;
  • end;
  • end;
  • end;
  • if EncodingFound then
  • begin
  • encodingendpos:=PosIdx('?', UpperCase(Header),encodingendpos+1); {Do not Localize}
  • if encodingendpos=0 then
  • begin
  • EncodingFound := false;
  • end else begin
  • for i := LEncodingStartPos to encodingendpos-1 do begin
  • if CharIsInSet(Header, i, Whitespace) then begin
  • EncodingFound := false;
  • break;
  • end;
  • end;
  • end;
  • end;
  • if EncodingFound then
  • begin
  • encodingendpos:=PosIdx('?=', UpperCase(Header),encodingendpos+1); {Do not Localize}
  • if encodingendpos > 0 then
  • begin
  • for i := LEncodingStartPos to encodingendpos-1 do begin
  • if CharIsInSet(Header, i, Whitespace) then begin
  • EncodingFound := false;
  • break;
  • end;
  • end;
  • if EncodingFound then begin
  • substring:=Copy(Header,LEncodingStartPos,encodingendpos-LEncodingStartPos+2);
  • //now decode the substring
  • for i := 1 to 3 do
  • begin
  • l := Pos('?', substring); {Do not Localize}
  • substring := Copy(substring, l+1, Length(substring) - l + 1 );
  • if i = 1 then
  • begin
  • HeaderCharSet := Copy(substring, 1, Pos('?', substring)-1) {Do not Localize}
  • end else if i = 2 then
  • begin
  • HeaderEncoding := copy(substring,1,1);
  • end;
  • end;
  • //now Substring needs to end with '?=' otherwise give up! {Do not Localize}
  • if Copy(substring,Length(substring)-1,2)<>'?=' then {Do not Localize}
  • begin
  • EncodingFound := false;
  • end;
  • end;
  • if (EncodingBeforeEnd>=0) and EncodingFound and (LEncodingStartPos > 0) then begin
  • OnlyWhitespace := true;
  • for i:=EncodingBeforeEnd to LEncodingStartPos-1 do begin
  • if not (CharIsInSet(Header, i, WhiteSpace)) then begin
  • OnlyWhitespace := false;
  • break;
  • end;
  • end;
  • if OnlyWhitespace then begin
  • Delete(Header, EncodingBeforeEnd, LEncodingStartPos-EncodingBeforeEnd);
  • encodingendpos := encodingendpos - (LEncodingStartPos-encodingbeforeend);
  • LEncodingStartPos := EncodingBeforeEnd;
  • end;
  • end;
  • // Get the HeaderEncoding
  • if TextIsSame(HeaderEncoding, 'Q') {Do not Localize}
  • and EncodingFound then begin
  • i := 1;
  • s := ''; {Do not Localize}
  • repeat // substring can be accessed by index here, because we know that it ends with '?=' {Do not Localize}
  • if substring[i] = '_' then {Do not Localize}
  • begin
  • s := s + ' '; {Do not Localize}
  • end else if (substring[i] = '=') and (Length(substring)>=i+2+2) then //make sure we can access i+2 and '?=' is still beyond {Do not Localize}
  • begin
  • s := s + chr(StrToInt('$' + substring[i+1] + substring[i+2])); {Do not Localize}
  • inc(i,2);
  • end else
  • begin
  • s := s + substring[i];
  • end;
  • inc(i);
  • until (substring[i]='?') and (substring[i+1]='=') {Do not Localize}
  • end else if EncodingFound then
  • begin
  • while Length(substring) >= 4 do
  • begin
  • a4[1] := b64(substring[1]);
  • a4[2] := b64(substring[2]);
  • a4[3] := b64(substring[3]);
  • a4[4] := b64(substring[4]);
  • a3[1] := Byte((a4[1] shl 2) or (a4[2] shr 4));
  • a3[2] := Byte((a4[2] shl 4) or (a4[3] shr 2));
  • a3[3] := Byte((a4[3] shl 6) or (a4[4] shr 0));
  • substring := Copy(substring, 5, Length(substring));
  • s := s + CHR(a3[1]) + CHR(a3[2]) + CHR(a3[3]);
  • end;
  • end;
  • if EncodingFound then
  • begin
  • if TextIsSame(HeaderCharSet, 'ISO-2022-JP') then {Do not Localize}
  • begin
  • substring := Decode2022JP(s);
  • end
  • else
  • // RHR BEGIN
  • if TextIsSame(HeaderCharSet, 'utf-8')
  • then begin
  • SubString := Utf8ToAnsi(s);
  • end
  • // RHR END
  • else begin
  • substring := s;
  • end;
  • //replace old substring in header with decoded one:
  • header := Copy(header, 1, LEncodingStartPos - 1)
  • + substring + Copy(header, encodingendpos + 2, Length(Header));
  • encodingendpos := length(substring);
  • substring := ''; {Do not Localize}
  • end;
  • end;
  • end;
  • encodingendpos := LEncodingStartPos + encodingendpos;
  • {CC: Bug fix - changed LEncodingStartPos to LPreviousEncodingStartPos because
  • LEncodingStartPos gets overwritten by return value from PosIdx.}
  • LPreviousEncodingStartPos := LEncodingStartPos;
  • LEncodingStartPos := PosIdx('=?ISO', UpperCase(Header), LPreviousEncodingStartPos + 1); {do not localize}
  • if LEncodingStartPos = 0 then begin
  • LEncodingStartPos := PosIdx('=?WINDOWS', UpperCase(Header), LPreviousEncodingStartPos + 1); {do not localize}
  • end;
  • if LEncodingStartPos = 0 then begin
  • LEncodingStartPos := PosIdx('=?KOI8', UpperCase(Header), LPreviousEncodingStartPos + 1); {do not localize}
  • end;
  • // BEGIN RHR //
  • if LEncodingStartPos = 0 then begin
  • LEncodingStartPos := PosIdx('=?UTF-8', UpperCase(Header), LPreviousEncodingStartPos + 1); {do not localize}
  • end;
  • // END RHR //
  • // delete whitespace between adjacent encoded words, but only
  • // if we had an encoding before
  • if EncodingFound then begin
  • EncodingBeforeEnd := encodingendpos;
  • end else begin
  • EncodingBeforeEnd := -1;
  • end;
  • end;
  • //There might be #0's in header when this it b64 encoded, e.g with:
  • //decodeheader('"Fernando Corti=?ISO-8859-1?B?8Q==?=a" <fernando@nowhere.com>');
  • while Pos(#0, header) > 0 do begin
  • Delete(header, Pos(#0, header), 1);
  • end;
  • Result := Header;
  • end;
  • Voici la 2eme fonction à remplacer dans l' unité IdMessageClient.pas :
  • Mes changements sont marqués par "// RHR" pour que vous sachiez ce que j' ai fait!!!
  • La fonction est une sous-fonction de la fonction suivante:
  • procedure TIdMessageClient.ReceiveBody(AMsg: TIdMessage; const ADelim: string = '.'); {do not localize}
  • function ProcessTextPart(ADecoder: TIdMessageDecoder; AUseBodyAsTarget: Boolean = False): TIdMessageDecoder;
  • {Only set AUseBodyAsTarget to True if you want the input stream stored in TIdMessage.Body
  • instead of TIdText.Body: this happens with some single-part messages.}
  • var
  • LDestStream: TIdStreamVCL;
  • LStringStream: TStringStream;
  • i, l: integer;
  • LTxt : TIdText;
  • begin
  • LStringStream := TIdStringStream.Create('');
  • try
  • LDestStream := TIdStreamVCL.Create(LStringStream);
  • try
  • LParentPart := AMsg.MIMEBoundary.ParentPart;
  • Result := ADecoder.ReadBody(LDestStream, LMsgEnd);
  • if AUseBodyAsTarget then begin
  • // RHR BEGIN
  • if TextIsSame(AMsg.CharSet, 'utf-8') and TextIsSame(AMsg.ContentType, 'text/plain')
  • then begin
  • AMsg.Body.Text := LStringStream.DataString; // Utf8ToAnsi(LStringStream.DataString) ne marche pas si le body est trop grand !!!
  • for l := 0 to AMsg.Body.Count-1 do
  • AMsg.Body[l] := Utf8ToAnsi(AMsg.Body[l]);
  • end
  • else
  • // RHR END
  • AMsg.Body.Text := LStringStream.DataString;
  • end else begin
  • LTxt := TIdText.Create(AMsg.MessageParts);
  • LTxt.Body.Text := LStringStream.DataString;
  • RemoveLastBlankLine(LTxt.Body);
  • if AMsg.IsMsgSinglePartMime then begin
  • LTxt.ContentType := LTxt.ResolveContentType(AMsg.Headers.Values[SContentType]);
  • LTxt.Headers.Add('Content-Type: '+AMsg.Headers.Values[SContentType]); {do not localize}
  • LTxt.CharSet := LTxt.GetCharSet(AMsg.Headers.Values['Content-Type']); {do not localize}
  • LTxt.ContentTransfer := AMsg.Headers.Values['Content-Transfer-Encoding']; {do not localize}
  • LTxt.Headers.Add('Content-Transfer-Encoding: '+AMsg.Headers.Values['Content-Transfer-Encoding']); {do not localize}
  • LTxt.ContentID := AMsg.Headers.Values['Content-ID']; {do not localize}
  • LTxt.ContentLocation := AMsg.Headers.Values['Content-Location']; {do not localize}
  • end else begin
  • LTxt.ContentType := LTxt.ResolveContentType(ADecoder.Headers.Values[SContentType]);
  • LTxt.Headers.Add('Content-Type: '+ADecoder.Headers.Values[SContentType]); {do not localize}
  • LTxt.CharSet := LTxt.GetCharSet(ADecoder.Headers.Values['Content-Type']); {do not localize}
  • LTxt.ContentTransfer := ADecoder.Headers.Values['Content-Transfer-Encoding']; {do not localize}
  • LTxt.Headers.Add('Content-Transfer-Encoding: '+ADecoder.Headers.Values['Content-Transfer-Encoding']); {do not localize}
  • LTxt.ContentID := ADecoder.Headers.Values['Content-ID']; {do not localize}
  • LTxt.ContentLocation := ADecoder.Headers.Values['Content-Location']; {do not localize}
  • LTxt.ExtraHeaders.NameValueSeparator := '='; {do not localize}
  • for i := 0 to ADecoder.Headers.Count-1 do begin
  • if LTxt.Headers.IndexOfName(ADecoder.Headers.Names[i]) < 0 then begin
  • LTxt.ExtraHeaders.Add(ADecoder.Headers.Strings[i]);
  • end;
  • end;
  • end;
  • if TextIsSame(Copy(LTxt.ContentType, 1, 10), 'multipart/') then begin {do not localize}
  • LTxt.ParentPart := LPreviousParentPart;
  • end else begin
  • LTxt.ParentPart := LParentPart;
  • end;
  • // RHR BEGIN
  • if TextIsSame(LTxt.CharSet, 'utf-8') and TextIsSame(LTxt.ContentType, 'text/plain') // Sauter si au format HTML ou autre ...
  • then
  • for l := 0 to Ltxt.Body.Count-1 do
  • LTxt.Body[l] := Utf8ToAnsi(LTxt.Body[l]);
  • // RHR END
  • end;
  • ADecoder.Free;
  • finally FreeAndNil(LDestStream); end;
  • finally FreeAndNil(LStringStream); end;
  • end;
Voici la 1ere fonction à remplacer dans l' unité IdCoderHeader.pas : 
Mes changements sont marqués par "// RHR" en commentaire pour que vous sachiez ce que j' ai fait!!!

function DecodeHeader(Header: string):string;  
const
  WhiteSpace = [LF, CR, CHAR32, TAB];
var
  i, l: Integer;
  HeaderEncoding,
  HeaderCharSet,
  s: string;
  a3: array [1..3] of byte;
  a4: array [1..4] of byte;
  LEncodingStartPos,encodingendpos:Integer;
  LPreviousEncodingStartPos: integer;
  substring: string;
  EncodingFound: Boolean;
  OnlyWhitespace: boolean;
  EncodingBeforeEnd: integer;
begin
  // Get the Charset part.
  EncodingBeforeEnd := -1;
  LEncodingStartPos := PosIdx('=?ISO', UpperCase(Header), 1); {do not localize}
  if LEncodingStartPos = 0 then begin
    LEncodingStartPos := PosIdx('=?WINDOWS', UpperCase(Header), 1); {do not localize}
  end;
  if LEncodingStartPos = 0 then begin
    LEncodingStartPos := PosIdx('=?KOI8', UpperCase(Header), 1); {do not localize}
  end;
  // RHR BEGIN
  if LEncodingStartPos = 0 then begin
    LEncodingStartPos := PosIdx('=?UTF-8', UpperCase(Header), 1); {do not localize}
  end;
  // RHR END

  while LEncodingStartPos > 0 do begin
    // Assume we will find the encoding
    EncodingFound := True;

    //we need 3 more question marks first and after that a '?='    {Do not Localize}
    //to find the end of the substring, we can't just search for '?=',    {Do not Localize}
    //example: '=?ISO-8859-1?Q?=E4?='    {Do not Localize}
    encodingendpos := PosIdx('?', UpperCase(Header),LEncodingStartPos+5);  {Do not Localize}
    if encodingendpos = 0 then begin
      EncodingFound := False;
    end else begin
      // valid encoded words can not contain spaces
      // if the user types something *almost* like an encoded word,
      // and its sent as-is, we need to find this!!
      for i := LEncodingStartPos to encodingendpos-1 do begin
        if CharIsInSet(Header, i, Whitespace) then begin
          EncodingFound := false;
          break;
        end;
      end;
    end;

    if EncodingFound then
    begin
      encodingendpos:=PosIdx('?', UpperCase(Header),encodingendpos+1);  {Do not Localize}
      if encodingendpos=0 then
      begin
        EncodingFound := false;
      end else begin
        for i := LEncodingStartPos to encodingendpos-1 do begin
          if CharIsInSet(Header, i, Whitespace) then begin
            EncodingFound := false;
            break;
          end;
        end;
      end;
    end;

    if EncodingFound then
    begin
      encodingendpos:=PosIdx('?=', UpperCase(Header),encodingendpos+1);  {Do not Localize}
      if encodingendpos > 0 then
      begin
        for i := LEncodingStartPos to encodingendpos-1 do begin
          if CharIsInSet(Header, i, Whitespace) then begin
            EncodingFound := false;
            break;
          end;
        end;

        if EncodingFound then begin
          substring:=Copy(Header,LEncodingStartPos,encodingendpos-LEncodingStartPos+2);
          //now decode the substring
          for i := 1 to 3 do
          begin
            l := Pos('?', substring);   {Do not Localize}
            substring := Copy(substring, l+1, Length(substring) - l + 1 );
            if i = 1 then
            begin
              HeaderCharSet := Copy(substring, 1, Pos('?', substring)-1)  {Do not Localize}
            end else if i = 2 then
            begin
              HeaderEncoding := copy(substring,1,1);
            end;
          end;

          //now Substring needs to end with '?=' otherwise give up!    {Do not Localize}
          if Copy(substring,Length(substring)-1,2)<>'?=' then    {Do not Localize}
          begin
            EncodingFound := false;
          end;
        end;

        if (EncodingBeforeEnd>=0) and EncodingFound and (LEncodingStartPos > 0) then begin
          OnlyWhitespace := true;
          for i:=EncodingBeforeEnd to LEncodingStartPos-1 do begin
            if not (CharIsInSet(Header, i, WhiteSpace)) then begin
              OnlyWhitespace := false;
              break;
            end;
          end;
          if OnlyWhitespace then begin
            Delete(Header, EncodingBeforeEnd, LEncodingStartPos-EncodingBeforeEnd);
            encodingendpos := encodingendpos - (LEncodingStartPos-encodingbeforeend);
            LEncodingStartPos := EncodingBeforeEnd;
          end;
        end;

        // Get the HeaderEncoding
        if TextIsSame(HeaderEncoding, 'Q') {Do not Localize}
        and EncodingFound then begin
          i := 1;
          s := '';        {Do not Localize}
          repeat // substring can be accessed by index here, because we know that it ends with '?='    {Do not Localize}
            if substring[i] = '_' then  {Do not Localize}
            begin
              s := s + ' ';    {Do not Localize}
            end else if (substring[i] = '=') and (Length(substring)>=i+2+2) then //make sure we can access i+2 and '?=' is still beyond    {Do not Localize}
            begin
              s := s + chr(StrToInt('$' + substring[i+1] + substring[i+2]));   {Do not Localize}
              inc(i,2);
            end else
            begin
              s := s + substring[i];
            end;
            inc(i);
          until (substring[i]='?') and (substring[i+1]='=')   {Do not Localize}
        end else if EncodingFound then
        begin
          while Length(substring) >= 4 do
          begin
            a4[1] := b64(substring[1]);
            a4[2] := b64(substring[2]);
            a4[3] := b64(substring[3]);
            a4[4] := b64(substring[4]);
            a3[1] := Byte((a4[1] shl 2) or (a4[2] shr 4));
            a3[2] := Byte((a4[2] shl 4) or (a4[3] shr 2));
            a3[3] := Byte((a4[3] shl 6) or (a4[4] shr 0));
            substring := Copy(substring, 5, Length(substring));
            s := s + CHR(a3[1]) + CHR(a3[2]) + CHR(a3[3]);
          end;
        end;

        if EncodingFound then
        begin
          if TextIsSame(HeaderCharSet, 'ISO-2022-JP') then  {Do not Localize}
          begin
            substring := Decode2022JP(s);
          end
          else
            // RHR BEGIN
            if TextIsSame(HeaderCharSet, 'utf-8')
            then begin
              SubString := Utf8ToAnsi(s);
            end
            // RHR END 
            else begin
              substring := s;
            end;

          //replace old substring in header with decoded one:
          header := Copy(header, 1, LEncodingStartPos - 1)
            + substring + Copy(header, encodingendpos + 2, Length(Header));
          encodingendpos := length(substring);
          substring := '';   {Do not Localize}
        end;

      end;
    end;
    encodingendpos := LEncodingStartPos + encodingendpos;
    {CC: Bug fix - changed LEncodingStartPos to LPreviousEncodingStartPos because
     LEncodingStartPos gets overwritten by return value from PosIdx.}

    LPreviousEncodingStartPos := LEncodingStartPos;
    LEncodingStartPos := PosIdx('=?ISO', UpperCase(Header), LPreviousEncodingStartPos + 1); {do not localize}
    if LEncodingStartPos = 0 then begin
      LEncodingStartPos := PosIdx('=?WINDOWS', UpperCase(Header), LPreviousEncodingStartPos + 1); {do not localize}
    end;
    if LEncodingStartPos = 0 then begin
      LEncodingStartPos := PosIdx('=?KOI8', UpperCase(Header), LPreviousEncodingStartPos + 1); {do not localize}
    end;
    // BEGIN RHR //
    if LEncodingStartPos = 0 then begin
      LEncodingStartPos := PosIdx('=?UTF-8', UpperCase(Header), LPreviousEncodingStartPos + 1); {do not localize}
    end;
    // END RHR //

    // delete whitespace between adjacent encoded words, but only
    // if we had an encoding before
    if EncodingFound then begin
      EncodingBeforeEnd := encodingendpos;
    end else begin
      EncodingBeforeEnd := -1;
    end;
  end;
  //There might be #0's in header when this it b64 encoded, e.g with:
  //decodeheader('"Fernando Corti=?ISO-8859-1?B?8Q==?=a" <fernando@nowhere.com>');
  while Pos(#0, header) > 0 do begin
    Delete(header, Pos(#0, header), 1);
  end;
  Result := Header;
end;





Voici la 2eme fonction à remplacer dans l' unité IdMessageClient.pas : 
Mes changements sont marqués par "// RHR" pour que vous sachiez ce que j' ai fait!!!
La fonction est une sous-fonction de la fonction suivante: 
procedure TIdMessageClient.ReceiveBody(AMsg: TIdMessage; const ADelim: string = '.');  {do not localize}

  function ProcessTextPart(ADecoder: TIdMessageDecoder; AUseBodyAsTarget: Boolean = False): TIdMessageDecoder;
  {Only set AUseBodyAsTarget to True if you want the input stream stored in TIdMessage.Body
  instead of TIdText.Body: this happens with some single-part messages.}
  var
    LDestStream: TIdStreamVCL;
    LStringStream: TStringStream;
    i, l: integer;
    LTxt : TIdText;
  begin
    LStringStream := TIdStringStream.Create('');
    try
      LDestStream := TIdStreamVCL.Create(LStringStream);
      try
        LParentPart := AMsg.MIMEBoundary.ParentPart;
        Result := ADecoder.ReadBody(LDestStream, LMsgEnd);
        if AUseBodyAsTarget then begin
          // RHR BEGIN
          if TextIsSame(AMsg.CharSet, 'utf-8') and TextIsSame(AMsg.ContentType, 'text/plain')
          then begin  
            AMsg.Body.Text := LStringStream.DataString; // Utf8ToAnsi(LStringStream.DataString) ne marche pas si le body est trop grand !!!

            for l := 0 to AMsg.Body.Count-1 do
              AMsg.Body[l] := Utf8ToAnsi(AMsg.Body[l]);
          end
          else
          // RHR END
          AMsg.Body.Text := LStringStream.DataString;
        end else begin
          LTxt := TIdText.Create(AMsg.MessageParts);
          LTxt.Body.Text := LStringStream.DataString;
          RemoveLastBlankLine(LTxt.Body);
          if AMsg.IsMsgSinglePartMime then begin
            LTxt.ContentType := LTxt.ResolveContentType(AMsg.Headers.Values[SContentType]);
            LTxt.Headers.Add('Content-Type: '+AMsg.Headers.Values[SContentType]);  {do not localize}
            LTxt.CharSet := LTxt.GetCharSet(AMsg.Headers.Values['Content-Type']);  {do not localize}
            LTxt.ContentTransfer := AMsg.Headers.Values['Content-Transfer-Encoding']; {do not localize}
            LTxt.Headers.Add('Content-Transfer-Encoding: '+AMsg.Headers.Values['Content-Transfer-Encoding']);  {do not localize}
            LTxt.ContentID := AMsg.Headers.Values['Content-ID'];  {do not localize}
            LTxt.ContentLocation := AMsg.Headers.Values['Content-Location'];  {do not localize}
          end else begin
            LTxt.ContentType := LTxt.ResolveContentType(ADecoder.Headers.Values[SContentType]);
            LTxt.Headers.Add('Content-Type: '+ADecoder.Headers.Values[SContentType]);          {do not localize}
            LTxt.CharSet := LTxt.GetCharSet(ADecoder.Headers.Values['Content-Type']);          {do not localize}
            LTxt.ContentTransfer := ADecoder.Headers.Values['Content-Transfer-Encoding']; {do not localize}
            LTxt.Headers.Add('Content-Transfer-Encoding: '+ADecoder.Headers.Values['Content-Transfer-Encoding']);  {do not localize}
            LTxt.ContentID := ADecoder.Headers.Values['Content-ID'];  {do not localize}
            LTxt.ContentLocation := ADecoder.Headers.Values['Content-Location'];  {do not localize}
            LTxt.ExtraHeaders.NameValueSeparator := '=';                          {do not localize}
            for i := 0 to ADecoder.Headers.Count-1 do begin
              if LTxt.Headers.IndexOfName(ADecoder.Headers.Names[i]) < 0 then begin
                LTxt.ExtraHeaders.Add(ADecoder.Headers.Strings[i]);
              end;
            end;
          end;
          if TextIsSame(Copy(LTxt.ContentType, 1, 10), 'multipart/') then begin {do not localize}
            LTxt.ParentPart := LPreviousParentPart;
          end else begin
            LTxt.ParentPart := LParentPart;
          end;

          // RHR BEGIN
          if TextIsSame(LTxt.CharSet, 'utf-8') and TextIsSame(LTxt.ContentType, 'text/plain')   // Sauter si au format HTML ou autre ...
          then
            for l := 0 to Ltxt.Body.Count-1 do
              LTxt.Body[l] := Utf8ToAnsi(LTxt.Body[l]);
          // RHR END
        end;
        ADecoder.Free;
      finally FreeAndNil(LDestStream); end;
    finally FreeAndNil(LStringStream); end;
  end;

Historique

31 juillet 2007 15:05:36 :
Optimisation/Correction de la fonction
31 juillet 2007 16:24:23 :
Prise en compte du Body au format UTF-8 ...
01 août 2007 14:55:37 :
Optimisation utilisant la fonction TextIsSame()

Commentaires et avis

signaler à un administrateur
Commentaire de MAURICIO le 30/07/2007 10:31:45

Salut,
je me suis juste contenté de boucher la lacune qu' il y avait dans le code, j' ai pas cherché à optimiser ...
A+

signaler à un administrateur
Commentaire de MAURICIO le 31/07/2007 15:07:02

Cette fois le Header est mieux décodé!
J' attaque les bodys en UTF-8!!!
A+

signaler à un administrateur
Commentaire de MAURICIO le 31/07/2007 16:25:57

Voila, les bodys sont traités...
NJoy!!!
A+

signaler à un administrateur
Commentaire de MAURICIO le 31/07/2007 17:37:57

TextIsSame est une fonction Indy...
Mais tu as raison: faudra que je change cela même si LTxt.CharSet = 'utf-8' ne pose pas de problème particulier.
A+

signaler à un administrateur
Commentaire de MAURICIO le 31/07/2007 18:38:50

Ouai, vu comme ça, t' as raison lol !!!

signaler à un administrateur
Commentaire de MAURICIO le 01/08/2007 15:20:07

Voilà c' est fait!
il y a encore une petite erreur qui surgit ocasionnellement (du moins je crois) sur le compo IdPOP3 (fonction receiveHeader qui ne renvoie pas le même "Header" selon qu' on appelle la fonction IdPop3.Retrieve ou IdPop3.RetrieveHeader) mais je ne vois pas comment je peux faire ...
Le fait est que avec IdPop3.RetrieveHeader, le charSet est bien informé alors que lorsqu' ensuite je fais IdPop3.Retrieve pour récupérer le message, le CharSet est vide, le Header étant légèrement diférent ... Arg ...

function TIdPOP3.Retrieve(const MsgNum: Integer; AMsg: TIdMessage): Boolean;
begin
  if SendCmd('RETR ' + IntToStr(MsgNum), '') = ST_OK then begin   {Do not Localize}
    AMsg.Clear;
    // This is because of a bug in Exchange? with empty messages. See comment in ReceiveHeader
    if ReceiveHeader(AMsg) = '' then begin
      // Only retreive the body if we do not already have a full RFC
      ReceiveBody(AMsg);
    end;
  end;
  // Will only hit here if ok and NO exception, or IF is not executed
  Result := LastCmdResult.Code = ST_OK;
end;

function TIdPOP3.RetrieveHeader(const MsgNum: Integer; AMsg: TIdMessage): Boolean;
begin
//  Result := False;
  AMsg.Clear;
  SendCmd('TOP ' + IntToStr(MsgNum) + ' 0', ST_OK);    {Do not Localize}
  // Only gets here if no exception is raised
  ReceiveHeader(AMsg,'.');
  Result := True;
end;

Je pense que le problème vient de SendCmd('TOP ' qui renvoie bien le Header alors que SendCmd('RETR ' ne renvoie pas tout à fait le même Header.

A+

signaler à un administrateur
Commentaire de ActiveX le 21/01/2008 20:39:44

Bonjour Mauricio, j'ai un problème, j'ai tous les informations sauf les infos sur les attachements.

j'utilise Indy10 avec delphi entreprise 6

le ExtraHeaders.Text est toujours vide

peux tu m'aider SVP

mon code est le suivant :


      IdMessage.NoDecode := false;
      IdMessage.NoEncode := false;
      IdMessage.ProcessHeaders;
      for i := 0 to IdMessage.MessageParts.Count-1 do
      begin
        // récupération du corps du mail
//        if IdMessage.MessageParts.Items[i].ClassName = 'TIdText' then
//        if IdMessage.MessageParts.Items[i].DisplayName = 'TIdText' then
//        if IdMessage.MessageParts.Items[i] is TIdText then
        if IdMessage.MessageParts.Items[i].ClassName = 'TIdText' then
        begin
          try
            if TIdText(IdMessage.MessageParts.Items[i]).ContentType = 'text/html'then
              ViewerSourceForm.RichHtml.Lines.Add(TIdText(IdMessage.MessageParts.Items[i]).Body.Text)//text/html
            else
              ViewerSourceForm.Body.Lines.Add(TIdText(IdMessage.MessageParts.Items[i]).Body.Text);//text/plain
            if TIdText(IdMessage.MessageParts.Items[i]).Boundary <> '' then
              ViewerSourceForm.Source.Lines.Add(TIdText(IdMessage.MessageParts.Items[i]).Boundary);
            if TIdText(IdMessage.MessageParts.Items[i]).Headers.Text <> '' then
              ViewerSourceForm.Source.Lines.Add(TIdText(IdMessage.MessageParts.Items[i]).Headers.Text);
            if TIdText(IdMessage.MessageParts.Items[i]).ExtraHeaders.Text <> '' then
              ViewerSourceForm.Source.Lines.Add(TIdText(IdMessage.MessageParts.Items[i]).ExtraHeaders.Text);
            ViewerSourceForm.Source.Lines.Add(TIdText(IdMessage.MessageParts.Items[i]).Body.Text);
          except
          end;
        end;
//        if IdMessage.MessageParts.Items[i].ClassName = 'TIdAttachmentFile' then
//        if IdMessage.MessageParts.Items[i].DisplayName = 'TIdAttachmentFile' then
//        if IdMessage.MessageParts.Items[i] is TIdAttachment then
        if IdMessage.MessageParts.Items[i].ClassName = 'TIdAttachmentFile' then
        begin
          try
            ViewerSourceForm.ListBox1.Items.Add(TIdAttachment(IdMessage.MessageParts.Items[i]).FileName);
            if TIdAttachment(IdMessage.MessageParts.Items[i]).Boundary <> '' then
              ViewerSourceForm.Source.Lines.Add(TIdAttachment(IdMessage.MessageParts.Items[i]).Boundary);
            if TIdAttachment(IdMessage.MessageParts.Items[i]).Headers.Text <> '' then
              ViewerSourceForm.Source.Lines.Add(TIdAttachment(IdMessage.MessageParts.Items[i]).Headers.Text);
            if TIdAttachment(IdMessage.MessageParts.Items[i]).ExtraHeaders.Text <> '' then
              ViewerSourceForm.Source.Lines.Add(TIdAttachment(IdMessage.MessageParts.Items[i]).ExtraHeaders.Text);
          except
          end;
        end;
      end;

#############################################################################
CE QUE JE N'AI PAS C'EST CECI

80YnlKSFtJXE1OT0pbXF1eX1VmZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3EQACAgECBAQDBAUGBwcG
BTUBAAIRAyExEgRBUWFxIhMFMoGRFKGxQiPBUtHwMyRi4XKCkkNTFWNzNPElBhaisoMHJjXC0kST
VKMXZEVVNnRl4vKzhMPTdePzRpSkhbSVxNTk9KW1xdXl9VZmdoaWprbG1ub2JzdHV2d3h5ent8f/

#############################################################################

This is a multi-part message in MIME format.

------=_NextPart_000_0008_01C85764.EF744620
Content-Type: multipart/alternative;
boundary="----=_NextPart_001_0009_01C85764.EF744620"


------=_NextPart_001_0009_01C85764.EF744620
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable


----- Original Message -----=20
From: xxxxxxxxxxx
To: xxxxxxxxx
Sent: Monday, January 14, 2008 10:28 AM
Subject: image



------=_NextPart_001_0009_01C85764.EF744620
Content-Type: text/html;
charset="iso-8859-1"
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=3Diso-8859-1">
<META content=3D"MSHTML 6.00.6000.16587" name=3DGENERATOR>
<STYLE></STYLE>
</HEAD>
<BODY bgColor=3D#ffffff>
<DIV>&nbsp;</DIV>
<DIV style=3D"FONT: 10pt arial">----- Original Message -----=20
<DIV style=3D"BACKGROUND: #e4e4e4; font-color: black"><B>From:</B> <A=20
title=xxxxxxxxxxxxxxxx href=3D"mailto:xxxxxxxxxxxxxxx">xxxxxxxxxxxxxxxx</A>=20
</DIV>
<DIV><B>To:</B> <A title=xxxxxxxxxxx=20
href=3D"mailto:xxxxxxxxxx">xxxxxxxxxxxxxx</A> </DIV>
<DIV><B>Sent:</B> Monday, January 14, 2008 10:28 AM</DIV>
<DIV><B>Subject:</B> image</DIV></DIV>
<DIV><BR></DIV>
<DIV>&nbsp;</DIV></BODY></HTML>

------=_NextPart_001_0009_01C85764.EF744620--

------=_NextPart_000_0008_01C85764.EF744620
Content-Type: image/jpeg;name="clefdevoute.jpg"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;filename="clefdevoute.jpg"


CE QUE JE N'AI PAS C'EST CECI

/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB
AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/2wBDAQEBAQEBAQEBAQEBAQEBAQEBAQEB
AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/wAARCAEaAfgDASIA
AhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQA
AAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3
ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWm
p6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEA
AwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSEx
BhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElK
U1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3
uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD+UD9m
YVcL8tFM/wCClaTxeHP2c4iVaWL4U+Aoydsax7R4XX5UaNU3tzks+5ucAjAFFc+RyUsupuKSTqVr
JbaVZLTRaO19jDPv+RpiP+4f/puPr+Z8Hf8ABPt3h/az+GAQNmTV44QAPvhrm1JX6MFJJHPf3r9k
/wBtaySX9lH4zqlvbtPYfGz46TSTG9nS5eM6poxz8xlFwII2x5DbQ2c7128/jR+wGkzftafCSVAP
k8SWh5LKpBuIAeVIyfm6Z49OlfsB+3iXH7L3xKhjQMX+P/x6uZpIAXaOBLzRokSUnd+68zO5zhs/
xY6/O8UJPPctvbXG5Hp/3Uo7dvU+k4WX/CJmv/XjMPW31Pv/AF95/NnRRRX7SfmYUUUU1q9XbzBe

------=_NextPart_000_0008_01C85764.EF744620
Content-Type: image/jpeg;name="Gaff1935662259.jpg"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;filename="Gaff1935662259.jpg"


CE QUE JE N'AI PAS C'EST CECI

80YnlKSFtJXE1OT0pbXF1eX1VmZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3EQACAgECBAQDBAUGBwcG
BTUBAAIRAyExEgRBUWFxIhMFMoGRFKGxQiPBUtHwMyRi4XKCkkNTFWNzNPElBhaisoMHJjXC0kST
VKMXZEVVNnRl4vKzhMPTdePzRpSkhbSVxNTk9KW1xdXl9VZmdoaWprbG1ub2JzdHV2d3h5ent8f/
2gAMAwEAAhEDEQA/AOiZcXO27hPtc0zpq468N9r0UbQZ1G76DiYMD6OjYb7tv/XFUZmNktkbWkgQ
SInRv9r6H9dHL5b7QQNGw06RLXzzscsiw3yCzcxljnbdx1DnACdCPh9JPawFhDpJkgAAkGQ7n+1/
LTMg7R9AGTAM6u+J8tqqZnUcbDYA9wMDSSCRoP3f3kLVRT3GtxMthreR5tduDvb9Fio2scS4fR2j
VoIHJdrDY37IWRf9bai4MrPt84bGn7wBQx9ZQ9hlwjznuT9L+qnCMt+Eqsdw6t+OGV7oa4Tu0GoE
+X/Q/r/TVOzHY5hDSNn0oHA/lbnfS/fVd/XaXAl1jidNRof63/Uqs/rbZI9UuEiZdAPkfvREZdlW
O6+Vj1iSBBkzGhnt9H2/mrmOstYxrgNPCFuXZ4c07I3AAQY7jtt9q53qtxe0gDQ8z+VT4AeIMOUi
jTjxrH4JJJK+1X//0KF2L9Ya4c6uqWgOhlrS6P6vsb3Wj0DrTrnjEu9r2DXdAIIn2uaSuJf9WOvV
5lmym+tlb3fpYeNAZYa7Hfzm7+suj6ZgdRYKr8whl9bmgWaF72un2WtZO97Gj+cas3JCIGkoy/u6
Sb0TInYjz1emvyH1Vvc3T2kEgcRO3/qn71539ZOt33ZDq2mA08/7l6P1OsNwDPZsOIGsx7v6zty8
oycC/Iz3g6BzzudPbyTuVETIyl+iFmcnhAj13Q4NWZm2+nQ3c7x4A/tLaPRm01zldWxqn/uzJOv9
lb/RPqlQ9sPuNdJ4bX7XOE/nWu/6ah9ZvqRTZj0WdKpaHMJF53S924aP97/c2tzU+XMRlOgeCPfh
v7eJbHDUdRxS7XTyOVXfQT9mzKsmOfTOvyVM9QyQYceOZ54WxZ9Tc2ss9wYADve+Gkn/AIOtpd7P
5bk+L9UX5VkG8hvZ0A7jEhrdf7KmjlxVrIS8a/71jOPJegr6uXj5t1lgZE9tNPJGyanls2CIC6rF
+q2Fg1b5LyRBc+ASY3f6+1ZfVqmNLmsEAaeH5UwZomfpC/25CPqLy3pu3bPzklOP1iJ78pK1f5Ne

------=_NextPart_000_0008_01C85764.EF744620--

peux tu m'aider SVP

Merci à l'avance

ActiveX

signaler à un administrateur
Commentaire de MAURICIO le 22/01/2008 10:15:44

Salut ActiveX,

Ce n' est pas en utilisant :
IdMessage.MessageParts.Items[i]).Headers.Text
ou
IdMessage.MessageParts.Items[i]).ExtraHeaders.Text que tu récupère le fichier.

Je te conseille de lire mes 2 autres sources sur Indy pour voir comment faire :

MAILS AVEC INDY:QUE FAIRE (ET POURQUOI) LORSQUE L' ANEXE NE SEMBLE PAS AVOIR DE NOM (FILENAME='') :
http://www.delphifr.com/codes/MAILS-AVEC-INDY-FAIRE-POURQUOI-LORSQUE-ANEXE-NE_44335.aspx

MAILS AVEC INDY10 : CONTENTTYPE/CONTENTID/PARENTPART :
http://www.delphifr.com/codes/MAILS-AVEC-INDY10-CONTENTTYPE-CONTENTID-PARENTPART_45372.aspx

signaler à un administrateur
Commentaire de ActiveX le 22/01/2008 22:47:25

j'ai répété exactement la même chose que toi et cela ne fonctionne pas, peux tu mettres un zip avec un prog qui fonctionne que je puisse les comparer et voir mes erreurs.

merci

ActiveX

Ajouter un commentaire

Discussions en rapport avec ce code source dans le forum

Idtelnet (composant Indy) [ par DarkLago ] Y a t'il quelqu'un qui aurait déjà réaliser une petite application telnet avec le composant IdTelnet dans delphi 6. Si oui un petit code source serait [Indy] Composant TIdPop3Server [ par baloo151 ] Bonjour,Je cherche à réaliser un simple serveur POP3 à partir du programme de démo fourni avec Indy.Je n'arrive pas à faire fonctionner la commande po Composant Indy [ par Squarepusher ] Bonjour, ma question va peut-être paraitre idiote mais j'aimerais en fait savoir si je dois utiliser les composants TIdServerTCP TIdClientTCP pour dev composant Indy [ par Squarepusher ] Bonjour, j'aimerais savoir si il faut utiliser les propriété BoundIP et BoundPort en plus des propriétés Host et Port du composant idTCPClient pour fa COMPOSANT INDY : METTRE EN COPIE DES DESTINATAIRES [ par adjena ] Je suis en train de migrer une application de delphi 5 vers delphi 7. Avec delphi 5 pour mettre en copie les destinataires d'un mail j'utilisais la co Equivalent de chmod pour les composant INDY [ par Isabelle31 ] Bonjour a tous, Je me demandais comment on fait avec un composant INDY, TIdFTP pour modifier les droit d'un utilisteur connect&#233; &#224 composant indy SMTP [ par templeofboom ] bonjour dans une appli je voudrai pouvoir envoyer des mails donc j'utilise le composant idsmtp pour le faire or y a un pti soucis c'est que j'arrive j IdHTTPServer depuis internet [ par ytillang30400 ] Indy 9 :Je place un composant IdHttpServer et dans l'&#233;v&#232;nement OnCommandGet, j'entre par exemple&nbsp;le code : AResponseInfo.ContentText := Envoie e-mail avec indy [ par xt3 ] Salut tout le monde, Voil&#224; mon probl&#232;me : je souhaite envoy&#233; le contenu d'un fichier texte dans un e-mail. Je suis parvenu &#224; charg Composant Indy Aide !!! [ par Rudy3212 ] Best PigJe vait essay&#233; d'&#234;tre explicite ^^.Sur un un ftp je met un .txt qui correspond a la d&#232;rni&#232;re version de mon programme.dans


Nos sponsors

Sondage...

CalendriCode

Juillet 2009
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
2728293031  

Consulter la suite du CalendriCode

Téléchargements

Comparez les prix Nouvelle version

Photothèque Nouveau !



Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés
Temps d'éxécution de la page : 0,671 sec

Google Coop CodeS-SourceS Google Coop CodeS-SourceS


Certaines images présentes sur le site (notament certains avatars) sont issues des collections IconShock, donc si vous souhaitez utiliser ces icons vous devez les acheter, ne les copiez pas et ne utilisez pas dans vos sites et applications sans les avoir commandé.