查询已有ACL
SELECT host, lower_port, upper_port, acl FROM dba_network_acls;
--查询访问权限(官方地址:https://docs.oracle.com/cd/B28359_01/server.111/b28320/statviews_4143.htm#REFRN23712)
SELECT acl,
principal,
privilege,
is_grant,
to_char(start_date, 'DD-MON-YYYY') AS start_date,
to_char(end_date, 'DD-MON-YYYY') AS end_date
FROM dba_network_acl_privileges;
下面操作一定要切换到 system 管理员用户下,因为只有管理员才有dbms_network_acl_admin包的权限
一。删除ACL
BEGIN
dbms_network_acl_admin.drop_acl(acl => 'email_server_permissions.xml');
COMMIT;
END;
二。创建访问控制列表步骤
--1.创建访问控制列表(ACLemail_server_permissions)
BEGIN
dbms_network_acl_admin.create_acl(acl => 'email_server_permissions.xml',
description => 'Enables network permissions for the e-mail server',
principal => 'USER', --此为将来要进行操作的用户
is_grant => TRUE,
privilege => 'connect');
END;
--2. 将此 ACL 与邮件服务器相关联
BEGIN
dbms_network_acl_admin.assign_acl(acl => 'email_server_permissions.xml',
host => '101.101.101.101', --SMTP服务器地址
lower_port => 25,
upper_port => 25);
COMMIT;
END;
--3.创建访问控制列表(ACL)network_services
BEGIN
dbms_network_acl_admin.create_acl(acl => 'network_services.xml',
description => 'Enables network permissions for the e-mail server',
principal => 'USER', --此为将来要进行操作的用户
is_grant => TRUE,
privilege => 'connect');
END;
--4. 将此 ACL 与邮件服务器相关联 此时的端口要和第2步一致才行
BEGIN
dbms_network_acl_admin.assign_acl(acl => 'network_services.xml',
host => '101.101.101.101', --SMTP服务器地址
lower_port => 25, --端口要第二步一致
upper_port => NULL);
COMMIT;
END;
实现邮件发送的程序包,如下:
CREATE OR REPLACE PACKAGE send_mail_test_pck IS
/*===============================================================================
Program
send_mail_test
Parameter
Description
邮件发送
History
===============================================================================*/
PROCEDURE send_mail_test(p_mail_recipient VARCHAR2, -- 邮件接收人
p_subject VARCHAR2, -- 邮件标题
p_message VARCHAR2 -- 邮件正文
);
END send_mail_test_pck;
/
CREATE OR REPLACE PACKAGE BODY send_mail_test_pck IS
PROCEDURE send_mail_test(p_mail_recipient VARCHAR2, -- 邮件接收人
p_subject VARCHAR2, -- 邮件标题
p_message VARCHAR2 -- 邮件正文
) IS
lv_conn utl_smtp. connection; --到邮件服务器的连接
lv_msg VARCHAR2(4000); --邮件内容
lv_nls_characterset VARCHAR2(40);--编码格式
--下面四个变量请根据实际邮件服务器进行赋值
lv_mailhost VARCHAR2(60) := '101.101.101.101'; --SMTP服务器地址
lv_user VARCHAR2(30) := 'test@hand-china.com'; --登录SMTP服务器的用户名
lv_pass VARCHAR2(20) := 'testkey'; --登录SMTP服务器的密码
lv_sender VARCHAR2(50) := 'test@hand-china.com'; --发送者邮箱,一般与 lv_user 对应
BEGIN
--获取编码格式
SELECT VALUE
INTO lv_nls_characterset
FROM nls_database_parameters
WHERE parameter = 'NLS_CHARACTERSET';
lv_conn := utl_smtp.open_connection(lv_mailhost, 25);--创建邮件服务器连接
utl_smtp.ehlo(lv_conn, lv_mailhost); --是用 ehlo() 而不是 helo() 函数
--否则会报:ORA-29279: SMTP 永久性错误: 503 5.5.2 Send hello first.
utl_smtp.command(lv_conn, 'AUTH LOGIN'); -- smtp服务器登录校验
--登录
utl_smtp.command(lv_conn,
utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw(lv_user))));
utl_smtp.command(lv_conn,
utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw(lv_pass))));
utl_smtp.mail(lv_conn, lv_sender); --设置发件人
utl_smtp.rcpt(lv_conn, p_mail_recipient); --设置收件人
-- 创建要发送的邮件内容 注意报头信息和邮件正文之间要空一行
lv_msg := 'Date:' || to_char(SYSDATE, 'dd mon yy hh24:mi:ss') || utl_tcp.crlf || 'From: ' || '<' ||
lv_sender || '>' || utl_tcp.crlf || 'To: ' || '<' || p_mail_recipient || '>' ||
utl_tcp.crlf || 'Subject: ' || p_subject || utl_tcp.crlf || utl_tcp.crlf -- 这前面是报头信息
|| p_message; -- 这个是邮件正文
utl_smtp.open_data(lv_conn); --打开流
utl_smtp.write_raw_data(lv_conn, utl_raw.cast_to_raw(convert(lv_msg, 'ZHS16GBK', lv_nls_characterset)))); --这样写标题和内容都能用中文
utl_smtp.close_data(lv_conn); --关闭流
utl_smtp.quit(lv_conn); --关闭连接
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line(dbms_utility.format_error_stack);
dbms_output.put_line(dbms_utility.format_call_stack);
END send_mail_hand;
END send_mail_test_pck;
/