印地。通过流发送 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()
方法以将您的数据库流考虑在内.
我无法通过流发送附件。 我使用 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()
方法以将您的数据库流考虑在内.