【发布时间】:2020-07-28 06:03:27
【问题描述】:
在我的项目中,我尝试从 .eml 文件中提取附件。
在正常情况下(字符集 ISO),它可以工作。但是在特殊情况下,它给了我错误的附件文件名。
这是我示例中的 MessagePart 的样子:
------=_Part_315_1401515384.1585891801067
Content-Type: application/octet-stream;
name="=?UTF-8?Q?Report=5F2020-3=5FCustomerA with some spaces in between.csv?="
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
filename="=?UTF-8?Q?Report=5F2020-3=5FCustomerA with some spaces in between.csv?="
UGFydG5lcjtNYW5kYW50ZW5uYW1lO05hbWU7RmlybWE7U3RyYd9lO1Bvc3RsZWl0emFobDtPcnQ7
TGFuZDtQcm9kdWt0bGluaWU7S3VuZGVuc3RhdHVzO0RhdHVtIFJlZ2lzdHJpZXJ1bmc7QmVnaW5u
IEthdWY7S/xuZGlndW5nIGf8bHRpZyBhYjtBbnphaGwgQmVudXR6ZXI7QW56YWhsIE1vYmlsZSBz
eW5jO05ldHRvIFJlY2hudW5nc2JldHJhZyBpbiBFdXJvO1Byb3Zpc2lvbnNzdHVmZTtQcm92aXNp
b25zYW50ZWlsIGluIEV1cm8NCg==
------=_Part_315_1401515384.1585891801067--
到目前为止没有什么了不起的。但由于某种原因,我没有从该附件中获得正确的文件名。
这是我获取该文件的文件名并将其保存到临时位置的代码:
function foo(MyMail: TIdMessage; SavePathWithoutBackSlash : string): boolean;
var
i : Integer;
lfilename: string;
begin
for i := 0 to Pred(MyMail.MessageParts.Count) do
begin
if (MyMail.MessageParts.Items[i] is TIdAttachmentFile) then
begin
lFilename := TIdAttachmentFile(MyMail.MessageParts.Items[i]).FileName;
TIdAttachmentFile(MyMail.MessageParts.Items[i]).SaveToFile(SavePathWithoutBackSlash + '\' + lFilename);
end;
end;
end;
end;
我已经尝试了很多编码,但似乎没有任何影响。
我期望的是这样的字符串:path/Report_2020-3_CustomerA.csv
我得到的是:path/=?UTF-8?Q?Report=5F2020-3=5FCustomerA.csv?=
如何正确保存附件?
【问题讨论】:
-
综合答案很复杂,解决方案要求您递归遍历整个电子邮件层次结构,检查每个节点的
MyMail.ContentType,以确定您是在“节点”上还是在附件上.附言您的示例代码使用 [ii],但您的循环使用 i。 -
你试过DecodeHeader()吗?
-
@nolanspeaker - 你的意思是什么?检查每个 Messagepart 是否为 TIdAttachmentFile。如果它会被Namen保存,我不明白你的意思。顺便提一句。我更正了 ii,感谢提供信息。
-
@Olivier - 我应该如何使用 DecodeHeader?我尝试了 DecodeHeader(TidAttachmentFile.FileName) 但结果是一样的。
-
@olivier - 在这种情况下,我使用 Base64 测试一个可以工作的字符串(=?UTF-8?B?) DecodeHeader 做的一切都是正确的,但在我的示例中它是引用/可打印的(=?UTF -8?Q?) 对此有何建议?
标签: delphi utf-8 email-attachments indy mime