Πώς στέλνουμε email μέσα από Oracle Database όταν αποτύχει ένα RDBMS_SCHEDULER Job

Πώς στέλνουμε email μέσα από Oracle Database όταν αποτύχει ένα RDBMS_SCHEDULER Job
Πώς στέλνουμε email μέσα από Oracle Database όταν αποτύχει ένα RDBMS_SCHEDULER Job

Σε αυτό το άρθρο θα δούμε πώς μπορούμε να εγκαταστήσουμε email alert μηχανισμό ώστε όταν αποτύχει ένα Job να μας στείλει email απευθείας η βάση δεδομένων της Oracle μέσω SMTP Relay server. Θα δούμε όμως και γενικά πώς μπορούμε να στείλουμε email μέσω της procedure UTL_SMTP.

Για να στείλουμε email μέσα απο το RDBMS θα πρέπει να δώσουμε πρόσβαση προς το συγκεκριμένο IP του SMTP server με την χρήση του Oracle Application Security access control lists (ACL).

Η εγκατάσταση

Για αρχή ορίζουμε το default SMTP relay server βάζωντας την IP ή το host name του:

ALTER SYSTEM SET smtp_out_server = '10.0.13.8' SCOPE=BOTH;

Η παραμετροποίηση του ACL (Oracle Application Security access control list) security

Σε αυτό το το σημείο δίνουμε το δικαίωμα να συνδεθεί στην συγκεκριμένη IP και πόρτα ο χρήστης που θέλουμε με μία access control entry (ACE):

BEGIN
  DBMS_NETWORK_ACL_ADMIN.APPEND_HOST_ACE(
    host       => '10.0.13.8',         -- SMTP server IP/hostname
    lower_port => 25,                  -- Lower port (e.g., 25 for SMTP)
    upper_port => 25,                  -- Upper port (same as lower for single port)
    ace        => xs$ace_type(
      privilege_list => xs$name_list('connect'),
      principal_name => 'SYS',-- Database user (e.g., 'SCOTT')
      principal_type => xs_acl.ptype_db
    )
  );
END;
/

Για να δούμε την ACE εγγραφή που φτιάξαμε για προς τον συγκεκριμένο server τρέχουμε το παρακάτω query:

SELECT HOST, LOWER_PORT, UPPER_PORT,
       ACE_ORDER, PRINCIPAL, PRINCIPAL_TYPE,
       GRANT_TYPE, INVERTED_PRINCIPAL, PRIVILEGE,
       START_DATE, END_DATE
  FROM (SELECT ACES.*,
DBMS_NETWORK_ACL_UTILITY.CONTAINS_HOST('10.0.22.8',
                                                      HOST) PRECEDENCE
          FROM DBA_HOST_ACES ACES)
 WHERE PRECEDENCE IS NOT NULL
 ORDER BY PRECEDENCE DESC,
          LOWER_PORT NULLS LAST,
          UPPER_PORT NULLS LAST,
          ACE_ORDER;
HOST                                                                             LOWER_PORT UPPER_PORT  ACE_ORDER PRINCIPAL                                                                        PRINCIPAL_TYPE GRANT_TYPE INVERTED_PRINCIPAL PRIVILEGE                                                                        START_DATE                                        END_DATE
-------------------------------------------------------------------------------- ---------- ---------- ---------- -------------------------------------------------------------------------------- -------------- ---------- ------------------ -------------------------------------------------------------------------------- ------------------------------------------------- -------------------------------------------------
10.0.13.8                                                                                25         25          1 SYS                                                                              DATABASE       GRANT      NO                 CONNECT     

Εναλλακτικά μπορούμε να φτιάξουμε ένα καινούργιο ACL και να το δώσουμε αντίστοιχα τα ίδια δικαιώματα με πριν:

