這個網上有好多人已經做瞭解釋,相關代碼也很多,代碼參考http://hi.baidu.com/bailang3106/item/c80b0fed8a08dbd1ea34c952
http://baser.blog.51cto.com/4153192/871086
收件者只有一個的過程如下:
CREATE OR REPLACE PROCEDURE p_mail_sina(sender IN VARCHAR2,--發送人
recipient IN VARCHAR2,--接收人
subject IN VARCHAR2,--郵件主題
message IN VARCHAR2) IS --郵件內容
mailhost VARCHAR2(30) := 'smtp.sina.com' ; --新浪郵箱伺服器
c utl_smtp.connection;
msg VARCHAR2(1000);
BEGIN
msg := 'Date: ' || to_char(SYSDATE - 1, 'dd mon yy hh24:mi:ss') ||
utl_tcp.crlf || 'From: <' || sender || '>' || utl_tcp.crlf ||
'subject: ' || subject || utl_tcp.crlf || 'To: <' || recipient || '>' ||
utl_tcp.crlf || '' || utl_tcp.crlf || message;
c := utl_smtp.open_connection(mailhost, 25);
utl_smtp.command(c, 'auth login'); --1
utl_smtp.command(c, --2
utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw('使用者名稱')))); --3 --發送信箱使用者名
utl_smtp.command(c, --4
utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw('密碼'))));--5 --發送郵箱密碼
utl_smtp.helo(c, mailhost);
utl_smtp.mail(c, sender);
utl_smtp.rcpt(c, recipient);
utl_smtp.open_data(c);
utl_smtp.write_raw_data(c, utl_raw.cast_to_raw(msg));
utl_smtp.close_data(c);
utl_smtp.quit(c);
EXCEPTION
WHEN utl_smtp.transient_error OR utl_smtp.permanent_error THEN
BEGIN
utl_smtp.quit(c);
EXCEPTION
WHEN OTHERS THEN
NULL;
END;
WHEN OTHERS THEN
dbms_output.put_line(SQLERRM);
END p_mail_sina;
注意事項:
1.由於在測試中我採用的都是外網的方式發送內送郵件,因此必須加上用黃色圈出的這部分代碼進行認證。內網內部發送就不需要了,不過沒測試。
2. 黃色圈出的這部分代碼第三行和第五行填寫的內容分別是郵箱伺服器對應的信箱使用者名和密碼。
3.用於發送的郵箱的伺服器必須建立acl,主要是三個步驟
1)建立存取控制清單acl
BEGIN
DBMS_NETWORK_ACL_ADMIN.CREATE_ACL (
acl => 'email_server_permissions.xml',
description => 'Enables network permissions for the e-mail server',
principal => 'database_user',--進行操作的資料庫使用者且使用者要大寫
is_grant => TRUE,
privilege => 'connect');
END;
2)將ACL與郵件伺服器關聯(這一步,採用不同的郵箱伺服器就需要分別執行,如想用qq郵箱發送,那麼就必須換成qq郵箱伺服器執行一遍)
BEGIN
DBMS_NETWORK_ACL_ADMIN.assign_acl (
acl => 'email_server_permissions.xml',
host => 'smtp.sina.com', /*新浪的郵箱伺服器位址,如果是用qq作為發送郵件,
則用qq郵箱伺服器位址smtp.qq.com*/
lower_port => 25,
upper_port => NULL);
COMMIT;
END;
關聯後,可用dba_network_acls查看是否已經產生
SELECT host, lower_port, upper_port, acl FROM sys.dba_network_acls;
3)為執行的資料庫使用者授予串連郵件伺服器的許可權
BEGIN
dbms_network_acl_admin.add_privilege(
acl => 'email_server_permissions.xml',
principal =>'database_user',--進行操作的資料庫使用者且使用者要大寫
is_grant => TRUE,
privilege => 'connect');
END;
採用dba_network_acl_privileges視圖查看授與權限
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 sys.dba_network_acl_privileges;
4.utl_tcp.crlf作用:換行
注意在寫郵件標題,發送人,接收人,郵件內容時,各個之間一定要有換行,否則會無法發送或者是郵件內容為空白。
5.中文亂碼問題
utl_smtp.write_raw_data 用該過程替代utl_smtp.write_data可以解決中文亂碼的問題。
6.自己測試中發現如果採用qq郵箱發送郵件,則
utl_smtp.helo(c, mailhost);語句必須放在utl_smtp.command之前,否則無法發送,但是新浪郵箱則無所謂,這個不知何故。 ???
發給多個人
CREATE OR REPLACE PROCEDURE p_sendmailto_many(sender IN VARCHAR2,
recipient1 IN VARCHAR2,
recipient2 IN VARCHAR2,
recipient3 IN VARCHAR2,
subject IN VARCHAR2,
message IN VARCHAR2) IS
mailhost VARCHAR2(30) := 'smtp.qq.com';
c utl_smtp.connection;
msg VARCHAR2(1000);
BEGIN
msg := 'Date: ' || to_char(SYSDATE - 1, 'dd mon yy hh24:mi:ss') ||
utl_tcp.crlf || 'From: <' || sender || '>' || utl_tcp.crlf ||
'subject: ' || subject || utl_tcp.crlf || 'To: <' || recipient1 ||
'>;<' || recipient2 || '>' || utl_tcp.crlf || 'Cc: <' ||
recipient3 || '>' || utl_tcp.crlf || '' || utl_tcp.crlf ||
message;
c := utl_smtp.open_connection(mailhost, 25);
utl_smtp.helo(c, mailhost);
utl_smtp.command(c, 'auth login');
utl_smtp.command(c,
utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw(sender))));
utl_smtp.command(c,
utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw('password'))));
utl_smtp.mail(c, sender);
utl_smtp.rcpt(c, recipient1);
utl_smtp.rcpt(c, recipient2);
utl_smtp.rcpt(c, recipient3);
utl_smtp.open_data(c);
utl_smtp.write_raw_data(c, utl_raw.cast_to_raw(msg));
utl_smtp.close_data(c);
utl_smtp.quit(c);
END p_sendmailto_many;