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

Oracle 19c中UTL_SMTP发送邮件空格被截断的问题求助

UTL_SMTP发送HTML邮件保留连续空格的解决办法

环境与问题

  • 数据库:Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production Version 19.20.0.0.0
  • 场景:用UTL_SMTP发送HTML格式邮件,能正常收到,但正文里的连续空格(包括前导、尾随)被自动截断,无法保留预期格式。

原代码如下:

declare
 l_mail_conn   UTL_SMTP.connection;
  l_boundary    VARCHAR2(50) := '              =abc1234321cba=';
  p_smtp_host VARCHAR2 (100) := 'smtp.cac.com';
   p_smtp_port      NUMBER := 25;
   p_to VARCHAR2(100) := 'hello@gmail.com';
   p_subject VARCHAR2(100) := 'Hello';
   p_html_msg  VARCHAR2(100) :=  '              ' ||'ABC <br>' || '              ' || 'DEF';
BEGIN
  l_mail_conn := UTL_SMTP.open_connection(p_smtp_host, p_smtp_port);
  UTL_SMTP.helo(l_mail_conn, p_smtp_host);
  UTL_SMTP.mail(l_mail_conn, p_to);
  UTL_SMTP.rcpt(l_mail_conn, p_to);

  UTL_SMTP.open_data(l_mail_conn);
  
  UTL_SMTP.write_data(l_mail_conn, 'Date: ' || TO_CHAR(SYSDATE, 'DD-MON-YYYY HH24:MI:SS') || UTL_TCP.crlf);
  UTL_SMTP.write_data(l_mail_conn, 'To: ' || p_to || UTL_TCP.crlf);
  UTL_SMTP.write_data(l_mail_conn, 'From: ' || p_to || UTL_TCP.crlf);
  UTL_SMTP.write_data(l_mail_conn, 'Subject: ' || p_subject || UTL_TCP.crlf);
  UTL_SMTP.write_data(l_mail_conn, 'MIME-Version: 1.0' || UTL_TCP.crlf);
  UTL_SMTP.write_data(l_mail_conn, 'Content-Type: multipart/alternative; boundary="' || l_boundary || '"' || UTL_TCP.crlf || UTL_TCP.crlf);

  IF p_html_msg IS NOT NULL THEN
    UTL_SMTP.write_data(l_mail_conn, '--' || l_boundary || UTL_TCP.crlf);
    UTL_SMTP.write_data(l_mail_conn, 'Content-Type: text/html; charset="iso-8859-1"' || UTL_TCP.crlf || UTL_TCP.crlf);

    UTL_SMTP.write_data(l_mail_conn, p_html_msg);
    UTL_SMTP.write_data(l_mail_conn, UTL_TCP.crlf || UTL_TCP.crlf);
  END IF;

  UTL_SMTP.write_data(l_mail_conn, '--' || l_boundary || '--' || UTL_TCP.crlf);
  UTL_SMTP.close_data(l_mail_conn);

  UTL_SMTP.quit(l_mail_conn);
END;
/

问题原因

这不是UTL_SMTP的问题,是HTML的默认渲染规则:浏览器/邮件客户端会把连续的空白字符(空格、换行、制表符)合并成单个空格,所以你写的连续空格会被自动压缩。

解决方法

有两种常用的办法可以保留空格格式:

方法1:使用<pre>标签

<pre>标签会保留文本的原始格式,包括空格、换行和缩进,适合需要保留排版的内容。修改p_html_msg的定义:

p_html_msg  VARCHAR2(200) :=  '&lt;pre&gt;' || '              ABC' || '&lt;br&gt;' || '              DEF' || '&lt;/pre&gt;';

方法2:用&nbsp;替换普通空格

把每个需要保留的空格替换成HTML空格实体&nbsp;,连续空格就用多个&nbsp;。比如前导的14个空格就写成14个&nbsp;:

p_html_msg  VARCHAR2(200) :=  '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;' ||'ABC &lt;br&gt;' || '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;' || 'DEF';

修改后的完整代码示例(以<pre>为例)

declare
 l_mail_conn   UTL_SMTP.connection;
  l_boundary    VARCHAR2(50) := '              =abc1234321cba=';
  p_smtp_host VARCHAR2 (100) := 'smtp.cac.com';
   p_smtp_port      NUMBER := 25;
   p_to VARCHAR2(100) := 'hello@gmail.com';
   p_subject VARCHAR2(100) := 'Hello';
   -- 使用<pre>标签保留空格格式
   p_html_msg  VARCHAR2(200) :=  '&lt;pre&gt;' || '              ABC' || '&lt;br&gt;' || '              DEF' || '&lt;/pre&gt;';
BEGIN
  l_mail_conn := UTL_SMTP.open_connection(p_smtp_host, p_smtp_port);
  UTL_SMTP.helo(l_mail_conn, p_smtp_host);
  UTL_SMTP.mail(l_mail_conn, p_to);
  UTL_SMTP.rcpt(l_mail_conn, p_to);

  UTL_SMTP.open_data(l_mail_conn);
  
  UTL_SMTP.write_data(l_mail_conn, 'Date: ' || TO_CHAR(SYSDATE, 'DD-MON-YYYY HH24:MI:SS') || UTL_TCP.crlf);
  UTL_SMTP.write_data(l_mail_conn, 'To: ' || p_to || UTL_TCP.crlf);
  UTL_SMTP.write_data(l_mail_conn, 'From: ' || p_to || UTL_TCP.crlf);
  UTL_SMTP.write_data(l_mail_conn, 'Subject: ' || p_subject || UTL_TCP.crlf);
  UTL_SMTP.write_data(l_mail_conn, 'MIME-Version: 1.0' || UTL_TCP.crlf);
  UTL_SMTP.write_data(l_mail_conn, 'Content-Type: multipart/alternative; boundary=&quot;' || l_boundary || '&quot;' || UTL_TCP.crlf || UTL_TCP.crlf);

  IF p_html_msg IS NOT NULL THEN
    UTL_SMTP.write_data(l_mail_conn, '--' || l_boundary || UTL_TCP.crlf);
    UTL_SMTP.write_data(l_mail_conn, 'Content-Type: text/html; charset=&quot;iso-8859-1&quot;' || UTL_TCP.crlf || UTL_TCP.crlf);

    UTL_SMTP.write_data(l_mail_conn, p_html_msg);
    UTL_SMTP.write_data(l_mail_conn, UTL_TCP.crlf || UTL_TCP.crlf);
  END IF;

  UTL_SMTP.write_data(l_mail_conn, '--' || l_boundary || '--' || UTL_TCP.crlf);
  UTL_SMTP.close_data(l_mail_conn);

  UTL_SMTP.quit(l_mail_conn);
END;
/

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 08:50:58