За всякакви имейли от Oracle използвам тази обща процедура в пакета PL/SQL:
CREATE OR REPLACE TYPE VARCHAR_TABLE_TYPE AS TABLE OF VARCHAR2(1000);
/
CREATE OR REPLACE PACKAGE Mailing AS
PRIORITY_HIGH CONSTANT INTEGER := 1;
PRIORITY_NORMAL CONSTANT INTEGER := 3;
PRIORITY_LOW CONSTANT INTEGER := 5;
PROCEDURE SendMail(
Subject IN VARCHAR2,
Message IN OUT CLOB,
ToMail IN VARCHAR_TABLE_TYPE,
FromMail IN VARCHAR2, FromName IN VARCHAR2,
PRIORITY IN INTEGER DEFAULT PRIORITY_NORMAL,
FileName IN VARCHAR2 DEFAULT NULL,
MimeType IN VARCHAR2 DEFAULT NULL, --> determines the MIME-Type of binary attachment "BinAttachment"
TxtAttachment IN CLOB DEFAULT NULL,
BinAttachment IN BLOB DEFAULT NULL);
END Mailing;
/
CREATE OR REPLACE PACKAGE BODY Mailing AS
PROCEDURE SendMail(
Subject IN VARCHAR2,
Message IN OUT CLOB,
ToMail IN VARCHAR_TABLE_TYPE,
FromMail IN VARCHAR2, FromName IN VARCHAR2,
PRIORITY IN T_MAIL_PRIORITY DEFAULT PRIORITY_NORMAL,
FileName IN VARCHAR2 DEFAULT NULL,
MimeType IN VARCHAR2 DEFAULT NULL,
TxtAttachment IN CLOB DEFAULT NULL,
BinAttachment IN BLOB DEFAULT NULL) IS
SMTP_PORT CONSTANT INTEGER := 25;
SMTP_SERVER CONSTANT VARCHAR2(50):= 'mailhost';
MIME_BOUNDARY CONSTANT VARCHAR2(50) := '====Multipart.Boundary.689464861147414354====';
con UTL_SMTP.CONNECTION;
ret UTL_SMTP.REPLY;
Charset VARCHAR2(20);
Footer VARCHAR2(1000);
Recipients VARCHAR2(1000);
LobLen INTEGER;
amount INTEGER := 8000;
BUFFER VARCHAR2(32000);
BUFFER_B RAW(48);
OFFSET INTEGER := 1;
isHTML BOOLEAN := REGEXP_LIKE(DBMS_LOB.SUBSTR(Message, 1000, 1), '(< *html)|(< *body)', 'i');
BEGIN
SELECT UTL_I18N.MAP_CHARSET(VALUE)
INTO Charset
FROM NLS_DATABASE_PARAMETERS
WHERE parameter = 'NLS_CHARACTERSET';
-- Append common footer to mail
Footer := 'Message from '||SYS_CONTEXT('USERENV', 'DB_NAME')||' sent at '||TO_CHAR(SYSDATE,'yyyy-mm-dd hh24:mi:ss');
IF isHTML THEN
Message := REPLACE(message, '</body>', '<p>'||Footer||'</p></body>');
END IF;
-- setup mail header
con := UTL_SMTP.OPEN_CONNECTION(SMTP_SERVER, SMTP_PORT);
ret := UTL_SMTP.HELO(con, SYS_CONTEXT('USERENV', 'DB_DOMAIN'));
ret := UTL_SMTP.MAIL(con, FromMail);
FOR i IN ToMail.FIRST..ToMail.LAST LOOP
Recipients := Recipients ||ToMail(i)||',';
ret := UTL_SMTP.RCPT(con, ToMail(i));
END LOOP;
ret := UTL_SMTP.OPEN_DATA(con);
IF CONVERT(FromName, 'US7ASCII') = FromName THEN
UTL_SMTP.WRITE_DATA(con, 'From: "'||FromName||'" <'||FromMail||'>'||UTL_TCP.CRLF);
ELSE
UTL_SMTP.WRITE_DATA(con, 'From: =?UTF-8?B?'|| UTL_ENCODE.TEXT_ENCODE(FromName, 'AL32UTF8', UTL_ENCODE.BASE64) ||'?= <'||FromMail||'>'||UTL_TCP.CRLF);
END IF;
UTL_SMTP.WRITE_DATA(con, 'To: '||REGEXP_REPLACE(Recipients, ',$')||UTL_TCP.CRLF);
IF CONVERT(Subject, 'US7ASCII') = Subject THEN
UTL_SMTP.WRITE_DATA(con, 'Subject: '||Subject||UTL_TCP.CRLF);
ELSE
UTL_SMTP.WRITE_DATA(con, 'Subject: =?UTF-8?B?'|| REPLACE(REPLACE(UTL_ENCODE.TEXT_ENCODE(Subject, 'AL32UTF8', UTL_ENCODE.BASE64), CHR(13), NULL), CHR(10), NULL) ||'?='||UTL_TCP.CRLF);
END IF;
UTL_SMTP.WRITE_DATA(con, 'Date: '||TO_CHAR(CURRENT_TIMESTAMP, 'Dy, DD Mon YYYY hh24:mi:ss TZHTZM', 'NLS_DATE_LANGUAGE = American')||UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(con, 'X-Priority: '||PRIORITY||UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(con, 'MIME-Version: 1.0' || UTL_TCP.CRLF);
IF FileName IS NOT NULL THEN
UTL_SMTP.WRITE_DATA(con, 'Content-Type: multipart/mixed; boundary="'||MIME_BOUNDARY||'"' || UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(con, 'Content-Disposition: inline'|| UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(con, UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(con, '--'||MIME_BOUNDARY || UTL_TCP.CRLF);
END IF;
IF isHTML THEN
UTL_SMTP.WRITE_DATA(con, 'Content-Type: text/html; charset='||Charset || UTL_TCP.CRLF);
ELSE
UTL_SMTP.WRITE_DATA(con, 'Content-Type: text/plain; charset='||Charset || UTL_TCP.CRLF);
END IF;
UTL_SMTP.WRITE_DATA(con, 'Content-Disposition: inline'|| UTL_TCP.CRLF);
-- Mail Body
UTL_SMTP.WRITE_DATA(con, UTL_TCP.CRLF);
LobLen := DBMS_LOB.GETLENGTH(Message);
LOOP
EXIT WHEN OFFSET > LobLen;
DBMS_LOB.READ(Message, amount, OFFSET, BUFFER);
UTL_SMTP.WRITE_RAW_DATA(con, UTL_RAW.CAST_TO_RAW(BUFFER));
OFFSET := OFFSET + amount;
END LOOP;
UTL_SMTP.WRITE_DATA(con, UTL_TCP.CRLF);
IF NOT isHTML THEN
UTL_SMTP.WRITE_DATA(con, UTL_TCP.CRLF || UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(con, Footer);
UTL_SMTP.WRITE_DATA(con, UTL_TCP.CRLF);
END IF;
IF FileName IS NOT NULL THEN
-- Mail Attachment
UTL_SMTP.WRITE_DATA(con, UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(con, '--'||MIME_BOUNDARY || UTL_TCP.CRLF);
OFFSET := 1;
IF TxtAttachment IS NOT NULL THEN
UTL_SMTP.WRITE_DATA(con, 'Content-Type: text/plain; charset='||Charset|| UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(con, 'Content-Disposition: attachment; filename="'||Filename||'"'|| UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(con, UTL_TCP.CRLF);
LobLen := DBMS_LOB.GETLENGTH(TxtAttachment);
LOOP
EXIT WHEN OFFSET > LobLen;
DBMS_LOB.READ(TxtAttachment, amount, OFFSET, BUFFER);
UTL_SMTP.WRITE_RAW_DATA(con, UTL_RAW.CAST_TO_RAW(BUFFER));
OFFSET := OFFSET + amount;
END LOOP;
ELSIF BinAttachment IS NOT NULL THEN
UTL_SMTP.WRITE_DATA(con, 'Content-Type: '||MimeType||'; name="'||Filename||'"'|| UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(con, 'Content-Disposition: attachment; filename="'||Filename||'"'|| UTL_TCP.CRLF);
UTL_SMTP.write_data(con, 'Content-Transfer-Encoding: base64' || UTL_TCP.crlf);
UTL_SMTP.WRITE_DATA(con, UTL_TCP.CRLF);
amount := 48; -- must be a whole multiple of 3
LobLen := DBMS_LOB.GETLENGTH(BinAttachment);
LOOP
EXIT WHEN OFFSET > LobLen;
DBMS_LOB.READ(BinAttachment, amount, OFFSET, BUFFER_B);
UTL_SMTP.WRITE_RAW_DATA(con, UTL_ENCODE.BASE64_ENCODE(BUFFER_B));
OFFSET := OFFSET + amount;
END LOOP;
END IF;
UTL_SMTP.WRITE_DATA(con, UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(con, '--'||MIME_BOUNDARY||'--' || UTL_TCP.CRLF);
END IF;
-- finish mail
ret := UTL_SMTP.CLOSE_DATA(con);
ret := UTL_SMTP.QUIT(con);
EXCEPTION
WHEN UTL_SMTP.TRANSIENT_ERROR OR UTL_SMTP.PERMANENT_ERROR THEN
UTL_SMTP.QUIT(con);
END SendMail;
END Mailing;
/
Той предоставя някои екстри:
- Можете по желание да прикачите файл (txt или двоичен, но се поддържа само един файл)
From
иSubject
може да съдържа знаци, различни от ASCII, като öäü (разбира се, тялото на пощата може също да)- Множество получатели
- Автоматично използвайте правилния набор от знаци от базата данни
- Автоматично открива текст на обикновен текст или HTML текст на имейла
- Общ долен колонтитул за обозначаване на поща
Забележете, не пропускайте празните редове UTL_SMTP.WRITE_DATA(con, UTL_TCP.CRLF);
, те са необходими за правилна поща.
След това можете да използвате процедурата например така:
DECLARE
Message CLOB;
BEGIN
FOR aMsg IN (SELECT Log_id, Procedure_name, Fail_type, Message FROM log_messages ORDER BY Log_id) LOOP
Message := Message || aMsg.Log_id ||' - '|| aMsg.Procedure_name ||' - '|| aMsg.Fail_type ||' - '|| aMsg.Message || CHR(13);
end loop;
SendMail(
Subject => 'You got some logs',
Message => Message,
ToMail => VARCHAR_TABLE_TYPE('[email protected]'),
FromMail => '[email protected]',
FromName => 'Oracle User: '||USER);
END;
или можете да поставите регистрационни файлове като прикачен файл по следния начин:
DECLARE
Message CLOB;
Attachment CLOB;
BEGIN
Message := 'Open attachment to see log file';
FOR aMsg IN (SELECT Log_id, Procedure_name, Fail_type, Message FROM log_messages ORDER BY Log_id) LOOP
Attachment := Attachment || aMsg.Log_id ||' - '|| aMsg.Procedure_name ||' - '|| aMsg.Fail_type ||' - '|| aMsg.Message || CHR(13);
end loop;
Mailing.SendMail(
Subject => 'You got some logs',
Message => Message,
ToMail => VARCHAR_TABLE_TYPE('[email protected]'),
FromMail => '[email protected]',
FromName => 'Oracle User: '||USER,
TxtAttachment => Attachment,
FileName => 'logfile.txt');
END;