【问题标题】:ORA-29278: SMTP transient error: Service not available when running UTL_MAILORA-29278: SMTP 暂时错误: 运行 UTL_MAIL 时服务不可用
【发布时间】:2016-12-29 09:47:41
【问题描述】:

我们计划安装UTL_MAIL 软件包,目前正在我们的开发环境中测试安装步骤。 在成功安装UTL_MAIL 包脚本并创建足够的PUBLIC 同义词和授权后, 我们在运行下面的测试匿名块时收到错误ORA-29278

BEGIN 

    UTL_MAIL.SEND(sender     => 'xxx@oracle.com'
                , recipients => 'Migs.Isip.23@gmail.com'
                , subject    => 'Testmail'
                , message    => 'Hello');

END;

错误消息的详细信息:

ORA-29278: SMTP transient error: 421 4.3.2 Service not available
ORA-06512: at "SYS.UTL_MAIL", line 662
ORA-06512: at "SYS.UTL_MAIL", line 679
ORA-06512: at line 3
29278. 00000 -  "SMTP transient error: %s"
*Cause:    A SMTP transient error occurred.
*Action:   Correct the error and retry the SMTP operation.    

根据相关链接 (Send Email Using PLSQL) 的研究, 我可能需要设置正确的访问控制列表 (ACL) 才能正常工作。但是,在执行下面的脚本时,我仍然遇到同样的错误。

DECLARE
   -- ACL name to be used for email access reuse the same value for all 
   -- future calls
   l_acl         VARCHAR2 (30) := 'utl_smtp.xml';
   -- Oracle user to be given permission to send email
   l_principal   VARCHAR2 (30) := 'APPS';
   -- Name of email server
   g_mailhost    VARCHAR2 (60) := 'smtprelay.xxxxx.com';
   l_cnt         INTEGER;

   PROCEDURE validate_smtp_server
   AS
      l_value       v$parameter.VALUE%TYPE;
      l_parameter   v$parameter.name%TYPE := 'smtp_out_server';
   BEGIN

      SELECT VALUE
        INTO l_value
        FROM v$parameter
       WHERE name = l_parameter;

      IF l_value IS NULL
      THEN
         raise_application_error (
            -20001
          ,    'Oracle parameter '
            || l_parameter
            || ' has not been set'
            || UTL_TCP.crlf
            || 'it s/b smtprelay.alorica.com'
         );
      END IF;

      DBMS_OUTPUT.put_line ('parameter ' || l_parameter || ' value is ' ||     l_value);

   END validate_smtp_server;

   PROCEDURE create_if_needed (p_acl IN VARCHAR2)
   AS
      l_cnt   INTEGER;
   BEGIN

      SELECT COUNT (*) c
        INTO l_cnt
        FROM dba_network_acls a
       WHERE SUBSTR (acl, INSTR (acl, '/', -1) + 1) = p_acl;

      IF l_cnt = 0
      THEN
         DBMS_OUTPUT.put_line ('creating acl ' || p_acl);
         DBMS_NETWORK_ACL_ADMIN.create_acl (
            acl         => p_acl
          , description => 'Allow use of utl_smtp'
          , principal   => l_principal
          , is_grant    => TRUE
          , privilege   => 'connect'
         );

         DBMS_NETWORK_ACL_ADMIN.assign_acl (acl => p_acl, HOST => g_mailhost);
         COMMIT;
      ELSE
         DBMS_OUTPUT.put_line (p_acl || ' acl already exists');
      END IF;

   END create_if_needed;

   PROCEDURE add_if_needed (
      p_principal   IN VARCHAR2
    , p_acl         IN VARCHAR2
   )
   AS
      l_cnt   INTEGER;
   BEGIN

      SELECT COUNT (*) c
        INTO l_cnt
        FROM dba_network_acl_privileges
       WHERE SUBSTR (acl, INSTR (acl, '/', -1) + 1) = p_acl
         AND principal = p_principal;

      IF l_cnt = 0
      THEN
         DBMS_NETWORK_ACL_ADMIN.add_privilege (
            acl       => 'utl_smtp.xml'
          , principal => p_principal
          , is_grant  => TRUE
          , privilege => 'connect'
         );
         COMMIT;
         DBMS_OUTPUT.put_line ('access to ' || p_acl || ' added for ' ||     p_principal);
      ELSE
         DBMS_OUTPUT.put_line (p_principal || ' already has access to ' || p_acl);
      END IF;

   END add_if_needed;
