Indy10 POP3接收邮件乱码的解决办法

Indy总有大大小小的Bug,但是有时候你又离不开它,真是进退两难的感觉。最新的Indy10同样有不少的BUG,最近在做邮件接收的一个模块,碰到了令人头痛的乱码问题,一阵研究之后,得出如下心得:

 

在接收邮件的时候,一般是这样的代码:

for i := 1 to MailCount do
begin
IdMessage1.Clear;
FContent := '';
IdMessage1.ContentType := 'Multipart/*';
IdMessage1.CharSet := 'GB2312';
FPOP3.Retrieve(i, IdMessage1);

FFrom := (IdMessage1.From.Text);
FSubject := IdMessage1.Subject;
FFrom := CheckTxt(FFrom);
FSubject := CheckTxt(FSubject);
Fcontent := IdMessage1.Body.Text; 

for j := 0 to pred(IdMessage1.MessageParts.Count) do
begin
if IdMessage1.MessageParts.Items[j] is TIdText then
begin //正文
FContent := FContent + TIdText(IdMessage1.MessageParts.Items[j]).Body.Text;
end;
end;
end;

 

Fcontent := IdMessage1.Body.Text; 这一句保证邮件是SinglePart的时候同样显示内容,但是可能存在乱码,解决方法在下面。

 

首先解决邮件是MultiPart的时候,邮件体乱码的解决方法(方法来源于网上,参见:http://blog.csdn.net/kevinsh/article/details/6163029)

在IdMessageClient单元的ProcessTextPart函数中增加这一段(try和RemoveLastBlankLine(LTxt.Body)之间)

try
//ReadStringsAsContentType(LMStream, LTxt.Body, LHdrs.Values[SContentType], QuoteMIME);
{$IFDEF STRING_IS_ANSI}
cp := GetOEMCP;
LDestEncoding := TIdTextEncoding.GetEncoding(cp);
ReadStringsAsContentType(LMStream, LTxt.Body, LHdrs.Values[SContentType], QuoteMIME, LDestEncoding);
{$ELSE}
ReadStringsAsContentType(LMStream, LTxt.Body, LHdrs.Values[SContentType], QuoteMIME);
{$ENDIF}
RemoveLastBlankLine(LTxt.Body);


改完后,发现GB2312编码的邮件标题和邮件体都存在乱码现象,解决方法如下:

IdGlobalProtocols.pas单元ReadStringsAsCharset改成下面:

procedure ReadStringsAsCharset(AStream: TStream; AStrings: TStrings; const ACharset: String
{$IFDEF STRING_IS_ANSI}; ADestEncoding: TIdTextEncoding = nil{$ENDIF}
);
var
LEncoding: TIdTextEncoding;
cp:Word;
begin
//LEncoding := CharsetToEncoding(ACharset);

{$IFDEF DOTNET_OR_ICONV}
LEncoding := TIdTextEncoding.GetEncoding(ACharSet);
{$ELSE}
CP := CharsetToCodePage(ACharSet);
Assert(CP <> 0);
LEncoding := TIdTextEncoding.GetEncoding(CP);
{$ENDIF}

{$IFNDEF DOTNET}
try
{$ENDIF}
{$IFDEF HAS_TEncoding}
AStrings.LoadFromStream(AStream, LEncoding);
{$ELSE}
//AStrings.Text := ReadStringFromStream(AStream, -1, LEncoding{$IFDEF STRING_IS_ANSI}, ADestEncoding{$ENDIF});
AStrings.Text := ReadStringFromStream(AStream, -1, ADestEncoding);
{$ENDIF}
{$IFNDEF DOTNET}
finally
LEncoding.Free;
end;
{$ENDIF}
end;

 

IdHeaderCoderPlain.pas单元的类方法TIdHeaderCoderPlain.Decode改成这样:

class function TIdHeaderCoderPlain.Decode(const ACharSet: string; const AData: TIdBytes): String;
var
LEncoding: TIdTextEncoding;
LBytes: TIdBytes;
{$IFNDEF DOTNET_OR_ICONV}
CP: Word;
{$ENDIF}
begin
{if ACharSet <> 'GB2312' then
Result := BytesToString(AData, Indy8BitEncoding);
else }
begin
Result := '';
LBytes := nil;
try
{$IFDEF DOTNET_OR_ICONV}
LEncoding := TIdTextEncoding.GetEncoding(ACharSet);
{$ELSE}
CP := CharsetToCodePage(ACharSet);
Assert(CP <> 0);
LEncoding := TIdTextEncoding.GetEncoding(CP);
{$ENDIF}
{$IFNDEF DOTNET}
try
{$ENDIF}
LBytes := AData;
if LEncoding <> TIdTextEncoding.Unicode then begin
LBytes := TIdTextEncoding.Convert(LEncoding, TIdTextEncoding.Unicode, LBytes);
end;
Result := TIdTextEncoding.Unicode.GetString(LBytes, 0, Length(LBytes));
{$IFNDEF DOTNET}
finally
LEncoding.Free;
end;
{$ENDIF}
except
end;
end;
end;

 

重新编译Indy(废话),OK,这样应该能解决绝大多数的邮件乱码问题了。如果您发现了还有什么更好的方法,希望一起交流


转载于:https://www.cnblogs.com/simonl/archive/2011/11/26/2264387.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值