尝试通过 Oracle UTL_SMTP 发送邮件时出现 ACL 错误
ACL error when trying to send mail via Oracle UTL_SMTP
我试图通过 oracle utl_smtp 发送电子邮件,但每次我执行 apex_mail_p.mail 过程时都会收到 ACL 错误,更准确地说是错误 ORA-24247。但是我已经创建了 acl,添加了正确的权限并将主机和端口添加到 ACL。我不明白为什么它会给我一个错误。
这是代码:
-- create acl
begin
dbms_network_acl_admin.create_acl (
acl => 'gmail.xml',
description => 'Normal Access',
principal => 'CONNECT',
is_grant => TRUE,
privilege => 'connect',
start_date => null,
end_date => null
);
end;
/
-- add priviliege to acl
begin
dbms_network_acl_admin.add_privilege (
acl => 'gmail.xml',
principal => 'MY_PROJECT',
is_grant => TRUE,
privilege => 'connect',
start_date => null,
end_date => null);
end;
/
-- assign host, port to acl
begin
dbms_network_acl_admin.assign_acl (
acl => 'gmail.xml',
host => 'localhost',
lower_port => 25,
upper_port => 25);
end;
/
create or replace package apex_mail_p
is
g_smtp_host varchar2 (256) := 'localhost';
g_smtp_port pls_integer := 25;
g_smtp_domain varchar2 (256) := 'gmail.com';
g_mailer_id constant varchar2 (256) := 'Mailer by Oracle UTL_SMTP';
-- send mail using UTL_SMTP
procedure mail (
p_sender in varchar2
, p_recipient in varchar2
, p_subject in varchar2
, p_message in varchar2
);
end;
/
create or replace package body apex_mail_p
is
-- Write a MIME header
procedure write_mime_header (
p_conn in out nocopy utl_smtp.connection
, p_name in varchar2
, p_value in varchar2
)
is
begin
utl_smtp.write_data ( p_conn
, p_name || ': ' || p_value || utl_tcp.crlf
);
end;
procedure mail (
p_sender in varchar2
, p_recipient in varchar2
, p_subject in varchar2
, p_message in varchar2
)
is
l_conn utl_smtp.connection;
nls_charset varchar2(255);
begin
-- get characterset
select value
into nls_charset
from nls_database_parameters
where parameter = 'NLS_CHARACTERSET';
-- establish connection and autheticate
l_conn := utl_smtp.open_connection (g_smtp_host, g_smtp_port);
utl_smtp.ehlo(l_conn, g_smtp_domain);
utl_smtp.command(l_conn, 'auth login');
utl_smtp.command(l_conn,utl_encode.text_encode('mymail@gmail.com', nls_charset, 1));
utl_smtp.command(l_conn, utl_encode.text_encode('mypassword123', nls_charset, 1));
-- set from/recipient
utl_smtp.command(l_conn, 'MAIL FROM: <'||p_sender||'>');
utl_smtp.command(l_conn, 'RCPT TO: <'||p_recipient||'>');
-- write mime headers
utl_smtp.open_data (l_conn);
write_mime_header (l_conn, 'From', p_sender);
write_mime_header (l_conn, 'To', p_recipient);
write_mime_header (l_conn, 'Subject', p_subject);
write_mime_header (l_conn, 'Content-Type', 'text/plain');
write_mime_header (l_conn, 'X-Mailer', g_mailer_id);
utl_smtp.write_data (l_conn, utl_tcp.crlf);
-- write message body
utl_smtp.write_data (l_conn, p_message);
utl_smtp.close_data (l_conn);
-- end connection
utl_smtp.quit (l_conn);
exception
when others
then
begin
utl_smtp.quit(l_conn);
exception
when others then
null;
end;
raise_application_error(-20000,'Failed to send mail due to the following error: ' || sqlerrm);
end;
end;
/
begin
apex_mail_p.mail('mymail@gmail.com', 'test@gmail.com', 'Test', 'Its only a test');
end;
/
- 将
principal
参数替换为您的数据库用户名,
- 同时添加解析权限,
- 不需要使用冗余
begin..end
块。
所以你可以考虑使用下面的那个:
-- create acl
begin
dbms_network_acl_admin.create_acl (
acl => 'gmail.xml',
description => 'Normal Access',
principal => 'DB_USER',
is_grant => TRUE,
privilege => 'connect',
start_date => null,
end_date => null);
-- add priviliege to acl
dbms_network_acl_admin.add_privilege (
acl => 'gmail.xml',
principal => 'DB_USER',
is_grant => TRUE,
privilege => 'connect',
start_date => null,
end_date => null);
dbms_network_acl_admin.add_privilege (
acl => 'gmail.xml',
principal => 'DB_USER',
is_grant => TRUE,
privilege => 'resolve',
start_date => null,
end_date => null);
-- assign host, port to acl
dbms_network_acl_admin.assign_acl (
acl => 'gmail.xml',
host => 'localhost',
lower_port => 25,
upper_port => 25);
end;
/
host
是您要连接的主机名,即 gmail 服务器。我假设 gmail 不允许纯 smtp,您必须使用端口 465 用于 SSL 或 587 用于 TLS/STARTTLS.
begin
dbms_network_acl_admin.assign_acl (
acl => 'gmail.xml',
host => 'smtp.gmail.com', -- or host => 'gmail.com', - I never used gmail in Oracle
lower_port => 465,
upper_port => 465);
end;
你也可以试试
begin
dbms_network_acl_admin.assign_acl (
acl => 'gmail.xml',
host => '*');
end;
但是,Oracle DB 可以连接到任何端口上的任何服务器,因此出于安全原因,您应该仅将其用于测试(除非您的 Oracle 服务器和互联网之间有外部防火墙)
我试图通过 oracle utl_smtp 发送电子邮件,但每次我执行 apex_mail_p.mail 过程时都会收到 ACL 错误,更准确地说是错误 ORA-24247。但是我已经创建了 acl,添加了正确的权限并将主机和端口添加到 ACL。我不明白为什么它会给我一个错误。
这是代码:
-- create acl
begin
dbms_network_acl_admin.create_acl (
acl => 'gmail.xml',
description => 'Normal Access',
principal => 'CONNECT',
is_grant => TRUE,
privilege => 'connect',
start_date => null,
end_date => null
);
end;
/
-- add priviliege to acl
begin
dbms_network_acl_admin.add_privilege (
acl => 'gmail.xml',
principal => 'MY_PROJECT',
is_grant => TRUE,
privilege => 'connect',
start_date => null,
end_date => null);
end;
/
-- assign host, port to acl
begin
dbms_network_acl_admin.assign_acl (
acl => 'gmail.xml',
host => 'localhost',
lower_port => 25,
upper_port => 25);
end;
/
create or replace package apex_mail_p
is
g_smtp_host varchar2 (256) := 'localhost';
g_smtp_port pls_integer := 25;
g_smtp_domain varchar2 (256) := 'gmail.com';
g_mailer_id constant varchar2 (256) := 'Mailer by Oracle UTL_SMTP';
-- send mail using UTL_SMTP
procedure mail (
p_sender in varchar2
, p_recipient in varchar2
, p_subject in varchar2
, p_message in varchar2
);
end;
/
create or replace package body apex_mail_p
is
-- Write a MIME header
procedure write_mime_header (
p_conn in out nocopy utl_smtp.connection
, p_name in varchar2
, p_value in varchar2
)
is
begin
utl_smtp.write_data ( p_conn
, p_name || ': ' || p_value || utl_tcp.crlf
);
end;
procedure mail (
p_sender in varchar2
, p_recipient in varchar2
, p_subject in varchar2
, p_message in varchar2
)
is
l_conn utl_smtp.connection;
nls_charset varchar2(255);
begin
-- get characterset
select value
into nls_charset
from nls_database_parameters
where parameter = 'NLS_CHARACTERSET';
-- establish connection and autheticate
l_conn := utl_smtp.open_connection (g_smtp_host, g_smtp_port);
utl_smtp.ehlo(l_conn, g_smtp_domain);
utl_smtp.command(l_conn, 'auth login');
utl_smtp.command(l_conn,utl_encode.text_encode('mymail@gmail.com', nls_charset, 1));
utl_smtp.command(l_conn, utl_encode.text_encode('mypassword123', nls_charset, 1));
-- set from/recipient
utl_smtp.command(l_conn, 'MAIL FROM: <'||p_sender||'>');
utl_smtp.command(l_conn, 'RCPT TO: <'||p_recipient||'>');
-- write mime headers
utl_smtp.open_data (l_conn);
write_mime_header (l_conn, 'From', p_sender);
write_mime_header (l_conn, 'To', p_recipient);
write_mime_header (l_conn, 'Subject', p_subject);
write_mime_header (l_conn, 'Content-Type', 'text/plain');
write_mime_header (l_conn, 'X-Mailer', g_mailer_id);
utl_smtp.write_data (l_conn, utl_tcp.crlf);
-- write message body
utl_smtp.write_data (l_conn, p_message);
utl_smtp.close_data (l_conn);
-- end connection
utl_smtp.quit (l_conn);
exception
when others
then
begin
utl_smtp.quit(l_conn);
exception
when others then
null;
end;
raise_application_error(-20000,'Failed to send mail due to the following error: ' || sqlerrm);
end;
end;
/
begin
apex_mail_p.mail('mymail@gmail.com', 'test@gmail.com', 'Test', 'Its only a test');
end;
/
- 将
principal
参数替换为您的数据库用户名, - 同时添加解析权限,
- 不需要使用冗余
begin..end
块。
所以你可以考虑使用下面的那个:
-- create acl
begin
dbms_network_acl_admin.create_acl (
acl => 'gmail.xml',
description => 'Normal Access',
principal => 'DB_USER',
is_grant => TRUE,
privilege => 'connect',
start_date => null,
end_date => null);
-- add priviliege to acl
dbms_network_acl_admin.add_privilege (
acl => 'gmail.xml',
principal => 'DB_USER',
is_grant => TRUE,
privilege => 'connect',
start_date => null,
end_date => null);
dbms_network_acl_admin.add_privilege (
acl => 'gmail.xml',
principal => 'DB_USER',
is_grant => TRUE,
privilege => 'resolve',
start_date => null,
end_date => null);
-- assign host, port to acl
dbms_network_acl_admin.assign_acl (
acl => 'gmail.xml',
host => 'localhost',
lower_port => 25,
upper_port => 25);
end;
/
host
是您要连接的主机名,即 gmail 服务器。我假设 gmail 不允许纯 smtp,您必须使用端口 465 用于 SSL 或 587 用于 TLS/STARTTLS.
begin
dbms_network_acl_admin.assign_acl (
acl => 'gmail.xml',
host => 'smtp.gmail.com', -- or host => 'gmail.com', - I never used gmail in Oracle
lower_port => 465,
upper_port => 465);
end;
你也可以试试
begin
dbms_network_acl_admin.assign_acl (
acl => 'gmail.xml',
host => '*');
end;
但是,Oracle DB 可以连接到任何端口上的任何服务器,因此出于安全原因,您应该仅将其用于测试(除非您的 Oracle 服务器和互联网之间有外部防火墙)