2016-03-02 101 views
2

我想通过gmail或雅虎主机使用PL_SQL发送电子邮件,我在谷歌搜索和找到SMT.Mail软件包,但它没有为我工作,请任何人可以指导我如何实现这一点目标?使用PLSQL发送电子邮件

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

+3

你是什么意思,“它没有为我工作”?你得到的错误是什么?请显示一些你的代码。 –

+0

什么是错误信息? –

+0

@Wernfried Domscheit当我测试这个过程时,这是错误的:ORA-29278:SMTP瞬态错误:421服务不可用 – ahad

回答

2

您在服务器错过了你的身份验证,请参阅AUTH Function and Procedure

不过,我不知道的Gmail是否允许使用25端口这是不安全默认。

1

我的经验是,utl_mail软件包使用起来要容易得多。这是一个愚蠢的例子:

BEGIN 
    UTL_MAIL.send (sender  => '[email protected]' 
       , recipients => '[email protected]' 
       , 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; 
+0

嗨@ brian-leach,我试着上面提到的脚本,但我得到错误'PLS- 00201:必须声明标识符'DBMS_NETWORK_ACL_ADMIN',可能是因为缺少对'DBMS_NETWORK_ACL_ADMIN'的授权,是否可以使用另一个用户来运行?谢谢! –

+0

对不起,迟到了,我一直在为圣日度假。具有DBA权限的人必须为您运行此脚本。 –