如何配置 Amazon RDS for Oracle 实例以发送电子邮件?

上次更新时间:2021 年 11 月 16 日

我想配置我的 Amazon Relational Database Service (Amazon RDS) for Oracle 数据库实例以发送电子邮件。

简短描述

要从 Amazon RDS for Oracle 实例发送电子邮件,您可以使用 UTL_MAILUTL_SMTP 程序包。

  • 要通过 RDS for Oracle 使用 UTL_MAIL,您必须在随实例附加的非默认选项组中添加 UTL_MAIL 选项。有关配置 UTL_MAIL 的更多信息,请参阅 ORACLE UTL_MAIL
  • 要通过 RDS for Oracle 使用 UTL_SMTP,您必须在本地计算机上配置 SMTP 服务器,或使用 Amazon Simple Email Service (Amazon SES) 在 Amazon Elastic Compute Cloud (Amazon EC2) 实例上配置 SMTP 服务器。在这种情况下,请确保 RDS for Oracle 与 SMTP 服务器的连接配置正确。

本文重点介绍配置数据库实例以使用 Amazon SES 通过 UTL_SMTP 程序包发送电子邮件。

作为先决条件,请确保可以从 RDS 实例访问 Amazon SES 端点。如果您的 RDS 实例在私有子网中运行,则必须在子网的路由表中添加 NAT 网关。这是子网与 Amazon SES 端点通信的必需条件。要查看子网的路由表,请打开 Amazon VPC 控制台,然后在导航窗格中选择 Route Tables(路由表)

要将数据库实例配置为发送电子邮件,请执行以下操作:

  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.    安装 Oracle 客户端,其版本最好与 Amazon RDS 实例版本相同。在本文中,使用的是 19c 版本的 Oracle。您可以下载 Oracle 19c 客户端,请参阅 Oracle 数据库 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;
/

发送电子邮件

运行以下流程发送电子邮件:

注意:请务必在流程中替换以下值:

  • example-server 替换为 SMTP 邮件服务器的名称
  • 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;
/

有关电子邮件传输服务概览的 Oracle 文档

这篇文章对您有帮助吗?


您是否需要账单或技术支持?