【发布时间】:2019-09-10 02:24:18
【问题描述】:
使用 Indy 的 idHTTP.post 发送一个或多个任何类型的文件以及其他参数需要使用的正确代码是什么? (使用 Delphi 2009 和 Indy 10)
有问题的帖子调用了商业公司 API (ElasticEmail) 中的一个函数,该函数向其中一个参数中保存的收件人发送电子邮件。 (我正在调用的函数的文档链接是here. 我有来自公司here 的 C# 和其他语言的示例代码,我尝试在下面的 Delphi 代码中复制该代码。
如果,在过程 btnSendbyElastic 中,我注释掉 Filenames.add(Afilename); 行,以便函数 Upload 不会尝试附加文件,那么当 API 成功发送电子邮件时,似乎进行了正确的调用。
但是,如果我保留该行,以便函数 UpLoad 中的行
MimeStr := GetMIMETypeFromFile(filenames[i]);
FormData.Addfile('file'+inttostr(i), filenames[i],MIMEStr);
做被执行,然后没有电子邮件被发送并且来自服务器的响应是
{"success":false,"error":"其中一个文件的文件名中包含无效字符。"}
(文件 Afilename 确实存在于该位置,我已尝试使用单反斜杠和双反斜杠)
阅读有关此主题的其他 SO 帖子,我还尝试将 Function UpLoad 中的文件处理循环替换为以下循环
for i := 0 to filenames.Count - 1 do
begin
MimeStr := GetMIMETypeFromFile(filenames[i]);
FormData.AddFile('file'+inttostr(i), filenames[i],MIMEStr);
AttachmentContent := TFileStream.Create(filenames[i],fmOpenRead);
try
FormData.AddFormField(AttachmentContent.ToString,filenames[i]);
finally
AttachmentContent.free;
end;
end;
这一次,即使使用Filenames.add(Afilename); 中指定的文件名,电子邮件也可以正确发送,但收件人看不到附件。
在许多其他人中,我已经阅读了这些可能重复的 SO 问题
Post a file through https using indy / delphi components
posting a file as part of a form
Nodejs POST request multipart/form-data
特别是
Using the Indy TidHttp component to send email file attachments through sendgrid
(这几乎正是我想要做的)但我仍然看不到我在代码中做错了什么以及我需要做些什么来纠正它。
这是我正在使用的代码(UPPER_CASE 标识符是在别处定义的常量)
PS 我在英国,很抱歉延迟回复美国 cmets/answers
function TForm1.Upload(url: string; params, filenames: Tstringlist): string;
var
FormData : TIdMultiPartFormDataStream;
MIMEStr, ResponseText : string;
i : integer;
begin
try
FormData := TIdMultiPartFormDataStream.Create;
for i := 0 to params.Count - 1 do
FormData.AddFormField(params.Names[i],params.values[params.Names[i]]);
for i := 0 to filenames.Count - 1 do
begin
MimeStr := GetMIMETypeFromFile(filenames[i]);
FormData.Addfile(filenames[i], filenames[i],MIMEStr);
end;
ResponseText :=IdHTTP1.Post(url, FormData);
Memo1.Text := ResponseText; //debug
finally
FormData.free;
end;
end;
procedure TForm1.btnSendbyElastic(Sender: TObject);
var
Params, Filenames : Tstringlist;
url, Afilename : string;
begin
Afilename := 'C:\\Users\\Admin\\Documents\\arrival and departure small.pdf';
Params := Tstringlist.Create;
Filenames := Tstringlist.Create;
try
Params.add('apikey=' + ELASTIC_MAIL_API_KEY) ;
Params.add('from=' + ELASTIC_EMAIL_FROM_EMAIL) ;
Params.add('fromname=' + ELASTIC_EMAIL_FROM_NAME) ;
Params.add('Subject=' + 'The Subject') ;
Params.add('bodyHtml=' + '<h1>Html Body</h1>') ;
Params.add('bodyText=' + 'Text Body') ;
Params.add('to=' + THE_RECIPIENT_ADDRESS) ;
Filenames.add(Afilename); //*** comment out this line and an email is sent correctly
url := ELASTIC_EMAIL_EMAIL_SEND ;
Upload (url , params, filenames );
finally
Params.free;
Filenames.free;
end;
函数GetMIMETypeFromFile 定义在 Indy 单元 idGlobalProtocols 中。不是我写的,就是叫的。但我已经按要求在这里转载了
function GetMIMETypeFromFile(const AFile: TIdFileName): string;
var
MIMEMap: TIdMIMETable;
begin
MIMEMap := TIdMimeTable.Create(True);
try
Result := MIMEMap.GetFileMIMEType(AFile);
finally
MIMEMap.Free;
end;
end;
【问题讨论】:
-
我不明白为什么需要在文件名中添加双斜杠(c#,c 需要这个,而不是 Delphi)。您从 Elastic 得到的错误非常冗长,“文件名中的字符无效”。尝试一些简单的东西,例如“c:\temp\test.txt”。还请附上
GetMIMETypeFromFile的代码,以便我们尝试重现问题... -
@whosrdaddy
GetMIMETypeFromFile()是一个 Indy 函数。 -
啊,汤姆布伦伯格打败了我。无论如何,我已经根据要求编辑了我的帖子以包含它。我同意我不明白为什么我需要双反斜杠。我尝试使用它们,因为 C# 示例有它们,并且在处理网络以及一些 http 调用之前我必须使用它们。无论如何,它们不会给出语法错误,无论我是否使用它们,我都会得到相同的结果。
-
我确实尝试使用更简单的 pdf 文件名,文件名或路径中没有空格,但没有任何区别 - 已发送电子邮件但没有附件。但我认为问题不在于文件名本身。毕竟我不知道我的用户要附加什么文件,也不能坚持他们只附加简单的文件名。
-
我还尝试注释掉
Params.add('bodyHtml=' ...这一行,以便没有发送html正文,因为我在某处听说这可能会导致垃圾邮件过滤器出现问题。但是否有 html 正文和文本没有区别。