BEGIN
  DBMS_NETWORK_ACL_ADMIN.CREATE_ACL(
    acl          => 'smtp_server_acl.xml',  -- Name of the ACL file
    description  => 'ACL for SMTP Server',  -- Description
    principal    => 'SYS',        -- Database user (e.g., 'SYS' or the job owner)
    is_grant     => TRUE,                  -- Grant access
    privilege    => 'connect',             -- Required privilege
    start_date   => NULL,                  -- No start date restriction
    end_date     => NULL                   -- No end date restriction
  );
END;
/

BEGIN
  DBMS_NETWORK_ACL_ADMIN.ASSIGN_ACL(
    acl         => 'smtp_server_acl.xml',  -- Name of the ACL file
    host        => '10.0.13.8',-- SMTP server hostname/IP
    lower_port  => 25,                     -- Lower port (e.g., 25 for SMTP)
    upper_port  => 25                      -- Upper port (same as lower for single port)
  );
END;
/

Για να δούμε τα ACLs που υπάρχουν τρέχουμε το παρακάτω query:

SELECT * FROM dba_network_acls;
HOST                                                                             LOWER_PORT UPPER_PORT ACL                                                                              ACLID            ACL_OWNER
-------------------------------------------------------------------------------- ---------- ---------- -------------------------------------------------------------------------------- ---------------- --------------------------------------------------------------------------------
10.0.13.8                                                                                25         25 /sys/acls/smtp_server_acl.xml                                                    00000000800027D8 SYS

Δοκιμαστικό email με την χρήση UTL_SMTP

Τώρα για να δοκιμάσουμε οτι λειτουργεί ο SMTP server και οτι είναι σωστά φτιαγμένοι οι κανόνες security τρέχουμε το παρακάτω ώστε να στείλουμε ένα δοκιμαστικό email βάζωντας την ανάλογη IP, αποστολέα και παραλήπτη:

DECLARE
  v_From      VARCHAR2(80) := 'info@dataplatform.gr';
  v_Recipient VARCHAR2(80) := 'info@dataplatform.gr';
  v_Subject   VARCHAR2(80) := 'Send mail test';
  v_Mail_Host VARCHAR2(30) := '10.0.13.8';
  v_Mail_Conn utl_smtp.Connection;
  crlf        VARCHAR2(2) := chr(13) || chr(10);
BEGIN
  v_Mail_Conn := utl_smtp.Open_Connection(v_Mail_Host, 25);
  utl_smtp.Helo(v_Mail_Conn, v_Mail_Host);
  utl_smtp.Mail(v_Mail_Conn, v_From);
  utl_smtp.Rcpt(v_Mail_Conn, v_Recipient);
  utl_smtp.Data(v_Mail_Conn,
                'Date: ' || to_char(SYSDATE, 'Dy, DD Mon YYYY hh24:mi:ss') || crlf ||
                'From: ' || v_From || crlf || 'Subject: ' || v_Subject || crlf ||
                'To: ' || v_Recipient || crlf || crlf ||
                'some message text' || crlf || -- Message body
                'more message text' || crlf);
  utl_smtp.Quit(v_mail_conn);
END;

Πώς φτιάχνουμε ένα RDBMS_SCHEDULER Job που θα στέλνει email alerting

Ξεκινάμε ορίζοντας τις default παραμέτρους για την IP/hostname του SMTP relay server και τον αποστολέα:

BEGIN
  DBMS_SCHEDULER.set_scheduler_attribute('email_server', '10.0.13.8:25');
  DBMS_SCHEDULER.set_scheduler_attribute('email_sender', 'info@dataplatform.gr');
END;
/

Για να δούμε τις παραμέτρους που έχουμε βάλει τρέχουμε το παρακάτω query:

select * from dba_scheduler_global_attribute;
ATTRIBUTE_NAME                                                                   VALUE
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
MAX_JOB_SLAVE_PROCESSES                                                          
LOG_HISTORY                                                                      30
DEFAULT_TIMEZONE                                                                 Europe/Athens
EMAIL_SERVER                                                                     10.0.13.8:25
EMAIL_SERVER_ENCRYPTION                                                          NONE
EMAIL_SERVER_CREDENTIAL                                                          
EMAIL_SENDER                                                                     info@dataplatform.gr
LAST_OBSERVED_EVENT                                                              
EVENT_EXPIRY_TIME                                                                
FILE_WATCHER_COUNT                                                               0
CURRENT_OPEN_WINDOW                                                              

