我需要创建一个带有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(最近来自源代码)
答案 0 :(得分:6)
在Delphi的Unicode前版本中,所有内容都基于AnsiString
,您赋予TIdMessage.Subject
属性(以及AnsiString
的任何其他TIdMessage
属性的值,就此而言)必须使用OS默认字符编码进行编码。您将其编码为UTF-8,这将无法正常工作。这是因为TIdMessage
将首先使用操作系统默认编码将Subject
值解码为Unicode,然后使用TIdMessage.OnInitializeISO
事件提供的编码参数对Unicode数据进行MIME编码,或者默认为没有分配事件处理程序(在这种情况下,这些参数是CharSet=UTF-8
和HeaderEncoding=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
。