如何設定我的 Amazon RDS for Oracle 執行個體來傳送電子郵件?

上次更新日期︰2021 年 11 月 16 日

我想為 Oracle 資料庫執行個體設定我的 Amazon Relational Database Service (Amazon RDS) 來傳送電子郵件。

簡短描述

若要從 Amazon RDS for Oracle 執行個體來傳送電子郵件,您可以使用 UTL_MAILUTL_SMTP 套件。

  • 若要搭配 RDS for Oracle 來使用 UTL_MAIL,您必須在連接至執行個體的非預設選項群組中新增 UTL_MAIL 選項。如需設定 UTL_MAIL 的詳細資訊,請參閱 ORACLE UTL_MAIL
  • 若要搭配 RDS for Oracle 來使用 UTL_SMTP,您必須使用 Amazon Simple Email Service (Amazon SES) 在內部部署機器上設定 SMTP 伺服器,或在 Amazon Elastic Compute Cloud (Amazon EC2) 執行個體上設定 SMTP 伺服器。在此情況下,請確定來自 RDS for Oracle 與 SMTP 伺服器的連線已正確設定。

本文主要探討使用 Amazon SES 來設定資料庫執行個體以透過 UTL_SMTP 套件來傳送電子郵件。

開始之前,請先確定 Amazon SES 端點可從 RDS 執行個體存取。如果您的 RDS 執行個體在私有子網路中執行,則必須在這個子網路的路由表中新增 NAT 閘道。此為子網路與 Amazon SES 端點通訊的必要條件。若要檢查子網路的路由表,請開啟 Amazon VPC 主控台,然後在導覽窗格中選擇路由表

若要設定資料庫執行個體傳送電子郵件,請執行下列動作:

  1. 設定 SMTP 郵件伺服器。在本文中,Amazon SES 可用來設定 SMTP 郵件伺服器。
  2. 建立 Amazon EC2 執行個體。然後,使用適當的憑證設定 Oracle 用戶端和錢包。
  3. 將錢包上傳到 Amazon Simple Storage Service (Amazon S3) 儲存貯體。
  4. 使用 S3 整合,將錢包從 Amazon S3 儲存貯體下載到 RDS 伺服器。
  5. 將必要的權限授與使用者 (如果使用者是非主要使用者),並建立必要的存取控制清單 (ACL)。
  6. 使用 Amazon SES 憑證和本文提供的程序傳送電子郵件。

解決方案

使用 Amazon SES 設定 SMTP 郵件伺服器

建立 Amazon EC2 執行個體並設定 Oracle 用戶端和錢包

1.    建立 Amazon EC2 Linux 執行個體

2.    安裝與 Amazon RDS 執行個體相同版本的 Oracle 用戶端,如此可獲得最佳效果。本文使用的是 Oracle 版本 19c。您可以下載 Oracle 19c 用戶端,詳情請參閱 Oracle Database 19c (19.3)。此版本隨附 orapki 工具程式。

3.    安裝 AWS Command Line Interface (AWS CLI)

4.    允許透過 EC2 執行個體的 RDS 安全群組中的資料庫連接埠進行連線。如果兩個執行個體都使用相同的 VPC,則允許透過其私有 IP 地址進行連線。

5.    連線到 EC2 執行個體

6.    執行下列命令以下載 AmazonRootCA1 憑證

wget https://www.amazontrust.com/repository/AmazonRootCA1.pem

7.    執行下列命令來建立錢包:

orapki wallet create -wallet . -auto_login_only
orapki wallet add -wallet . -trusted_cert -cert AmazonRootCA1.pem -auto_login_only

將錢包上傳到 Amazon S3

1.    執行下列命令,將錢包上傳至 Amazon S3 儲存貯體:

附註:請確定 S3 儲存貯體與 RDS 執行個體位於相同的區域,S3 整合才能正常運作。

