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

问题描述 投票:0回答:2

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

我发现了以下线程(2011 年),其中 Remy Lebeau 指出,当使用

Name
将对象附加到电子邮件时,可以通过设置
TIdMessageBuilderAttachment
对象的
TIdMessageBuilderHtml
属性来实现此目的:

如何命名TIdMessageBuilderHtml构建的附件文件

然而,虽然听起来很简单,但它似乎对我不起作用。电子邮件已发送,但附件以原始文件名发送,而不是我指定的文件名。

以下是我希望按照我所描述的方式执行的代码片段,但无论出于何种原因,它都没有执行。在这种情况下,我希望文件名显示为

desired_filename.pdf
,但它显示为
undesired_filename.pdf
。出于显而易见的原因,我删除了邮件服务器凭据:

procedure TForm4.Button1Click(Sender: TObject);
var
  FMessageBuilder : TIdMessageBuilderHtml;
  FSMTP : TIdSMTP;
  FMessage : TIdMessage;
  FAttachment : TIdMessageBuilderAttachment;
begin
  FMessage := TIdMessage.Create();
  FMessageBuilder := TIdMessageBuilderHtml.Create;
  FSMTP := TIdSMTP.Create;

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

  FMessage.Sender.Address := '<Insert Sender Address>';
  FMessage.Sender.Name := '<Insert Sender Name>';
  FMessage.From.Address := '<Insert From Address>';
  FMessage.From.Name := '<Insert From Name>';
  FMessage.Recipients.EMailAddresses := '<Insert Recepient Address>';
  FMessage.Subject := 'Attachment Test';

  FSMTP.Host := '<Insert Mail Host>';
  FSMTP.Username := '<Insert Username>';
  FSMTP.Password := '<Insert Password>';
  FSMTP.Connect;
  FSMTP.Send(FMessage);
  FSMTP.Disconnect;
end;

我已经在 D10S 和 XE 中测试了这一点,两者的效果相同。有什么想法我做错了吗?

delphi smtp indy
2个回答
5
投票

使用接受

TIdMessageBuilderAttachments.Add
TStream
重载并将
TIdMessageBuilderAttachment.FileName
属性设置为所需的名称,对我来说在 XE4Indy 10.6.0.4975.

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

3
投票

TIdMessageBuilderAttachment
具有
FileName
Name
属性。将附件添加到构建器时,这些值将分配给添加到
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;

更新:

首次发布此答案后,通过在

WantedFileName
类中添加新的
TIdMessageBuilderAttachment
属性解决了该问题。

您可以将

WantedFileName
设置为您想要的任何值,填充
FileName
时,它将被分配给附件的
TIdMessage
属性。如果
WantedFileName
为空,则将像以前一样使用
TIdMessageBuilderAttachment.FileName
属性。

此外,如果

WantedFileName
属性也为空,则将使用
TIdMessageBuilderAttachment.Name
。因此,您现在可以在一处设置所需的名称,如果需要,它将用于
Content-Type
Content-Disposition
标头,例如:

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

填写

TIdAttachment.FileName
后不再需要手动更新
TIdMessage
属性。

© www.soinside.com 2019 - 2024. All rights reserved.