跳至內容

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

5 分的閱讀內容
0

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

簡短說明

若要從 RDS for Oracle 資料庫執行個體傳送電子郵件,請使用 UTL_MAIL 或 UTL_SMTP 套件。若要搭配 RDS for Oracle 使用 UTL_MAIL,請將 UTL_MAIL 選項新增至連接至執行個體的非預設選項群組。如需更多有關如何設定 UTL_MAIL 的資訊,請參閱 Oracle UTL_MAIL

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

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

先決條件

確認您的 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. 對於非主要使用者,請授予使用者必要權限,然後建立必要的網路存取控制清單 (網路 ACL)。
  7. 使用您的 Amazon SES 憑證傳送電子郵件。

解決方法

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

設定 SMTP 郵件伺服器

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

使用 Amazon SES 建立 VPC

如需如何使用 Amazon SES 建立 VPC 的指示,請參閱使用 Amazon SES 設定 VPC 端點

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

請完成以下步驟:

  1. 建立 Amazon EC2 Linux 執行個體

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

  3. 開啟 AWS CLI。

  4. 在 Amazon RDS 安全群組中,允許來自 EC2 執行個體且使用資料庫連接埠的連線。若資料庫執行個體和 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 Aurora 和 RDS 主控台,然後建立選項群組
  2. 將 S3_INTEGRATION 選項新增至選項群組
  3. 使用該選項群組建立資料庫執行個體
  4. 建立 AWS Identity and Access Management (IAM) 政策和角色。如需更多資訊,請參閱設定 RDS for Oracle 與 Amazon S3 整合的 IAM 權限
  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 擁有的物件 (例如 DBA_directories) 缺少授予 expample-username 的特定權限,請執行以下命令:

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 組態,確認其允許必要連接埠上的流量。
  • 子網路路由: 驗證相關子網路中的路由表是否已正確設定,以將流量路由至資料庫伺服器。
  • 延遲和封包遺失: 尋找延遲或封包遺失。延遲和封包遺失可能表示網路發生問題。

如需更多資訊,請參閱使用 VPC Flow Logs 記錄 IP 流量,以及 Oracle 網站上的使用 UTL_SMTP 時疑難排解 ORA-29278 和 ORA-29279 (文件 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'」

若要解決此問題,請在網域層級設定身分,或建立電子郵件地址身分。如需更多資訊,請參閱在 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

AWS 官方已更新 3 年前