aws s3 cp cwallet.sso s3://testbucket/
2.    執行下列命令以驗證檔案是否順利上傳:
aws s3 ls testbucket

使用 S3 整合將錢包下載到 RDS 伺服器

1.    使用 Amazon RDS 主控台來建立選項群組

2.    在您建立的選項群組中,新增 S3_INTEGRATION 選項。這是從 Amazon S3 下載錢包檔案到 RDS 執行個體的必要條件。

3.    運用您建立的選項群組來建立 RDS for Oracle 執行個體

4.    透過建立 AWS Identity and Access Management (IAM) 的政策和角色來準備 S3 整合。如需詳細資訊,請參閱Amazon RDS for Oracle 與 Amazon S3 整合的必要條件

5.    執行下列命令,從 S3 儲存貯體將錢包下載至 RDS:

SQL> exec rdsadmin.rdsadmin_util.create_directory('S3_WALLET');

PL/SQL procedure successfully completed.

SQL> SELECT OWNER,DIRECTORY_NAME,DIRECTORY_PATH FROM DBA_DIRECTORIES WHERE DIRECTORY_NAME='S3_WALLET';

OWNER             DIRECTORY_NAME            DIRECTORY_PATH
-------------------- ------------------------------ ----------------------------------------------------------------------
SYS             S3_WALLET                /rdsdbdata/userdirs/01

SQL> SELECT
rdsadmin.rdsadmin_s3_tasks.download_from_s3(
p_bucket_name => 'testbucket',
p_directory_name => 'S3_WALLET',
P_S3_PREFIX => 'cwallet.sso')  AS TASK_ID FROM DUAL;

TASK_ID
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1625291989577-52

SQL> SELECT filename FROM table(RDSADMIN.RDS_FILE_UTIL.LISTDIR('S3_WALLET'));

FILENAME
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
01/
cwallet.sso

將必要的權限授與使用者並建立必要的 ACL

附註:如果您使用的是 RDS for Oracle 的非主要使用者,則需要此步驟。

執行下列命令,將必要的權限授與非主要使用者:

begin
    rdsadmin.rdsadmin_util.grant_sys_object(
        p_obj_name  => 'DBA_DIRECTORIES',
        p_grantee   => 'example-username',
        p_privilege => 'SELECT');
end;
/

執行下列命令來建立必要的 ACL:

BEGIN
DBMS_NETWORK_ACL_ADMIN.CREATE_ACL (
acl => 'ses_1.xml',
description => 'AWS SES ACL 1',
principal => 'TEST',
is_grant => TRUE,
privilege => 'connect');
COMMIT;
END;
/
BEGIN
DBMS_NETWORK_ACL_ADMIN.ASSIGN_ACL (
acl => 'ses_1.xml',
host => 'example-host');
COMMIT;
END;
/

傳送電子郵件

執行下列程序來傳送電子郵件:

附註:請務必取代程序中的下列值:

  • 以您的 SMTP 郵件伺服器的名稱來取代 example-server
  • 以寄件者電子郵件地址來取代 example-sender-email
  • 以接收者電子郵件地址來取代 example-receiver-email
  • 以您的使用者名稱來取代 example-SMTP-username
  • 以您的密碼來取代 example-SMTP-password

如果您使用內部部署或 Amazon EC2 作為 SMTP 伺服器,請務必使用與內部部署或 EC2 伺服器相關的資訊,而不是 Amazon SES。

