You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Indy正确发送含Base64嵌入式图片的HTML邮件?

问题描述

我希望用Indy发送带有嵌入式图片的邮件,HTML模板里包含Base64格式的图片。测试用HTML模板如下:

<html>
  <head>
  </head>
  <body>
    <div>
      <p>Some text</p>
      <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4
        //8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==" alt="Red dot" />
    </div>
  </body>
</html>

这个HTML在Chrome、Firefox等浏览器里能正常加载图片,但通过Indy发送邮件后,图片无法正确显示,要么收到纯HTML代码,要么图片破损或空白。我尝试了以下代码:

uses
  idMessage, idText, IdSMTP, IdSSLOpenSSL, IdExplicitTLSClientServerBase;

procedure SendMail;
var
  html: TStringList;
  email: TIdMessage;
  idSMTP: TIdSMTP;
  idSSL: TIdSSLIOHandlerSocketOpenSSL;
begin
  html:= TStringlist.Create;
  html.LoadFromFile('<my_html_file>');

  email := TIdMessage.Create(nil);
  email.From.Text := 'from@mail.com';
  email.From.Name:= 'from name'; ///
  email.Recipients.EMailAddresses := 'recipient';

  email.Subject := 'From DELPHI';
  email.ContentType := 'multipart/mixed';  //email comes with HTML text
  //email.ContentType := 'text/html';  //email comes with plain text, but not images
  email.Body.Assign(html);

  // SSL stuff //
  idSSL:= TIdSSLIOHandlerSocketOpenSSL.Create(nil);
  idSSL.SSLOptions.Mode:= sslmClient;
  idSSL.SSLOptions.Method:= sslvSSLv23;

  // SMTP stuff //
  idSMTP:= TIdSMTP.Create(nil);
  idSMTP.IOHandler:= idSSL;
  idSMTP.Host:= 'smtp.office365.com';
  idSMTP.Port:=  587;
  idSMTP.AuthType := satDefault;
  //idSMTP.UseTLS:= utUseImplicitTLS;
  idSMTP.UseTLS:= utUseExplicitTLS;
  idSMTP.Username:= 'mail@mail.com';
  idSMTP.Password:=  'pass';

  try
    idSMTP.Connect();
    idSMTP.Send(email);
    ShowMessage('Sent');
  except
    on E: Exception do
    ShowMessage('Failed: ' + E.Message);
  end;
end;

同时我也试过使用TIdMessageBuilderHtml,但都没成功。请问我哪里操作有误?


解决方法

你的问题主要出在两个核心点:

  1. 邮件客户端对data URI支持有限:虽然浏览器能解析Base64内嵌的data URI,但很多邮件客户端(比如Outlook、部分Web邮箱)并不支持这种方式显示图片,这是图片空白/破损的主要原因之一。
  2. Indy邮件构建不符合MIME规范:直接设置ContentType并赋值Body的方式错误,正确的内嵌图片邮件应该采用CID(Content-ID)引用内嵌附件的标准方式。

正确实现步骤

  1. 修改HTML模板,将图片的src从data URI改为cid:唯一标识,比如:
<html>
  <head>
  </head>
  <body>
    <div>
      <p>Some text</p>
      <img src="cid:red_dot" alt="Red dot" />
    </div>
  </body>
</html>
  1. 使用TIdMessageBuilderHtml构建邮件,将图片作为LinkedResource添加,并绑定对应的CID。
  2. 依赖TIdMessageBuilderHtml自动处理多部分邮件的MIME结构。

修正后的代码

uses
  idMessage, idText, IdSMTP, IdSSLOpenSSL, IdExplicitTLSClientServerBase,
  IdMessageBuilderHtml, IdAttachmentFile, IdGlobal;

procedure SendMail;
var
  html: TStringList;
  email: TIdMessage;
  idSMTP: TIdSMTP;
  idSSL: TIdSSLIOHandlerSocketOpenSSL;
  builder: TIdMessageBuilderHtml;
begin
  html := TStringList.Create;
  try
    html.LoadFromFile('<my_html_file>'); // 替换为修改后的HTML文件路径

    email := TIdMessage.Create(nil);
    try
      email.From.Text := 'from@mail.com';
      email.From.Name := 'from name';
      email.Recipients.EMailAddresses := 'recipient';
      email.Subject := 'From DELPHI';

      // 用TIdMessageBuilderHtml构建带内嵌图片的HTML邮件
      builder := TIdMessageBuilderHtml.Create;
      try
        builder.Html.Assign(html);
        // 添加内嵌图片,设置Content-ID为"red_dot",对应HTML里的cid:red_dot
        builder.HtmlFiles.Add('<你的PNG图片文件路径>', 'red_dot');

        // 将构建好的内容赋值给邮件
        builder.FillMessage(email);
      finally
        builder.Free;
      end;

      // SSL配置
      idSSL := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
      try
        idSSL.SSLOptions.Mode := sslmClient;
        idSSL.SSLOptions.Method := sslvSSLv23;

        // SMTP配置
        idSMTP := TIdSMTP.Create(nil);
        try
          idSMTP.IOHandler := idSSL;
          idSMTP.Host := 'smtp.office365.com';
          idSMTP.Port := 587;
          idSMTP.AuthType := satDefault;
          idSMTP.UseTLS := utUseExplicitTLS;
          idSMTP.Username := 'mail@mail.com';
          idSMTP.Password := 'pass';

          idSMTP.Connect;
          try
            idSMTP.Send(email);
            ShowMessage('Sent');
          finally
            idSMTP.Disconnect;
          end;
        finally
          idSMTP.Free;
        end;
      finally
        idSSL.Free;
      end;
    finally
      email.Free;
    end;
  finally
    html.Free;
  end;
end;

关键说明

  • TIdMessageBuilderHtml.HtmlFiles.Add()会自动将图片转为内嵌附件,设置正确的Content-ID和Content-Disposition: inline,确保邮件客户端能通过CID引用加载图片。
  • 若坚持使用Base64 data URI,需设置email.ContentType := 'text/html'并指定字符编码(如email.CharSet := 'UTF-8'),但仍无法保证所有邮件客户端兼容,因此优先推荐CID内嵌附件方案。

内容的提问来源于stack exchange,提问作者snowdev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 02:23:29