在我的项目中,我尝试从.eml文件中提取附件。在正常条件下(字符集ISO),它可以工作。但是在特殊情况下,它为附件提供了拧紧的文件名。
这是我的示例中的messagepart看起来像:
------=_Part_315_1401515384.1585891801067
Content-Type: application/octet-stream;
name="=?UTF-8?Q?Report=5F2020-3=5FCustomerA.csv?="
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
filename="=?UTF-8?Q?Report=5F2020-3=5FCustomerA.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?=
如何正确保存附件?
向@olivier致谢,我找到了该问题的解决方案。它是2个问题的组合。
第一个问题:
TIdAttachmentFile(MyMail.MessageParts.Items[i]).FileName
不返回=?UTF-8?Q?它返回= _UTF-8_Q_所以我将其更改为
TIdAttachmentFile(MyMail.MessageParts.Items[i]).Name
-
第二个问题:
根据RFC2047的=?...?=
之间不允许有空格。因此DecodeHeader将保持字符串不变。我的代码现在可以正常工作,如下所示:
Uses
...IdAttachmentFile, IdMessage, IdCoderHeader...
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]).Name;
if pos('=?UTF-8?Q?',uppercase(lfilename)) > 0 then
begin
lfilename:=StringReplace(lFilename,' ','=20',[rfReplaceAll,rfIgnoreCase]);
end;
lFileName:= DecodeHeader(lFileName);
TIdAttachmentFile(MyMail.MessageParts.Items[i]).SaveToFile(SavePathWithoutBackSlash + '\' + lFilename);
end;
end;
end;
end;
= 20是带引号可打印的UTF-8中空白的正确符号