消息客户端如何读取indy下载的附件?

时间:2014-07-06 02:46:11

标签: delphi indy indy10

我有一个使用Indy库在delphi中编写的消息客户端,它接收电子邮件消息。我在解码MMS短信电子邮件时遇到了困难。

这些消息来自multipart/mixed个电子邮件,其中一个消息部分(附件)为text/plain(即base64编码),文件名为text0.txt

我的TIdMessageClient调用ProcessMessage(使用基于流的版本)来填充我将在屏幕上显示的TidMessage。但是当我浏览消息部分并试图解开它们时,那​​个附加文件就是我身边的一根刺。目前,我将附件的名称打印成一个正常工作的字符串(请参阅下面的代码片段,FBody是字符串类型),但无法获取文本文件的内容。

以下是有效的方法:

FBody := 'Attachment: ['+TidAttachment(Msg.MessageParts.Items[0]).FileName+']';

(编辑:)最初当我写这个问题时,我不确定附件是否存储在TidAttachmentFile或TidAttachmentMemory对象中。但是使用正确的调试器命令,我确定它是一个TidAttachmentFile。我想可以使用TidAttachmentFile.SaveToFile()将附件保存到磁盘上的文件,然后从磁盘读回文件,但这似乎浪费和缓慢(特别是对于200字符的文本消息)。如果可能的话,我真的更喜欢在没有临时文件的情况下“在内存中”执行此操作。

我需要做什么(a)使TidMessageClient返回TidAttachmentMemory对象而不是TidAttachmentObject(在ProcessMessage中),以及(b)将附加的文本文件读成字符串?

根据indy文档,我对这段代码看起来的起点大致如下:

TidAttachmentMemory(Msg.MessageParts.Items[0]).PrepareTempStream();
FBody := FBody + TidAttachmentMemory(Msg.MessageParts.Items[0]).DataString;
TidAttachmentMemory(Msg.MessageParts.Items[0]).FinishTempStream;

如果这不是正确的方式或使用TidAttachment(s),请随时指出我正确的方向。

1 个答案:

答案 0 :(得分:3)

  

我想可以使用TidAttachmentFile.SaveToFile()将附件保存到磁盘上的文件中,然后从磁盘读回文件,但这看起来很浪费和慢(特别是对于200个字符的文本消息)。

使用TIdAttachmentFile时,文件始终位于磁盘上。 TIdAttachmentFile.StoredPathName属性指定实际文件的路径。 TIdAttachmentFile.SaveToFile()方法仅将文件复制到指定位置。

  

我真的更喜欢这样做#34;在记忆中#34;如果可能的话,没有临时文件。

有可能。

  

我需要做什么(a)使TidMessageClient返回TidAttachmentMemory对象而不是TidAttachmentObject(在ProcessMessage中)

TIdMessage.OnCreateAttachment事件中,返回TIdAttachmentMemory个对象,例如:

procedure TMyForm.IdMessage1CreateAttachment(const AMsg: TIdMessage; const AHeaders: TStrings; var AAttachment: TIdAttachment);
begin
  AAttachment := TIdAttachmentMemory.Create(AMsg.MessageParts);
end;

如果没有为TIdMessage.OnCreateAttachment事件分配处理程序,或者没有为AAttachment分配任何内容,则默认情况下会创建TIdAttachmentFile

您可以选择实现自己的自定义TIdAttachment派生类,如果您知道附件包含文本数据(TStringStream参数会告诉您,请在内部使用AHeaders )。

  

和(b)将附加的文本文件读成字符串?

     

根据indy文档,我对这段代码看起来的起点大致如下:

你很亲密。您需要使用TIdAttachment.OpenLoadStream()方法而不是TIdAttachment.PrepareTempStream(),并且需要读取TStream返回TIdAttachment.OpenLoadStream()的数据。在您的示例中,您可以使用Indy的ReadStringFromStream()函数,例如:

// if using Indy 10.6 or later...
var
  Attachment: TIdAttachment;
  Strm: TStream;
 begin
  ...
  Attachment := TIdAttachment(Msg.MessageParts.Items[0]);
  Strm := Attachment.OpenLoadStream;
  try
    FBody := FBody + ReadStringFromStream(Strm, -1, CharsetToEncoding(Attachment.Charset));
  finally
    Attachment.CloseLoadStream;
  end;
  ...
end;

或者:

// if using Indy 10.5.x or earlier...
var
  Attachment: TIdAttachment;
  Strm: TStream;
  Enc: TIdTextEncoding;
 begin
  ...
  Attachment := TIdAttachment(Msg.MessageParts.Items[0]);
  Strm := Attachment.OpenLoadStream;
  try
    Enc := CharsetToEncoding(Attachment.Charset);
    try
      FBody := FBody + ReadStringFromStream(Strm, -1, Enc);
    finally
      Enc.Free;
    end;
  finally
    Attachment.CloseLoadStream;
  end;
  ...
end;