如何從 Amazon RDS for Oracle 資料庫執行個體傳送電子郵件?
我想設定 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 端點通訊。
設定資料庫執行個體以傳送電子郵件
若要設定資料庫執行個體以傳送電子郵件,請完成以下步驟:
- 使用 Amazon SES 設定 SMTP 郵件伺服器。
- 建立連至 Amazon SES 的 VPC 端點。
- 建立 Amazon Elastic Compute Cloud (Amazon EC2) Linux 執行個體。然後,使用適當的憑證設定 Oracle 用戶端和錢包。
- 將錢包上傳至 Amazon Simple Storage Service (Amazon S3) 儲存貯體。
- 使用 Amazon S3 整合,將錢包從 Amazon S3 儲存貯體下載至 Amazon RDS 伺服器。
- 對於非主要使用者,請授予使用者必要權限,然後建立必要的網路存取控制清單 (網路 ACL)。
- 使用您的 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 用戶端和錢包
請完成以下步驟:
-
安裝 Oracle 用戶端。
**注意:**最佳實務是使用與資料庫執行個體版本相同的用戶端。此解決方法使用 Oracle 19c 版本。若要下載此用戶端,請參閱 Oracle 網站上的 Oracle Database 19c (19.3)。此版本隨附 orapki 公用程式。 -
開啟 AWS CLI。
-
在 Amazon RDS 安全群組中,允許來自 EC2 執行個體且使用資料庫連接埠的連線。若資料庫執行個體和 EC2 執行個體使用相同的 VPC,請使用其私有 IP 位址允許連線。
-
執行以下命令以下載 AmazonRootCA1 憑證:
wget https://www.amazontrust.com/repository/AmazonRootCA1.pem -
執行以下命令以建立錢包:
orapki wallet create -wallet . -auto_login_only orapki wallet add -wallet . -trusted_cert -cert AmazonRootCA1.pem -auto_login_only
將錢包上傳至 Amazon S3
請完成以下步驟:
-
執行以下命令,將錢包上傳至 Amazon S3 儲存貯體:
**注意:**S3 儲存貯體必須與資料庫執行個體位於相同的 AWS 區域。aws s3 cp cwallet.sso s3://testbucket/ -
執行以下命令以驗證檔案是否成功上傳:
aws s3 ls testbucket
使用 Amazon S3 整合將錢包下載至 Amazon RDS 伺服器
請完成以下步驟:
- 開啟 Amazon Aurora 和 RDS 主控台,然後建立選項群組。
- 將 S3_INTEGRATION 選項新增至選項群組。
- 使用該選項群組建立資料庫執行個體。
- 建立 AWS Identity and Access Management (IAM) 政策和角色。如需更多資訊,請參閱設定 RDS for Oracle 與 Amazon S3 整合的 IAM 權限。
- 執行以下命令,將錢包從 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
相關內容
已提問 3 年前
已提問 2 年前
