如何從 Amazon RDS for Oracle 資料庫執行個體傳送電子郵件?

5 分的閱讀內容
0

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

簡短說明

若要從 RDS for Oracle 資料庫執行個體傳送電子郵件,請使用 UTL_MAIL 或 UTL_SMTP 套件。若要將 UTL_MAIL 用於 RDS for Oracle,請在附加到執行個體的非預設選項群組中新增 UTL_MAIL 選項。如需如何設定 UTL_MAIL 的詳細資訊,請參閱 Oracle UTL_MAIL

若要將 ULT_SMTP 用於 RDS for Oracle,請在內部部署機器上設定 SMTP 伺服器,或使用 Amazon Simple Email Service (Amazon SES)。確認從 RDS for Oracle 資料庫執行個體到 SMTP 伺服器的連線已正確設定。

下列解決方法說明如何使用 Amazon SES 透過 UTL_SMTP 套件傳送電子郵件。

先決條件

請確認可從您的 RDS 資料庫執行個體存取 Amazon SES 端點。如果您的資料庫執行個體在私有子網路中執行,請為 Amazon SES 建立虛擬私有雲端 (VPC) 端點

**注意:**對於在私有子網路中執行的資料庫執行個體,您也可使用 NAT 閘道與 Amazon SES 端點通訊。

設定資料庫執行個體以傳送電子郵件

若要設定資料庫執行個體以傳送電子郵件,請完成下列步驟:

  1. 使用 Amazon SES 設定 SMTP 郵件伺服器。
  2. 為 Amazon SES 建立 VPC 端點。
  3. 建立 Amazon Elastic Compute Cloud (Amazon EC2) Linux 執行個體。然後,使用適當的憑證來設定 Oracle 用戶端和錢包。
  4. 將錢包上傳到 Amazon Simple Storage Service (Amazon S3) 儲存貯體。
  5. 使用 Amazon S3 整合,將錢包從 Amazon S3 儲存貯體下載到 Amazon RDS 伺服器。
  6. 如為非主要使用者,請將所需許可授予這些使用者,然後建立必要的網路存取控制清單 (network ACL)。
  7. 使用您的 Amazon SES 憑證來傳送電子郵件。

解決方法

**注意:**如果您在執行 AWS Command Line Interface (AWS CLI) 命令時收到錯誤訊息,請參閱 Troubleshoot AWS CLI errors。此外,請確認您使用的是最新的 AWS CLI 版本

設定 SMTP 郵件伺服器

有關如何使用 Amazon SES 設定 SMTP 郵件伺服器的指示,請參閱如何使用 Amazon SES 設定並連線到 SMTP?

使用 Amazon SES 建立 VPC

有關如何使用 Amazon SES 建立 VPC 的指示,請參閱 Setting up VPC endpoints with Amazon SES

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

請完成下列步驟:

  1. 建立 Amazon EC2 Linux 執行個體

  2. 安裝 Oracle 用戶端。
    **注意:**最佳實務是使用與資料庫執行個體相同版本的用戶端。此解決方法使用 Oracle 第 19c 版。若要下載此用戶端,請參閱 Oracle 網站上的 Oracle Database 19c (19.3)。此版本隨附 orapki 公用程式。

  3. 開啟 AWS CLI。

  4. 從 EC2 執行個體在 Amazon RDS 安全群組中允許資料庫連接埠的連線。如果資料庫執行個體和 EC2 執行個體使用相同的 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 儲存貯體必須與資料庫執行個體位於相同的 AWS 區域。

    aws s3 cp cwallet.sso s3://testbucket/
  2. 執行下列命令來確認檔案上傳成功:

    aws s3 ls testbucket

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

請完成下列步驟:

  1. 開啟 Amazon RDS 主控台,然後建立選項群組
  2. 新增 S3_INTEGRATION 選項至選項群組。
  3. 使用此選項群組建立資料庫執行個體
  4. 建立 AWS Identity and Access Management (IAM) 政策和角色。如需詳細資訊,請參閱 Configuring IAM permissions for RDS for Oracle integration with Amazon S3
  5. 執行下列命令,將錢包從 S3 儲存貯體下載至 Amazon 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

針對 RDS for Oracle 非主要使用者: 為使用者授予所需許可並建立所需的網路 ACL

執行下列命令,將所需許可授予非主要使用者:

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;  
/

傳送電子郵件

若要傳送電子郵件,請執行下列程序。

**注意:**請將下列值取代為您的值:

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

如果您使用內部部署 SMTP 伺服器或 Amazon EC2 作為 SMTP 伺服器,請將 Amazon SES 資訊取代為您的內部部署或 EC2 伺服器詳細資訊。

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"

請找出沒有存取權的物件,然後授予所需許可。例如,如果 SYS 擁有的物件缺少某些許可 (例如 expample-usernameDBA_directories),請執行下列命令:

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;  
/

**ORA-29278:**如未正確設定安全群組、防火牆或網路 ACL,您會收到以下錯誤訊息:

"ORA-29278: SMTP transient error: 421 Service not available"

若要解決此問題,請確認您已正確設定網路組態。您也可以檢閱 VPC 流程日誌的下列資訊:

  • 分析來源和目的地 IP 位址: 從 VPC 流程日誌中,確認從來源和目的地 IP 位址傳輸的資料會收到回應。
  • 檢查連接埠和協定: 確認使用正確的連接埠和協定,且沒有出現異常差異。
  • 安全群組和網路 ACL: 檢查安全群組和網路 ACL 組態,確認它們允許必要連接埠上的流量。
  • 子網路路由: 驗證相關子網路中的路由表已正確設定,可將流量路由至資料庫伺服器。
  • 延遲和封包遺失: 檢查是否出現延遲或封包遺失。延遲和封包遺失可能表示網路有問題。

如需詳細資訊,請參閱 Logging IP traffic using VPC Flow Logs 和 Oracle 網站上的 Troubleshooting ORA-29278 and ORA-29279 when using UTL_SMTP (Doc ID 2287232.1)

**ORA-29279:**如未在 Amazon SES 上建立身分,您可能會收到以下錯誤訊息:

"ORA-29279: SMTP permanent error: 554 Message rejected: Email address is not verified.The following identities failed the check in region <REGION>:'example-sender-email'"

若要解決此問題,請設定網域層級的身分或建立電子郵件地址身分。如需詳細資訊,請參閱 Creating and verifying identities in Amazon SES

測試 Amazon RDS 到 Amazon SES 端點的連線

請執行下列程序來測試 Amazon RDS 和 Amazon SES 端點之間的連線:

CREATE OR REPLACE FUNCTION fn_check_network  
(p_remote_host in varchar2, -- host name  
 p_port_no in integer default 587  
)  
RETURN number IS  
   v_connection   utl_tcp.connection;  
BEGIN  
   v_connection := utl_tcp.open_connection(REMOTE_HOST=>p_remote_host, REMOTE_PORT=>p_port_no, IN_BUFFER_SIZE=>1024, OUT_BUFFER_SIZE=>1024,   TX_TIMEOUT=>5);  
   RETURN 1;  
EXCEPTION  
   WHEN others THEN  
      return sqlcode;  
END fn_check_network;  
/
SELECT fn_check_network('email-smtp.<region>.amazonaws.com', 587) FROM dual;

如果程序成功,函數會傳回 1。如果程序失敗,則函數會傳回 ORA -29260

相關資訊

Oracle 網站上的電子郵件傳遞服務概觀

Oracle 網站上的 UTL_SMTP