带有Unicode主题的Indy消息

时间:2014-07-09 10:33:29

标签: delphi unicode indy

我需要创建一个带有Unicode主题的IdMessage(例如“本语 - 测试”)

我尝试使用

进行设置
Msg.Subject := UTF8Encode(subject);

其中subject是包含上述文本的WideString 但是当我查看编码主题时(通过将Message保存到文件中),它看起来像这样:

Subject: =?UTF-8?Q?=C3=A6=C5=93=C2=AC=C3=A8=C2=AA=C5=BE?= - test

而不是

Subject: =?UTF-8?Q?=E6=0C=AC=E8=AA=9E?= - test

并且Outlook将其显示为“本語 - test”

关于我哪里出错的指示?

Delphi 2006(pre-unicode),Indy 10(最近来自源代码)

1 个答案:

答案 0 :(得分:6)

在Delphi的Unicode前版本中,所有内容都基于AnsiString,您赋予TIdMessage.Subject属性(以及AnsiString的任何其他TIdMessage属性的值,就此而言)必须使用OS默认字符编码进行编码。您将其编码为UTF-8,这将无法正常工作。这是因为TIdMessage将首先使用操作系统默认编码将Subject值解码为Unicode,然后使用TIdMessage.OnInitializeISO事件提供的编码参数对Unicode数据进行MIME编码,或者默认为没有分配事件处理程序(在这种情况下,这些参数是CharSet=UTF-8HeaderEncoding=QuotedPrintable)。 TIdMessage没有机制允许您指定用于分配给它的任何AnsiString数据的编码。因此,使用'本語 - test'属性发送Subject值的唯一可能性是将源WideString按原样分配给属性,然后让RTL将数据转换为{{1}使用操作系统默认编码:

AnsiString

但是,如果操作系统不支持使用的Unicode字符,则会丢失数据。在这种情况下无法避免这种情况。

另一种方法是将Msg.Subject := subject; 属性设置为空字符串,然后使用Subject属性,以便您可以提供自己的标头值,该标头值将按原样放入电子邮件中。使用这种方法,您可以直接调用Indy的TIdMessage.ExtraHeaders函数。在Unicode的Unicode前版本中,它有一个可选的EncodeHeader()参数,默认为操作系统默认编码(ASrcEncoding当前在编码标题时不提供该参数的值):

TIdMessage

这样,uses ..., IdCoderHeader; Msg.Subject := ''; Msg.ExtraHeaders.Values['Subject'] := EncodeHeader(UTF8Encode(subject), '', 'Q', 'UTF-8', IndyTextEncoding_UTF8); 将能够避免冗余转换,因为它可以检测到源和目标字符编码都是UTF-8,因此只需对源UTF-8数据进行MIME编码 - 是。更糟糕的情况是,即使它没有检测到字符编码是相同的,它也只是使用UTF-8将源数据解码为Unicode,然后将其重新编码回UTF-8。这些是无损转换,因此不会丢失任何数据。

FYI,您显示的Unicode字符的正确编码是:

EncodeHeader()

Subject: =?UTF-8?Q?=E6=9C=AC=E8=AA=9E?= - test

如你所示。请注意,第二个编码的八位位组是Subject: =?UTF-8?Q?=E6=0C=AC=E8=AA=9E?= - test 而不是9C