BEGIN

   EXECUTE IMMEDIATE 'grant execute on utl_mail to ' || l_principal;

   create_if_needed (p_acl => l_acl);
   add_if_needed (p_principal => l_principal, p_acl => l_acl);
   DBMS_OUTPUT.put_line ('Verification SQL:');
   DBMS_OUTPUT.put_line ('    SELECT * FROM dba_network_acls;');
   DBMS_OUTPUT.put_line ('    SELECT * FROM dba_network_acl_privileges;');
   COMMIT;
   validate_smtp_server;
END;

为此我还可以采取哪些其他步骤或需要向 DBA 提供哪些其他说明?

Oracle 数据库版本:

Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
PL/SQL Release 11.2.0.4.0 - Production
"CORE   11.2.0.4.0  Production"
TNS for Solaris: Version 11.2.0.4.0 - Production
NLSRTL Version 11.2.0.4.0 - Production

非常感谢。

【问题讨论】:

    标签: oracle plsql


    【解决方案1】:

    我能够通过联系我们的系统管理员并询问邮件服务器的详细信息来解决此问题。 事实证明,如果我们只在内部发送电子邮件,建议我们使用不同的服务器mail.xxx.xxx.xxxx,因为它不会被防火墙阻止。 另一方面,如果我们要向外部发送电子邮件,则涉及另一台服务器smtprelay.xxxxx.com 这涉及将要发送到的外部服务器列入白名单的额外步骤。

    当我签入V$PARAMETER 时,我们正在使用smtprelay.xxxxx.com 服务器并决定尝试其他服务器mail.xxx.xxx.xxxx

    我发出Alter命令如下:

    alter system set smtp_out_server = 'mail.xxx.xxx.xxxx';
    

    并运行匿名块并能够成功接收电子邮件。

    BEGIN 
    
        UTL_MAIL.SEND(sender     => 'xxx@oracle.com'
                    , recipients => 'Migs.Isip.23@gmail.com'
                    , subject    => 'Testmail'
                    , message    => 'Hello');
    
    END;
    

    【讨论】:

    • 您好,我的应用程序遇到了类似的问题。我无法发送电子邮件并且我在公司网络中。我想和你更深入地讨论它。我也收到“SMTP 暂时错误:421 服务不可用”。
    • @RaviShankar 你也在使用 PL/SQL 吗?
    【解决方案2】:

    我提出了 19c 数据库的 SMTP 电子邮件挑战。我能够解决它。以下是完整的解决方案:-

    • 授予 utl_tcp、utl_smtp 和 utl_http 的相应架构名称。

      将 utl_tcp 上的执行权限授予 schemaname; 将 utl_smtp 上的执行权限授予 schemaname; 将 utl_http 上的执行权限授予 schemaname;
    • 使用 DBMS_NETWORK_ACL_ADMIN 系统包创建 ACL:-

      开始 DBMS_NETWORK_ACL_ADMIN.CREATE_ACL ( acl => '/sys/acls/utl_http.xml', 描述 => '允许 SMTP 连接', 主体 => 'SCHEMANAME', is_grant => 真, 特权 => '连接', 开始日期 => SYSTIMESTAMP, end_date => NULL); 犯罪; 结尾; /
    • 使用 DBMS_NETWORK_ACL_ADMIN 包将 ADD_PRIVILEGE 添加到架构:-

      开始 DBMS_NETWORK_ACL_ADMIN.ADD_PRIVILEGE( acl => '/sys/acls/utl_http.xml', 主体 => 'SCHEMANAME', is_grant => 真, 特权 => '解决'); 犯罪; 结尾; /
    • ASSIGN_ACL 到使用 DBMS_NETWORK_ACL_ADMIN 包的邮件服务器:-

      开始 DBMS_NETWORK_ACL_ADMIN.ASSIGN_ACL ( acl => '/sys/acls/utl_http.xml', 主机 => '邮件主机名'); 犯罪; 结尾; /

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-10-31
      • 2011-08-04
      • 2016-08-22
      • 1970-01-01
      • 2018-02-25
      • 2011-12-27
      • 1970-01-01
      相关资源
      最近更新 更多