使用TIdMessageBuilderHtml设置电子邮件附件名称

时间:2016-03-04 10:03:09

标签: delphi smtp indy

我尝试使用Delphi(D10S)将PDF文档附加到电子邮件中,并且我希望将名称设置为文件系统上文件名以外的名称。

我找到了以下帖子(2011年),其中Remy Lebeau声明您可以通过使用{{1}将Name对象附加到电子邮件时设置TIdMessageBuilderAttachment属性来实现此目的}:

  

How to name attachment files constructed by TIdMessageBuilderHtml

但是,听起来很简单,它似乎对我不起作用。电子邮件通过,但附件是原始文件名,而不是我指定的文件名。

以下是我希望按照我所描述的方式执行的代码片段,但无论出于何种原因,它都没有。在这种情况下,我希望文件名为TIdMessageBuilderHtml,但它会以desired_filename.pdf的形式出现。我出于显而易见的原因删除了邮件服务器凭据:

undesired_filename.pdf

我在D10S和XE中对此进行了测试,两者都做了同样的事情。我有什么想法我做错了吗?

2 个答案:

答案 0 :(得分:5)

使用TIdMessageBuilderAttachments.Add重载接受TStream并将TIdMessageBuilderAttachment.FileName属性设置为所需名称,这对我来说就是 XE4 Indy 10.6.0.4975。

stream := TFileStream.Create('c:\undesired_filename.pdf', fmOpenRead);
FAttachment := FMessageBuilder.Attachments.Add(stream, 'application/pdf');
FAttachment.FileName := 'desired_filename.pdf';

答案 1 :(得分:3)

TIdMessageBuilderAttachment同时拥有FileNameName属性。向构建器添加附件时,会将这些值分配给TIdAttachment对象的相应属性,这些属性将添加到TIdMessage.MessageParts集合中。

如果附件分配了Name,则该值会放在name标题的Content-Type属性中,例如:

Content-Type: media/type; name="desired_filename.pdf"

如果附件分配了FileName,则该值会放在filename标题的Content-Disposition属性中,例如:

Content-Disposition: attachment; filename="undesired_filename.pdf"

如果两个标题都存在,符合标准的读者在查找文件名时将优先Content-Disposition。这就是为什么您的读者显示不需要的文件名。

向构建器添加物理文件时,TIdMessageBuilderAttachment当前不允许您指定与真实文件不同的FileName。这是因为TIdMessageBuilderAttachment不是实际加载文件的那个。它只是创建一个新的TIdAttachmentFile对象并将其FileName分配给该对象,因此它需要真实的文件名,否则在发送电子邮件时附件将无法加载。但是,TIdAttachmentFile确实允许在创建后自定义FileName。它有一个单独的StoredPathName属性来跟踪物理文件,因此它的FileName可以是您想要的任何内容。

在@ fantaghirocco的示例中,向构建器添加TStream会导致TIdAttachmentMemory添加到TIdMessage而不是TIdAttachmentFile。由于不涉及物理文件,因此附件的FileName可以是您想要的任何内容。

因此,必须更新TIdMessageBuilderAttachment以允许将物理文件附件FileName与其StoredPathName分开设置。在此期间,您可以在TIdAttachmentFile.FileName填写后手动更新TIdMessage属性,例如:

FAttachment := FMessageBuilder.Attachments.Add('c:\undesired_filename.pdf');
FAttachment.Name := 'desired_filename.pdf';
FMessageBuilder.FillMessage(FMessage);

for I := 0 to FMessage.MessageParts.Count-1 do
begin
  if FMessage.MessageParts[I].PartType = mptAttachment then
    FMessage.MessageParts[I].FileName = FMessage.MessageParts[I].Name;
end;