印地。通过流发送 Attach pdf

Indy. sending Attach pdf by stream

我无法通过流发送附件。 我使用 Indy 10.6.2 和 Delphi Berlin。 邮件包含 html 和附加图像,以及直接从数据库插入的一个或多个 PDF 文件。 我在此过程中没有收到任何错误。 邮件已无缝发送,但未收到附件的 PDF。

期待评论

 Msg := TIdMessage.Create(self);
  try
    Msg.ContentType := 'multipart/mixed';
    Msg.From.Name := FromName;
    Msg.From.Address := FromAddress;
    Msg.Priority := mpHigh;
    Msg.Subject := Asunto;

    with TIdMessageBuilderHtml.Create do
      try
        if FMsgTxtPlnPac <> '' then
          PlainText.Text := FMsgTxtPlnPac;

        if FMsgHtmlPac <> '' then
        begin
          Html.Text := FMsgHtmlPac;
          n := 0;
          for s in FMsgHTMLFiles.Split([',']) do
          begin
            n := Succ(n);
            c := 'img' + inttostr(n);
            HTMLFiles.Add(s, c); // cid de imagen en HTML(cid:img1, cid:img2...)
          end;

        end;

        if AttachFiles <> '' then
          for s in AttachFiles.Split([',']) do
            Attachments.Add(s);

        // Attach from DB
        while not dm.qryBlb.Eof do
        begin
          Attach := TIdAttachmentMemory.Create(Msg.MessageParts);
          Attach.ContentType := 'application/pdf';
          Attach.FileName := dm.qryBlb.FieldByName('nombre_archivo').AsString;
          Attach.LoadFromStream(dm.GetDataBlbStrm('DATA_TXT')); // this ok in attach.datastream.size
          Attach.CloseLoadStream;    
          dm.qryBlb.Next;
        end;

        FillMessage(Msg);
      finally
        Free;
      end;

    for s in FMailPac.Split([',']) do
    begin
      EmailAddress := Trim(s);
      if EmailAddress <> '' then
      begin
        with Msg.recipients.Add do
        begin
          Address := EmailAddress;
        end;
      end;
    end;

    for s in MailCC.Split([',']) do
    begin
      EmailAddress := Trim(s);
      if EmailAddress <> '' then
        Msg.CCList.Add.Address := EmailAddress;
    end;

    for s in MailCCO.Split([',']) do
    begin
      EmailAddress := Trim(s);
      if EmailAddress <> '' then
        Msg.BccList.Add.Address := EmailAddress;
    end;

 finally
   SMTP1.Send(Msg);
 end;

TIdMessageBuilderHtml 支持通过流和文件添加附件。但是,这些流必须在填充 TIdCustomMessageBuilder.Attachments 集合期间保持活动状态,这在您的情况下不是一个选项,因为您一次循环一个数据库记录,因此您只能访问一次 1 个 DB 流。

您可以创建 TMemoryStream 个对象的本地 array/list,然后用这些流填充 TMessageBuilderHtml,但是您最终会浪费大量内存,因为 TIdMessageBuilderHtml 会制作自己的 TMemoryStream 数据副本。而且没有办法 TIdMessageBuilderHtml 在只读模式下按原样使用你的 TMemoryStream 数据(嗯,我想知道我是否应该添加该功能!)。

您的手动 TIdAttachmentMemory 对象不起作用的原因仅仅是因为 TIdCustomMessageBuilder.FillMessage() 在重新填充之前清除了 TIdMessage 的主体,从而丢失了您的附件(以及您事先手动设置的各种其他属性)。

FillMessage() 首先完成其工作后,您必须将数据库附件添加到 TIdMessage 。但是,您可能 TIdMessageBuilderHtml 没有正确设置 TIdMessage 结构,因为它不知道您的数据库附件存在。

附带说明一下,您没有正确使用 TIdAttachmentMemory。如果您没有先调用它的 OpenLoadStream() 方法,请不要调用它的 CloseLoadStream() 方法。在这种情况下调用其 LoadFromStream() 方法就足够了(或者,您甚至可以将 TStream 传递给 TIdAttachmentMemory 的构造函数)。但是请注意,您正在泄漏 dm.GetDataBlbStrm().

返回的 TStream

因此,在这种情况下,您最好手动填充 TIdMessage 而根本不使用 TIdMessageBuilderHtml。或者,您可以从 TIdMessageBuilderHtml(或直接 TIdCustomMessageBuilder)派生一个新的 class 并覆盖其虚拟 FillBody()FillHeaders() 方法以将您的数据库流考虑在内.