4

有一种特殊的 Amazon 消息似乎会抛出 Indy 的 MessagePart 解析器。

该消息的结构(当然是强烈删节的版本)如下:

Content-Type: multipart/mixed;
       boundary="----=_Part_853547_18414509.1354745829993"

<some irrelevant header stuff>

------=_Part_853547_18414509.1354745829993
Content-Type: multipart/alternative;
       boundary="----=_Part_853548_20128671.1354745829993"

------=_Part_853548_20128671.1354745829993
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<the message in plain text>

------=_Part_853548_20128671.1354745829993
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<the message in HTML>

------=_Part_853548_20128671.1354745829993--

------=_Part_853547_18414509.1354745829993--

现在,当我执行

imap.UIDRetrieve(UID,Msg)

然后

Msg.ContentType = "multipart/mixed"

并且个人Msg.MessageParts将其作为内容类型:

Msg.MessageParts[0].ContentType = "multipart/alternative; boundary="----=_Part_853548_20128671.1354745829993""

Msg.MessageParts[1].ContentType = "text/plain"

没有零件的痕迹text/html

有人知道这里发生了什么吗?

(我正在使用最新的 Indy 版本)

4

1 回答 1

6

TIdMessage当我使用当前的 Indy 10 SVN 快照直接运行该电子邮件数据时,它解析得很好。正如预期的那样,MessageParts生成了三个条目 - multipart/alternativetext/plain和-。text/html

您最近在 Embarcadero 论坛上就同一主题发表的帖子中,您遗漏了一条关键信息——您正在使用TIdIMAP4它来检索对您来说失败的电子邮件。这很重要,因为您认为不相关的电子邮件部分必须包含与 Indy 代码相关的数据,该代码具有已知的设计限制,不会在 Indy 10 中修复(但已标记为 Indy 11 的要求)但这会影响TIdIMAP4.

在内部,TIdIMAP4.UIDRetreive()将原始下载的电子邮件按原样传递到TIdMessage.LoadFromStream(). 内部的核心解析器TIdMessage期望使用 IMAP 实际不使用的 SMTP 样式的点透明度对输入数据进行转义。 TIdMessage目前没有任何方式知道输入电子邮件数据的来源,因此无法知道转义数据的格式。更高级别的协议传输负责根据需要解析和解码转义数据,然后应将未转义的数据传递TIdMessage给进一步解析。但现在实际情况并非如此。在 Indy 10 中,这种逻辑分离并没有达到应有的程度。 TIdMessage使用对源数据的直接访问,TIdSMTPTIdPOP3TIdIMAP4.

在该IdMessageClient.pas单元中,有一个名为的助手类TIdIOHandlerStreamMsg,它具有一个公共EscapeLines属性,专门设计用于在需要它的情况下帮助解决此问题(即,将未转义的数据传递给TIdMessage.LoadFrom...()方法)。TIdMessage.LoadFromStream()当前的解决方法不是直接调用,而是实例化 a TIdMessageClient,将 a 分配TIdIOHandlerStreamMsg给它的IOHandler属性,将其EscapeLines属性设置为 True,然后将TStream要解析的源和TIdMessage输出的目标传递给它。这允许 Indy 伪造核心解析器期望取消转义的转义格式。

但是,TIdIMAP4目前尚未使用此解决方法。现在我想了想,应该很容易添加,所以我会研究一下。同时,您可以使用TIdIMAP4.RetrieveNoDecodeToStream()or TIdIMAP4.UIDRetrieveNoDecodeToStream(),这将在写入目标时间接转义数据TStream(另一个需要修复的已知设计限制),然后您可以将其传递TStream给以TIdMessage.LoadFromStream()正常解析。

更新:我刚刚签入了AppendMsg()InternalRetrieve()方法的更新,TIdIMAP4不再依赖于 SMTP 样式的点透明度。这已经在 Indy 的 TODO 列表上好几年了,所以很高兴最终解决它。

于 2012-12-10T06:02:30.907 回答