使用 PLSQL 发送电子邮件
Posted
技术标签:
【中文标题】使用 PLSQL 发送电子邮件【英文标题】:Send Email Using PLSQL 【发布时间】:2016-03-02 10:29:23 【问题描述】:我想使用 PL_SQL 通过 gmail 或 yahoo 主机发送电子邮件,我在 google 中搜索并找到了 SMT.Mail 包,但它对我不起作用,请任何人指导我如何实现这个目标?
CREATE OR REPLACE PROCEDURE
send_mail (sender IN VARCHAR2,
recipient IN VARCHAR2,
message IN VARCHAR2,
nStatus OUT NUMBER)
IS
mailhost VARCHAR2(30) := 'smtp.gmail.com '; -- host mail addr
mail_conn utl_smtp.connection;
BEGIN
nStatus := 0;
mail_conn := utl_smtp.open_connection(mailhost, 25);
utl_smtp.helo(mail_conn, mailhost);
utl_smtp.mail(mail_conn, sender);
utl_smtp.rcpt(mail_conn, recipient);
utl_smtp.data(mail_conn, message);
utl_smtp.quit(mail_conn);
EXCEPTION
WHEN OTHERS THEN
nStatus := SQLCODE;
END send_mail;
当我测试这个程序时,我得到:ORA-29278: SMTP transient error: 421 Service not available
【问题讨论】:
“它对我不起作用”是什么意思?你得到什么错误?请显示您的一些代码。 错误信息是什么? @Wernfried Domscheit 这是我测试此过程时出现的错误:ORA-29278: SMTP 瞬态错误:421 服务不可用 【参考方案1】:您错过了在服务器上的身份验证,请参阅AUTH Function and Procedure
但是,我不知道gmail是否允许使用默认不安全的端口25。
【讨论】:
【参考方案2】:我的经验是 utl_mail 包更容易使用。这是一个愚蠢的例子:
BEGIN
UTL_MAIL.send (sender => 'bighearted@somewhere.com'
, recipients => 'receiver@footballreceiver.com'
, subject => 'Goofy Messages'
, MESSAGE => 'Please don''t send any more goofy messages'
, mime_type => 'text/html; charset=us-ascii');
END;
您必须将系统参数 smtp_out_server 设置为您的电子邮件服务器的名称。
对于 Oracle 11G R2 及更高版本,您必须设置正确的访问控制列表 (ACL) 才能使其正常工作。这是我用来执行此操作的代码。
DECLARE
-- ACL name to be used for email access reuse the same value for all
-- future calls
l_acl VARCHAR2 (30) := 'utl_smtp.xml';
-- Oracle user to be given permission to send email
l_principal VARCHAR2 (30) := 'CEAADMIN';
-- Name of email server
g_mailhost VARCHAR2 (60) := 'mail.yourserver.com';
l_cnt INTEGER;
PROCEDURE validate_smtp_server
AS
l_value v$parameter.VALUE%TYPE;
l_parameter v$parameter.name%TYPE := 'smtp_out_server';
BEGIN
SELECT VALUE
INTO l_value
FROM v$parameter
WHERE name = l_parameter;
IF l_value IS NULL
THEN
raise_application_error (
-20001
, 'Oracle parameter '
|| l_parameter
|| ' has not been set'
|| UTL_TCP.crlf
|| 'it s/b mail.yourserver.com'
);
END IF;
DBMS_OUTPUT.put_line ('parameter ' || l_parameter || ' value is ' || l_value);
END validate_smtp_server;
PROCEDURE create_if_needed (p_acl IN VARCHAR2)
AS
l_cnt INTEGER;
BEGIN
SELECT COUNT (*) c
INTO l_cnt
FROM dba_network_acls a
WHERE SUBSTR (acl, INSTR (acl, '/', -1) + 1) = p_acl;
IF l_cnt = 0
THEN
DBMS_OUTPUT.put_line ('creating acl ' || p_acl);
DBMS_NETWORK_ACL_ADMIN.create_acl (
acl => p_acl
, description => 'Allow use of utl_smtp'
, principal => l_principal
, is_grant => TRUE
, privilege => 'connect'
);
DBMS_NETWORK_ACL_ADMIN.assign_acl (acl => p_acl, HOST => g_mailhost);
COMMIT;
ELSE
DBMS_OUTPUT.put_line (p_acl || ' acl already exists');
END IF;
END create_if_needed;
PROCEDURE add_if_needed (
p_principal IN VARCHAR2
, p_acl IN VARCHAR2
)
AS
l_cnt INTEGER;
BEGIN
SELECT COUNT (*) c
INTO l_cnt
FROM dba_network_acl_privileges
WHERE SUBSTR (acl, INSTR (acl, '/', -1) + 1) = p_acl
AND principal = p_principal;
IF l_cnt = 0
THEN
DBMS_NETWORK_ACL_ADMIN.add_privilege (
acl => 'utl_smtp.xml'
, principal => p_principal
, is_grant => TRUE
, privilege => 'connect'
);
COMMIT;
DBMS_OUTPUT.put_line ('access to ' || p_acl || ' added for ' || p_principal);
ELSE
DBMS_OUTPUT.put_line (p_principal || ' already has access to ' || p_acl);
END IF;
END add_if_needed;
BEGIN
EXECUTE IMMEDIATE 'grant execute on utl_mail to ' || l_principal;
create_if_needed (p_acl => l_acl);
add_if_needed (p_principal => l_principal, p_acl => l_acl);
DBMS_OUTPUT.put_line ('Verification SQL:');
DBMS_OUTPUT.put_line (' SELECT * FROM dba_network_acls;');
DBMS_OUTPUT.put_line (' SELECT * FROM dba_network_acl_privileges;');
COMMIT;
validate_smtp_server;
END;
【讨论】:
嗨@brian-leach,我正在尝试上面提到的脚本,但我收到了错误PLS-00201: identifier 'DBMS_NETWORK_ACL_ADMIN' must be declared
,可能是由于缺乏对DBMS_NETWORK_ACL_ADMIN
的授权,是否有可能使用另一个用户运行它?谢谢!
抱歉回复晚了,圣日我一直在度假。必须由具有 DBA 权限的人为您运行此脚本。以上是关于使用 PLSQL 发送电子邮件的主要内容,如果未能解决你的问题,请参考以下文章
如何在不使用 Java 的情况下压缩 .csv 文件并在电子邮件中附加 Oracle plsql