我正在尝试将报告导出为 PDF,然后将其附加到电子邮件和/或彩信中。我将 TFileStream 编码为 TStringStream,然后将其附加到电子邮件,但是 使用相同的 TStringStream,我将其附加到彩信,它按预期工作。 Indy 方法似乎适用于流,我做错了什么?
编辑:电子邮件附件和电子邮件正文显示在附加文件中,这就是它不可读的原因。如果我对附件的内容进行 Base64 解码,它就可以工作。
有什么想法为什么会发生这种情况吗?
ReportPdf := TStringStream.Create;
try
if (CreateReportPdf(QuickRep1, ReportPdf, QryInfoPrintNumber.AsString, 'REPORT', IsReprint)) then
begin
if (Assigned(ReportPdf)) then
begin
SendReceiptEmail(ReportPdf, QryInfoPrintNumber.AsString, 'REPORT', QryReportName.AsString, 'Test', QryInfoReplyToEmailAddress.AsString);
SendReceiptSMS(ReportPdf, QryInfoPrintNumber.AsString, 'REPORT', QryReportName.AsString, 'Test');
end;
end;
finally
ReportPdf.Free;
end;
这里是导出报告的位置。这按预期工作。
function CreateReportPdf(QuickRep: TQuickRep; var ReportPdf: TStringStream; const PrintNumber, ReportName: string; const IsReprint: Boolean): Boolean;
var
aPdf: TQRPDFDocumentFilter;
tmpPath, tmpFileName: string;
fs: TFileStream;
begin
Result := False;
if (not Assigned(QuickRep)) then
Exit;
tmpPath := GetSpecialFolderPath(CSIDL_LOCAL_APPDATA) + '\Temp\';
tmpFileName := CreateTmpFileName(tmpPath, Format('%s_%s', [ReportName, PrintNumber]), '.pdf');
aPdf := TQRPDFDocumentFilter.Create(tmpPath + tmpFileName);
fs := nil;
try
try
aPdf.CompressionOn := True;
aPdf.PageLength := 11;
QuickRep.ExportToFilter(aPdf);
fs := TFileStream.Create(tmpPath + tmpFileName, fmOpenRead);
fs.Position := 0;
TNetEncoding.Base64.Encode(fs, ReportPdf);
Result := True;
except
ShowMessage('Failed to create report PDF.');
Result := False;
end;
finally
aPdf.Free;
fs.Free;
end;
end;
我尝试解码 Base64(见下文)——没有帮助。
procedure SendReportEmail(ReportPdf: TStringStream; const PrintNumber, ReportName, Recipients, MessageText, ReplyTo: string);
var
Attachment: TStringList;
Host: string;
Port: Integer;
// ReportPdfDecoded: TStringStream;
I: Integer;
begin
if (ReportPdf.DataString.Length > 0) then
begin
ReportPdf.Position := 0;
// ReportPdfDecoded := TStringStream.Create;
Attachment := TStringList.Create();
try
// TNetEncoding.Base64.Decode(ReportPdf, ReportPdfDecoded);
// Attachment.AddObject('stream/pdf', ReportPdfDecoded);
Attachment.AddObject('stream/pdf', ReportPdf);
Host := GetConfigValue(cCFG_EMAIL_HOST).AsString;
Port := GetConfigValue(cCFG_EMAIL_PORT).AsInteger;
From := GetConfigValue(cCFG_EMAIL_FROM).AsString;
Lib.SendEmail(Host, From, Recipients, ReportName + '_' + PrintNumber,
MessageText, '', '', ReplyTo, Port, False, Attachment);
finally
for I := Attachment.Count -1 downto 0 do
Attachment.Objects[I].Free;
Attachment.Free;
// ReportPdfDecoded.Free;
end;
end;
end;
我在这里遗漏了一些明显的东西吗?感谢您的关注。
procedure SendEmail(Host, From, Recipients, Subject, Body, CC, BCC, ReplyTo: string; Port: Integer; IsBodyHtml: Boolean; Attachments: TStrings);
var
IdSMTP: TIdSMTP;
IdMessage: TIdMessage;
builder: TIdCustomMessageBuilder;
s: Integer;
begin
IdSMTP := TIdSMTP.Create(nil);
IdMessage := TIdMessage.Create(nil);
try
if IsBodyHtml then
begin
builder := TIdMessageBuilderHtml.Create;
TIdMessageBuilderHtml(builder).Html.Text := Body
end
else
begin
builder := TIdMessageBuilderPlain.Create;
end;
try
if (Assigned(Attachments)) then
begin
IdMessage.ContentType := 'multipart/mixed';
for s := 0 to Attachments.Count -1 do
begin
if (Attachments.Strings[s] = 'stream/pdf') then
begin
builder.PlainTextCharSet := 'utf-8';
builder.Attachments.Add(TStringStream(attachments.Objects[s]), 'application/pdf');
end
else
builder.Attachments.Add(attachments.ValueFromIndex[s]);
end;
end;
builder.FillMessage(IdMessage);
finally
builder.Free;
end;
IdMessage.From.Address := From;
IdMessage.Recipients.EMailAddresses := Recipients;
IdMessage.Subject := Subject;
IdMessage.Body.Text := Body;
IdMessage.CCList.EMailAddresses := CC;
IdMessage.BccList.EMailAddresses := BCC;
IdMessage.ReplyTo.EMailAddresses := ReplyTo;
if not IsBodyHtml then
IdMessage.Body.Text := Body;
try
IdSMTP.Host := Host;
IdSMTP.Port := Port;
IdSMTP.Connect;
IdSMTP.Send(IdMessage);
IdSMTP.Disconnect;
finally
IdSMTP.Free;
end;
finally
IdMessage.Free;
end;
end;
在使用 Indy 通过电子邮件发送 PDF 之前,无需手动对 PDF 进行 Base64 编码(如果您需要 Base64 进行 SMS,则应在发送 SMS 时单独处理)。 Indy 的
TIdMessage
组件可以为您处理 base64,因此只需按原样附加原始 PDF 并将其 ContentTransfer
属性设置为 'base64'
。由于您要将 PDF 存储到 TStream
中,然后将其附加到电子邮件中,因此您应该仅存储 PDF 的原始字节(即使用 TMemoryStream
或 TFileStream
),不要存储预编码版本PDF 的。
尝试更多类似这样的事情:
ReportPdf := TMemoryStream.Create;
try
if CreateReportPdf(QuickRep1, ReportPdf, QryInfoPrintNumber.AsString, 'REPORT', IsReprint) then
begin
SendReceiptEmail(ReportPdf, QryInfoPrintNumber.AsString, 'REPORT', QryReportName.AsString, 'Test', QryInfoReplyToEmailAddress.AsString);
...
end;
finally
ReportPdf.Free;
end;
function CreateReportPdf(QuickRep: TQuickRep; ReportPdf: TMemoryStream; const PrintNumber, ReportName: string; const IsReprint: Boolean): Boolean;
var
aPdf: TQRPDFDocumentFilter;
tmpPath, tmpFileName: string;
begin
Result := False;
if not Assigned(QuickRep) then
Exit;
tmpPath := GetSpecialFolderPath(CSIDL_LOCAL_APPDATA) + '\Temp\';
tmpFileName := CreateTmpFileName(tmpPath, Format('%s_%s', [ReportName, PrintNumber]), '.pdf');
try
aPdf := TQRPDFDocumentFilter.Create(tmpPath + tmpFileName);
try
aPdf.CompressionOn := True;
aPdf.PageLength := 11;
QuickRep.ExportToFilter(aPdf);
ReportPdf.LoadFromFile(tmpPath + tmpFileName);
Result := True;
finally
aPdf.Free;
end;
except
ShowMessage('Failed to create report PDF.');
end;
end;
procedure SendReportEmail(ReportPdf: TMemoryStream; const PrintNumber, ReportName, Recipients, MessageText, ReplyTo: string);
var
Attachment: TStringList;
Host, From: string;
Port: Integer;
begin
if ReportPdf.Size > 0 then
begin
ReportPdf.Position := 0;
Attachment := TStringList.Create;
try
Attachment.AddObject('stream/pdf', ReportPdf);
Host := GetConfigValue(cCFG_EMAIL_HOST).AsString;
Port := GetConfigValue(cCFG_EMAIL_PORT).AsInteger;
From := GetConfigValue(cCFG_EMAIL_FROM).AsString;
Lib.SendEmail(Host, From, Recipients, ReportName + '_' + PrintNumber,
MessageText, '', '', ReplyTo, Port, False, Attachment);
finally
Attachment.Free;
end;
end;
end;
procedure SendEmail(Host, From, Recipients, Subject, Body, CC, BCC, ReplyTo: string; Port: Integer; IsBodyHtml: Boolean; Attachments: TStrings);
var
IdSMTP: TIdSMTP;
IdMessage: TIdMessage;
builder: TIdMessageBuilderHtml;
attach: TIdMessageBuilderAttachment;
I: Integer;
begin
IdMessage := TIdMessage.Create(nil);
try
builder := TIdMessageBuilderHtml.Create;
try
builder.PlainTextCharSet := 'utf-8';
builder.HtmlCharSet := 'utf-8';
if IsBodyHtml then
builder.Html.Text := Body
else
builder.PlainText.Text := Body;
if Assigned(Attachments) then
begin
for I := 0 to Attachments.Count - 1 do
begin
if Attachments.Strings[I] = 'stream/pdf' then
begin
attach := builder.Attachments.Add(TMemoryStream(attachments.Objects[I]), 'application/pdf');
attach.ContentTransfer := 'base64';
else
attach := builder.Attachments.Add(attachments.ValueFromIndex[I]);
// optional: set attach.WantedFileName or attach.FileName if desired...
end;
end;
builder.FillMessage(IdMessage);
finally
builder.Free;
end;
IdMessage.From.Address := From;
IdMessage.Recipients.EMailAddresses := Recipients;
IdMessage.Subject := Subject;
IdMessage.CCList.EMailAddresses := CC;
IdMessage.BccList.EMailAddresses := BCC;
IdMessage.ReplyTo.EMailAddresses := ReplyTo;
IdSMTP := TIdSMTP.Create(nil);
try
IdSMTP.Host := Host;
IdSMTP.Port := Port;
IdSMTP.Connect;
try
IdSMTP.Send(IdMessage);
finally
IdSMTP.Disconnect;
end;
finally
IdSMTP.Free;
end;
finally
IdMessage.Free;
end;
end;