declare
l_smtp_server varchar2(1024) := 'example-server';
l_smtp_port number := 587;
l_wallet_dir varchar2(128) := 'S3_WALLET';
l_from varchar2(128) := 'example-sender-email';
l_to varchar2(128)  := 'example-receiver-email';
l_user varchar2(128) := 'example-SMTP-username';
l_password varchar2(128) := 'example-SMTP-password';
l_subject varchar2(128) := 'Test mail from RDS Oracle';
l_wallet_path varchar2(4000);
l_conn utl_smtp.connection;
l_reply utl_smtp.reply;
l_replies utl_smtp.replies;
begin
select 'file:/' || directory_path into l_wallet_path from dba_directories where directory_name=l_wallet_dir;
--open a connection
l_reply := utl_smtp.open_connection(
host => l_smtp_server,
port => l_smtp_port,
c => l_conn,
wallet_path => l_wallet_path,
secure_connection_before_smtp => false);
dbms_output.put_line('opened connection, received reply ' || l_reply.code || '/' || l_reply.text);
--get supported configs from server
l_replies := utl_smtp.ehlo(l_conn, 'localhost');
for r in 1..l_replies.count loop
dbms_output.put_line('ehlo (server config) : ' || l_replies(r).code || '/' || l_replies(r).text);
end loop;
--STARTTLS
l_reply := utl_smtp.starttls(l_conn);
dbms_output.put_line('starttls, received reply ' || l_reply.code || '/' || l_reply.text);
--
l_replies := utl_smtp.ehlo(l_conn, 'localhost');
for r in 1..l_replies.count loop
dbms_output.put_line('ehlo (server config) : ' || l_replies(r).code || '/' || l_replies(r).text);
end loop;
utl_smtp.auth(l_conn, l_user, l_password, utl_smtp.all_schemes);
utl_smtp.mail(l_conn, l_from);
utl_smtp.rcpt(l_conn, l_to);
utl_smtp.open_data (l_conn);
utl_smtp.write_data(l_conn, 'Date: ' || to_char(SYSDATE, 'DD-MON-YYYY HH24:MI:SS') || utl_tcp.crlf);
utl_smtp.write_data(l_conn, 'From: ' || l_from || utl_tcp.crlf);
utl_smtp.write_data(l_conn, 'To: ' || l_to || utl_tcp.crlf);
utl_smtp.write_data(l_conn, 'Subject: ' || l_subject || utl_tcp.crlf);
utl_smtp.write_data(l_conn, '' || utl_tcp.crlf);
utl_smtp.write_data(l_conn, 'Test message.' || utl_tcp.crlf);
utl_smtp.close_data(l_conn);

l_reply := utl_smtp.quit(l_conn);
exception
when others then
utl_smtp.quit(l_conn);
raise;
end;
/

疑難排解錯誤

ORA-29279:如果您的 SMTP 使用者名稱或密碼不正確,您可能會收到下列錯誤

ORA-29279: SMTP permanent error: 535 Authentication Credentials Invalid

若要解決這個問題,請確認您的 SMTP 憑證正確無誤。

ORA-00942:如果電子郵件套件是由非主要使用者來執行,您可能會收到下列錯誤:

PL/SQL: ORA-00942: table or view does not exist

若要解決這個問題,請執行下列程序,將必要的許可授與使用者:

begin
    rdsadmin.rdsadmin_util.grant_sys_object(
        p_obj_name  => 'DBA_DIRECTORIES',
        p_grantee   => 'example-username',
        p_privilege => 'SELECT');
end;
/

ORA-24247: 如果 ACL 未指派給目標主機,或使用者沒有存取目標主機所需的權限,您可能會收到下列錯誤訊息:

ORA-24247: network access denied by access control list (ACL)

若要解決此問題,請建立 ACL 並執行下列程序,將 ACL 指派給主機:

BEGIN
DBMS_NETWORK_ACL_ADMIN.CREATE_ACL (
acl => 'ses_1.xml',
description => 'AWS SES ACL 1',
principal => 'TEST',
is_grant => TRUE,
privilege => 'connect');
COMMIT;
END;
/

BEGIN
DBMS_NETWORK_ACL_ADMIN.ASSIGN_ACL (
acl => 'ses_1.xml',
host => 'example-host');
COMMIT;
END;
/

此文章是否有幫助?


您是否需要帳單或技術支援?