Indy10 接收邮件正文和标题 出现乱码

本文详细介绍了如何在IdMessageClient.pas文件中修改字符编码处理逻辑,针对UTF-8和其他常见编码进行了解码操作,并对Header部分的编码识别进行了优化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

修改IdMessageClient.pas


//在ProcessTextPart方法中修改
AMsg.Body.Text :=  LStringStream.DataString;
//为
if  IndyUpperCase(AMsg.CharSet) ='UTF-8' then
  AMsg.Body.Text:=UTF8Decode(LStringStream.DataString)
 else
AMsg.Body.Text :=LStringStream.DataString;
//修改 
LTxt.Body.Text:=LStringStream.DataString ;
//为
   LTxt.Body.Text:=UTF8Decode(LStringStream.DataString) ;
   if LTxt.Body.Text='' then
     LTxt.Body.Text:=LStringStream.DataString ;


<pre name="code" class="delphi">//修改IdCoderHeader.pas
//修改DecodeHeader方法如下

function DecodeHeader(Header: string):string;
const
  WhiteSpace = LF+CR+CHAR32+TAB;
var
  i, l: Integer;
  HeaderEncoding,
  HeaderCharSet,
  s: string;
  aDecoder:TIdDecoderMIMELineByLine;
  LEncodingStartPos,encodingendpos:Integer;
  LPreviousEncodingStartPos: integer;
  substring: string;
  EncodingFound: Boolean;
  OnlyWhitespace: boolean;
  EncodingBeforeEnd: integer;
  TCharSet:string;
begin
  // Get the Charset part.
  EncodingBeforeEnd := -1;
  TCharSet:='';
  LEncodingStartPos := PosIdx('=?ISO', Sys.UpperCase(Header), 1); {do not localize}
  if LEncodingStartPos = 0 then begin
    LEncodingStartPos := PosIdx('=?WINDOWS', Sys.UpperCase(Header), 1); {do not localize}
  end;
  if LEncodingStartPos = 0 then begin
    LEncodingStartPos := PosIdx('=?KOI8', Sys.UpperCase(Header), 1); {do not localize}
  end;
  if LEncodingStartPos = 0 then begin
    LEncodingStartPos := PosIdx('=?UTF-8', Sys.UpperCase(Header), 1); {do not localize}
    TCharSet:='utf';
  end;
  if LEncodingStartPos = 0 then begin
    LEncodingStartPos := PosIdx('=?GBK', Sys.UpperCase(Header), 1); {do not localize}
    TCharSet:='';
  end;
  if LEncodingStartPos = 0 then begin
    LEncodingStartPos := PosIdx('=?GB2312', Sys.UpperCase(Header), 1); {do not localize}
    TCharSet:='';
  end;
  if LEncodingStartPos = 0 then begin
    LEncodingStartPos := PosIdx('=?GB18030', Sys.UpperCase(Header), 1); {do not localize}
    TCharSet:='';
  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('?', Sys.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('?', Sys.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('?=', Sys.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(Sys.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}
          s:=UTF8Decode(s);
        end else if EncodingFound then
        begin
           S := Copy(Substring,1,Length(Substring)-2);
           aDecoder := TIdDecoderMIMELineByLine.Create(nil);
           try
              aDecoder.Clear;
              S := aDecoder.DecodeString(S);
              if TCharSet<>'' then s:=UTF8Decode(s);
           finally
              Sys.FreeAndNil(aDecoder);
           end;
        end;

        if EncodingFound then
        begin
          if TextIsSame(HeaderCharSet, 'ISO-2022-JP') then  {Do not Localize}
          begin
            substring := Decode2022JP(s);
          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', Sys.UpperCase(Header), LPreviousEncodingStartPos + 1); {do not localize}
    if LEncodingStartPos = 0 then begin
      LEncodingStartPos := PosIdx('=?WINDOWS', Sys.UpperCase(Header), LPreviousEncodingStartPos + 1); {do not localize}
    end;
    if LEncodingStartPos = 0 then begin
      LEncodingStartPos := PosIdx('=?KOI8', Sys.UpperCase(Header), LPreviousEncodingStartPos + 1); {do not localize}
    end;
    if LEncodingStartPos = 0 then begin
    LEncodingStartPos := PosIdx('=?UTF-8', Sys.UpperCase(Header), 1); {do not localize}
    end;
    if LEncodingStartPos = 0 then begin
      LEncodingStartPos := PosIdx('=?GBK', Sys.UpperCase(Header), 1); {do not localize}
    end;
    if LEncodingStartPos = 0 then begin
      LEncodingStartPos := PosIdx('=?GB2312', Sys.UpperCase(Header), 1); {do not localize}
    end;
    if LEncodingStartPos = 0 then begin
      LEncodingStartPos := PosIdx('=?GB18030', Sys.UpperCase(Header), 1); {do not localize}
    end;
    // 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;




                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值