Delphi升级至11.3后Indy发送网络共享附件速度异常求助
问题排查与优化方案
一、网络共享附件发送缓慢问题排查
核心原因推测
- Indy默认网络文件读取逻辑缺陷:TIdAttachmentFile直接读取网络共享文件时,默认使用较小的IO缓冲(通常32KB),导致频繁发起跨网络IO请求,叠加网络延迟后总耗时剧增。
- Delphi 11.3 RTL文件API变动:升级后RTL对SMB协议的文件访问策略调整,默认缓存机制不适合网络共享文件,加剧读取等待。
- 主线程阻塞的调度影响:主线程执行同步发送时,系统对其网络IO的调度优先级低于后台线程,进一步拉长等待时间。
可疑代码点(基于常规Indy邮件实现)
若你的代码是直接通过共享路径创建附件,类似以下写法,这就是核心低效点:
vMsgBuilder := TIdMessageBuilderHtml.Create; try vMsgBuilder.plainText.Text := '邮件内容'; vMsgBuilder.Attachments.Add('\\server\share\file1.txt'); vMsgBuilder.Attachments.Add('\\server\share\file2.txt'); vMsgBuilder.FillMessage(vIdMessage); finally vMsgBuilder.Free; end; vIdSMTP.Send(vIdMessage);
解决措施
- 本地缓存后发送:先将共享文件复制到本地临时目录,避免直接跨网络读取:
var TempFile1, TempFile2: string; begin TempFile1 := TPath.GetTempFileName; TempFile2 := TPath.GetTempFileName; try CopyFile(PChar('\\server\share\file1.txt'), PChar(TempFile1), False); CopyFile(PChar('\\server\share\file2.txt'), PChar(TempFile2), False); // 用临时文件创建附件 vMsgBuilder.Attachments.Add(TempFile1); vMsgBuilder.Attachments.Add(TempFile2); vMsgBuilder.FillMessage(vIdMessage); vIdSMTP.Send(vIdMessage); finally DeleteFile(TempFile1); DeleteFile(TempFile2); end; end; - 增大Indy文件读取缓冲:手动调整TIdAttachmentFile的
FileBufferSize,减少IO次数:var Attachment: TIdAttachmentFile; begin Attachment := TIdAttachmentFile.Create(vIdMessage.MessageParts, '\\server\share\file1.txt'); Attachment.FileBufferSize := 1024 * 1024; // 设置为1MB缓冲 // 第二个附件同理 end; - 后台线程执行发送:将邮件发送逻辑放到后台线程,避免阻塞主线程,同时提升网络IO调度优先级:
TTask.Run(procedure begin // 邮件发送完整逻辑放在此处 // 若需更新UI,用TThread.Synchronize或TThread.Queue同步 end);
二、纯文本带附件的更优Indy用法
TIdMessageBuilderHtml是为HTML邮件设计的,纯文本场景下直接操作TIdMessage更高效,无需经过HTML构建层:
示例代码
var vIdMessage: TIdMessage; vIdSMTP: TIdSMTP; begin vIdMessage := TIdMessage.Create(nil); try vIdMessage.From.Address := 'sender@domain.com'; vIdMessage.Recipients.Add('recipient@domain.com'); vIdMessage.Subject := '纯文本邮件带附件'; // 设置纯文本内容 vIdMessage.Body.Text := '这是纯文本邮件内容'; // 直接添加附件,无需构建器 TIdAttachmentFile.Create(vIdMessage.MessageParts, 'local_file.txt'); TIdAttachmentFile.Create(vIdMessage.MessageParts, '\\server\share\file.txt'); vIdSMTP := TIdSMTP.Create(nil); try vIdSMTP.Host := 'smtp.domain.com'; vIdSMTP.Port := 587; vIdSMTP.Username := 'your_username'; vIdSMTP.Password := 'your_password'; vIdSMTP.Connect; try vIdSMTP.Send(vIdMessage); finally vIdSMTP.Disconnect; end; finally vIdSMTP.Free; end; finally vIdMessage.Free; end; end;
优势
- 跳过HTML构建器的冗余逻辑,减少对象创建和内存开销。
- 直接操作TIdMessage的核心属性,逻辑更简洁,性能更优。
内容的提问来源于stack exchange,提问作者Roland Bengtsson
相关产品推荐
相关产品推荐

