2016-03-02 55 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權限的人必須爲您運行此腳本。 –