Complete a 3 Question Survey and Earn a re:Post Badge
Help improve AWS Support Official channel in re:Post and share your experience - complete a quick three-question survey to earn a re:Post badge!
如何从我的 Amazon RDS for Oracle 数据库实例发送电子邮件?
我想为 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 端点通信。
配置您的数据库实例以发送电子邮件
要配置您的数据库实例以发送电子邮件,请完成以下步骤:
- 使用 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 命令行界面(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 客户端和钱包
完成以下步骤:
-
安装 Oracle 客户端。
**注意:**最佳做法是使用与您的数据库实例版本相同的客户端。在本解决方法中,使用的是 Oracle 19c 版本。要下载此客户端,请参阅 Oracle 网站上的 Oracle Database 19c (19.3)。此版本自带了 orapki 实用程序。 -
打开 AWS CLI。
-
在 EC2 实例中,允许连接在 Amazon RDS 安全组中的数据库端口上。如果数据库实例和 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 RDS 控制台,然后创建选项组。
- 将 S3_INTEGRATION 选项添加到选项组。
- 使用选项组创建数据库实例。
- 创建 AWS Identity and Access Management(AWS IAM)策略和角色。有关更多信息,请参阅为与 Amazon S3 集成的 RDS for Oracle 配置 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 拥有的对象缺少某些权限,例如 expample-username 缺少 DBA_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 配置,以确认其允许在必要端口上的流量。
- 子网路由: 验证相关子网中的路由表是否已正确配置为将流量路由到数据库服务器。
- 延迟和数据包丢失: 查看延迟或数据包丢失情况。延迟和数据包丢失可能表示存在网络问题。
有关更多信息,请参阅 Oracle 网站上的使用 VPC 流日志记录 IP 流量和 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 网站上的 Overview of the email delivery service
Oracle 网站上的 UTL_SMTP