Με την παρακάτω procedure σαν παράδειγμα φτιάχνουμε ένα job χωρίς να είναι scheduled και του προσθέτουμε email notification προς έναν παραλήπτη όταν το event είναι JOB_FAILED:

BEGIN
    sys.dbms_scheduler.create_job(job_name            => 'TEST_MAIL_JOB',
                                job_type            => 'PLSQL_BLOCK',
                                job_action          => 'BEGIN RAISE_APPLICATION_ERROR(-20001, 'DBMS_JOB Failed'); END;',
                                start_date          => to_date('23-01-2025 00:00:00', 'dd-mm-yyyy hh24:mi:ss'),
                                end_date            => to_date(null),
                                job_class           => 'DEFAULT_JOB_CLASS',
                                enabled             => true,
                                auto_drop           => false,
                                comments            => 'TEST_MAIL');
                                
                                
  sys.dbms_scheduler.add_job_email_notification(job_name         => 'TEST_MAIL_JOB',
                                                sender           => 'info@dataplatform.gr',
                                                subject          => '%JobFailed%',
                                                body             => 'Job: %job_owner%.%job_name%.%job_subname%
  Event: %event_type%
  Date: %event_timestamp%
  Log id: %log_id%
  Job class: %job_class_name%
  Run count: %run_count%
  Failure count: %failure_count%
  Retry count: %retry_count%
  Error code: %error_code%
  Error message:
  %error_message%',
                                                recipients       => 'info@dataplatform.gr',
                                                filter_condition => '',
                                                events           => 'JOB_FAILED');


  sys.dbms_scheduler.set_attribute(name => 'TEST_MAIL_JOB', attribute => 'raise_events', value => sys.dbms_scheduler.job_failed);
END;
/

Για να δούμε τα dbms_scheduler job email notifications που έχουμε φτιάξει τρέχουμε το παρακάτω query:

select * from all_scheduler_notifications WHERE job_name = 'TEST_MAIL_JOB';
OWNER                                                                            JOB_NAME                  JOB_SUBNAME                                                                      RECIPIENT            SENDER                                                                           SUBJECT                                                                          BODY                                                                             FILTER_CONDITION               EVENT               EVENT_FLAG
-------------------------------------------------------------------------------- ------------------------- -------------------------------------------------------------------------------- -------------------- -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- ------------------------------ ------------------- ----------
SYS                                                                              TEST_MAIL_JOB                                                                                            info@dataplatform.gr         info@dataplatform.gr                                                                 %JobFailed%                                                                     Job: %job_owner%.%job_name%.%job_subname%                                                                       JOB_FAILED           512
                                  

Οπότε τρέχοντας το job όπως παρακάτω θα πρέπει να βγάλει σφάλμα και να μας αποστείλει το email:

BEGIN
    DBMS_SCHEDULER.RUN_JOB('TEST_MAIL_JOB');
END;
/

Για να δούμε την ιστορικότητα του status του rdbms_scheduler job που φτιάξαμε τρέχουμε το παρακάτω query:

SELECT job_name, status, log_date
FROM DBA_SCHEDULER_JOB_LOG
WHERE job_name = 'TEST_MAIL_JOB'
ORDER BY log_date DESC;
JOB_NAME                  STATUS                         LOG_DATE
------------------------- ------------------------------ -------------------------------------------------
TEST_MAIL_JOB            FAILED                      29-JAN-25 01.27.48.007447 PM +02:00
TEST_MAIL_JOB            FAILED                      29-JAN-25 01.26.39.518793 PM +02:00

Πηγές:

Μοιράσου το

Αφήστε μία απάντηση