我需要创建一个带有 Unicode 主题的 IdMessage(例如“本语 - 测试”)
我试过设置它使用
Msg.Subject := UTF8Encode(subject);
其中 subject 是包含上述文本的 WideString
但是当我查看编码的主题(通过将消息保存到文件)时,它看起来像这样:
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 将其显示为“本語 - 测试”
关于我哪里出错的任何指示?
Delphi 2006 (pre-unicode), Indy 10 (相当新的来源)
最佳答案
在 Unicode 之前的 Delphi 版本中,所有内容都基于 AnsiString
,您分配给 TIdMessage.Subject
的值属性(以及 AnsiString
的任何其他 TIdMessage
属性,就此而言)必须使用操作系统默认字符编码进行编码。您正在将其编码为 UTF-8,这是行不通的。这是因为 TIdMessage
将首先解码 Subject
使用操作系统默认编码将值转换为 Unicode,然后使用 TIdMessage.OnInitializeISO
提供的编码参数对 Unicode 数据进行 MIME 编码。事件,如果没有分配事件处理程序,则为默认值(在这种情况下,这些参数是 CharSet=UTF-8
和 HeaderEncoding=QuotedPrintable
)。 TIdMessage
没有机制允许您指定用于任何 AnsiString
的编码。您分配给它的数据。所以唯一的可能发送值'本語 - test'
与 Subject
属性是分配您的来源WideString
原样到属性,让 RTL 将数据转换为 AnsiString
使用操作系统默认编码:
Msg.Subject := subject;
但是,如果操作系统不支持正在使用的 Unicode 字符,则会丢失数据。在这种情况下无法避免。
另一种方法是设置
Subject
属性为空字符串,然后使用 TIdMessage.ExtraHeaders
属性,以便您可以提供自己的标题值,该值将按原样放入电子邮件中。使用这种方法,您可以调用 Indy 的 EncodeHeader()
直接发挥作用。在 Unicode 之前的 Delphi 版本中,它有一个可选的 ASrcEncoding
默认为操作系统默认编码的参数(TIdMessage
当前在编码 header 时不提供该参数的值):uses
..., IdCoderHeader;
Msg.Subject := '';
Msg.ExtraHeaders.Values['Subject'] := EncodeHeader(UTF8Encode(subject), '', 'Q', 'UTF-8', IndyTextEncoding_UTF8);
这样,
EncodeHeader()
将能够避免冗余转换,因为它可以检测到源和目标字符编码都是 UTF-8,因此只需按原样对源 UTF-8 数据进行 MIME 编码。更糟糕的是,即使它没有检测到字符编码相同,它也会简单地将源数据使用 UTF-8 解码为 Unicode,然后将其重新编码回 UTF-8。这些是无损转换,因此不会丢失任何数据。仅供引用,您显示的 Unicode 字符的正确编码是:
Subject: =?UTF-8?Q?=E6=9C=AC=E8=AA=9E?= - test
不是
Subject: =?UTF-8?Q?=E6=0C=AC=E8=AA=9E?= - test
正如你所展示的。注意第二个编码的八位字节是
9C
而不是 0C
.
关于delphi - 带有 Unicode 主题的 Indy 消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24651339/