1. ホーム
  2. oracle

[解決済み] ORA-29278: SMTP transient エラー。UTL_MAIL の実行時にサービスが利用できない

2022-03-12 19:23:19

質問

をインストールする予定です。 UTL_MAIL 現在、開発環境でのインストール手順をテストしています。 のインストールに成功した後 UTL_MAIL パッケージスクリプトを作成し、十分な PUBLIC シノニムとグランツ というエラーが発生します。 ORA-29278 を実行すると、以下のAnonymous Blockのテストが実行されます。

BEGIN 

    UTL_MAIL.SEND(sender     => '[email protected]'
                , recipients => '[email protected]'
                , 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.    

関連リンクからの調べによると( 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 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

ありがとうございました。

解決方法は?

システム管理者に連絡し、メールサーバーの詳細を聞くことで解決することができました。 もし、社内でメールを送るだけであれば、別のサーバーを使用するようにとのことでした。 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     => '[email protected]'
                , recipients => '[email protected]'
                , subject    => 'Testmail'
                , message    => 'Hello');

END;