Procedure for sending mails
This commit is contained in:
parent
056b3bda88
commit
9bf82ae162
@ -32,6 +32,14 @@ CREATE OR REPLACE PACKAGE app_actions AS
|
||||
settings_package CONSTANT VARCHAR2(30) := 'SETT';
|
||||
settings_prefix CONSTANT VARCHAR2(30) := 'get_';
|
||||
|
||||
-- for sending emails
|
||||
smtp_from CONSTANT VARCHAR2(200) := '';
|
||||
smtp_username CONSTANT VARCHAR2(50) := NULL;
|
||||
smtp_password CONSTANT VARCHAR2(50) := NULL;
|
||||
smtp_host CONSTANT VARCHAR2(50) := '';
|
||||
smtp_port CONSTANT NUMBER(4) := 25;
|
||||
smtp_timeout CONSTANT NUMBER(2) := 20;
|
||||
|
||||
|
||||
|
||||
|
||||
@ -235,5 +243,23 @@ CREATE OR REPLACE PACKAGE app_actions AS
|
||||
--
|
||||
PROCEDURE refresh_user_source_views;
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Send UTF_8 email with compressed attachements
|
||||
--
|
||||
PROCEDURE send_mail (
|
||||
in_to VARCHAR2,
|
||||
in_subject VARCHAR2,
|
||||
in_body CLOB,
|
||||
in_cc VARCHAR2 := NULL,
|
||||
in_bcc VARCHAR2 := NULL,
|
||||
in_from VARCHAR2 := NULL,
|
||||
in_attach_name VARCHAR2 := NULL,
|
||||
in_attach_mime VARCHAR2 := NULL,
|
||||
in_attach_data CLOB := NULL,
|
||||
in_compress BOOLEAN := FALSE
|
||||
);
|
||||
|
||||
END;
|
||||
/
|
||||
|
||||
@ -816,5 +816,195 @@ CREATE OR REPLACE PACKAGE BODY app_actions AS
|
||||
app.raise_error();
|
||||
END;
|
||||
|
||||
|
||||
|
||||
PROCEDURE send_mail (
|
||||
in_to VARCHAR2,
|
||||
in_subject VARCHAR2,
|
||||
in_body CLOB,
|
||||
in_cc VARCHAR2 := NULL,
|
||||
in_bcc VARCHAR2 := NULL,
|
||||
in_from VARCHAR2 := NULL,
|
||||
in_attach_name VARCHAR2 := NULL,
|
||||
in_attach_mime VARCHAR2 := NULL,
|
||||
in_attach_data CLOB := NULL,
|
||||
in_compress BOOLEAN := FALSE
|
||||
) AS
|
||||
boundary CONSTANT VARCHAR2(80) := '-----5b9d8059445a8eb8c025f159131f02d94969a12c16363d4dec42e893b374cb85-----';
|
||||
--
|
||||
reply UTL_SMTP.REPLY;
|
||||
conn UTL_SMTP.CONNECTION;
|
||||
--
|
||||
blob_content BLOB;
|
||||
blob_gzipped BLOB;
|
||||
blob_amount BINARY_INTEGER := 6000;
|
||||
blob_offset PLS_INTEGER := 1;
|
||||
buffer VARCHAR2(24000);
|
||||
buffer_raw RAW(6000);
|
||||
--
|
||||
FUNCTION quote_encoding (
|
||||
in_text VARCHAR2
|
||||
)
|
||||
RETURN VARCHAR2 AS
|
||||
BEGIN
|
||||
RETURN '=?UTF-8?Q?' || REPLACE(
|
||||
UTL_RAW.CAST_TO_VARCHAR2(UTL_ENCODE.QUOTED_PRINTABLE_ENCODE(
|
||||
UTL_RAW.CAST_TO_RAW(in_text))), '=' || UTL_TCP.CRLF, '') || '?=';
|
||||
END;
|
||||
--
|
||||
FUNCTION quote_address (
|
||||
in_address VARCHAR2,
|
||||
in_strip_name BOOLEAN := FALSE
|
||||
)
|
||||
RETURN VARCHAR2 AS
|
||||
in_found PLS_INTEGER;
|
||||
BEGIN
|
||||
IF in_strip_name THEN
|
||||
RETURN REGEXP_REPLACE(in_address, '.*\s?<(\S+)>$', '\1');
|
||||
ELSE
|
||||
in_found := REGEXP_INSTR(in_address, '\s?<\S+@\S+\.\S{2,6}>$');
|
||||
IF in_found > 1 THEN
|
||||
RETURN quote_encoding(RTRIM(SUBSTR(in_address, 1, in_found))) || SUBSTR(in_address, in_found);
|
||||
ELSE
|
||||
RETURN in_address;
|
||||
END IF;
|
||||
END IF;
|
||||
END;
|
||||
--
|
||||
FUNCTION clob_to_blob (
|
||||
in_clob CLOB
|
||||
)
|
||||
RETURN BLOB AS
|
||||
out_blob BLOB;
|
||||
--
|
||||
v_file_size INTEGER := DBMS_LOB.LOBMAXSIZE;
|
||||
v_dest_offset INTEGER := 1;
|
||||
v_src_offset INTEGER := 1;
|
||||
v_blob_csid NUMBER := DBMS_LOB.DEFAULT_CSID;
|
||||
v_lang_context NUMBER := DBMS_LOB.DEFAULT_LANG_CTX;
|
||||
v_warning INTEGER;
|
||||
v_length NUMBER;
|
||||
BEGIN
|
||||
DBMS_LOB.CREATETEMPORARY(out_blob, TRUE);
|
||||
DBMS_LOB.CONVERTTOBLOB(out_blob, in_clob, v_file_size, v_dest_offset, v_src_offset, v_blob_csid, v_lang_context, v_warning);
|
||||
RETURN out_blob;
|
||||
END;
|
||||
--
|
||||
PROCEDURE split_addresses (
|
||||
in_out_conn IN OUT NOCOPY UTL_SMTP.CONNECTION,
|
||||
in_to IN VARCHAR2
|
||||
)
|
||||
AS
|
||||
BEGIN
|
||||
FOR i IN (
|
||||
SELECT LTRIM(RTRIM(REGEXP_SUBSTR(in_to, '[^;,]+', 1, LEVEL))) AS address
|
||||
FROM DUAL
|
||||
CONNECT BY REGEXP_SUBSTR(in_to, '[^;,]+', 1, LEVEL) IS NOT NULL)
|
||||
LOOP
|
||||
UTL_SMTP.RCPT(in_out_conn, quote_address(i.address, TRUE));
|
||||
END LOOP;
|
||||
END;
|
||||
BEGIN
|
||||
app.log_module(in_to, in_subject, in_cc, in_bcc, in_attach_name);
|
||||
|
||||
-- connect to SMTP server
|
||||
reply := UTL_SMTP.OPEN_CONNECTION(smtp_host, smtp_port, conn, smtp_timeout);
|
||||
UTL_SMTP.HELO(conn, smtp_host);
|
||||
IF smtp_username IS NOT NULL THEN
|
||||
UTL_SMTP.COMMAND(conn, 'AUTH LOGIN');
|
||||
UTL_SMTP.COMMAND(conn, UTL_ENCODE.BASE64_ENCODE(UTL_RAW.CAST_TO_RAW(smtp_username)));
|
||||
IF smtp_password IS NOT NULL THEN
|
||||
UTL_SMTP.COMMAND(conn, UTL_ENCODE.BASE64_ENCODE(UTL_RAW.CAST_TO_RAW(smtp_password)));
|
||||
END IF;
|
||||
END IF;
|
||||
|
||||
-- prepare headers
|
||||
UTL_SMTP.MAIL(conn, quote_address(COALESCE(in_from, smtp_from), TRUE));
|
||||
|
||||
-- handle multiple recipients
|
||||
split_addresses(conn, in_to);
|
||||
--
|
||||
IF in_cc IS NOT NULL THEN
|
||||
split_addresses(conn, in_cc);
|
||||
END IF;
|
||||
--
|
||||
IF in_bcc IS NOT NULL THEN
|
||||
split_addresses(conn, in_bcc);
|
||||
END IF;
|
||||
|
||||
-- continue with headers
|
||||
UTL_SMTP.OPEN_DATA(conn);
|
||||
--
|
||||
UTL_SMTP.WRITE_DATA(conn, 'Date: ' || TO_CHAR(SYSDATE, 'DD-MON-YYYY HH24:MI:SS') || UTL_TCP.CRLF);
|
||||
UTL_SMTP.WRITE_DATA(conn, 'From: ' || quote_address(COALESCE(in_from, smtp_from)) || UTL_TCP.CRLF);
|
||||
UTL_SMTP.WRITE_DATA(conn, 'To: ' || quote_address(in_to) || UTL_TCP.CRLF);
|
||||
UTL_SMTP.WRITE_DATA(conn, 'Subject: ' || quote_encoding(in_subject) || UTL_TCP.CRLF);
|
||||
UTL_SMTP.WRITE_DATA(conn, 'Reply-To: ' || in_from || UTL_TCP.CRLF);
|
||||
UTL_SMTP.WRITE_DATA(conn, 'MIME-Version: 1.0' || UTL_TCP.CRLF);
|
||||
UTL_SMTP.WRITE_DATA(conn, 'Content-Type: multipart/mixed; boundary="' || boundary || '"' || UTL_TCP.CRLF || UTL_TCP.CRLF);
|
||||
|
||||
-- prepare body content
|
||||
IF in_body IS NOT NULL THEN
|
||||
UTL_SMTP.WRITE_DATA(conn, '--' || boundary || UTL_TCP.CRLF);
|
||||
UTL_SMTP.WRITE_DATA(conn, 'Content-Type: ' || 'text/html' || '; charset="utf-8"' || UTL_TCP.CRLF);
|
||||
UTL_SMTP.WRITE_DATA(conn, 'Content-Transfer-Encoding: base64' || UTL_TCP.CRLF || UTL_TCP.CRLF);
|
||||
--
|
||||
FOR i IN 0 .. TRUNC((DBMS_LOB.GETLENGTH(in_body) - 1) / 12000) LOOP
|
||||
UTL_SMTP.WRITE_RAW_DATA(conn, UTL_ENCODE.BASE64_ENCODE(UTL_RAW.CAST_TO_RAW(DBMS_LOB.SUBSTR(in_body, 12000, i * 12000 + 1))));
|
||||
END LOOP;
|
||||
--
|
||||
UTL_SMTP.WRITE_DATA(conn, UTL_TCP.CRLF || UTL_TCP.CRLF);
|
||||
END IF;
|
||||
|
||||
-- prepare attachment
|
||||
IF in_attach_name IS NOT NULL AND in_compress THEN
|
||||
-- compress attachment
|
||||
UTL_SMTP.WRITE_DATA(conn, '--' || boundary || UTL_TCP.CRLF);
|
||||
UTL_SMTP.WRITE_DATA(conn, 'Content-Transfer-Encoding: base64' || UTL_TCP.CRLF);
|
||||
UTL_SMTP.WRITE_DATA(conn, 'Content-Type: ' || 'application/octet-stream' || UTL_TCP.CRLF);
|
||||
UTL_SMTP.WRITE_DATA(conn, 'Content-Disposition: attachment; filename="' || in_attach_name || '.gz"' || UTL_TCP.CRLF || UTL_TCP.CRLF);
|
||||
--
|
||||
blob_content := clob_to_blob(in_attach_data);
|
||||
DBMS_LOB.CREATETEMPORARY(blob_gzipped, TRUE, DBMS_LOB.CALL);
|
||||
DBMS_LOB.OPEN(blob_gzipped, DBMS_LOB.LOB_READWRITE);
|
||||
--
|
||||
UTL_COMPRESS.LZ_COMPRESS(blob_content, blob_gzipped, quality => 8);
|
||||
--
|
||||
WHILE blob_offset <= DBMS_LOB.GETLENGTH(blob_gzipped) LOOP
|
||||
DBMS_LOB.READ(blob_gzipped, blob_amount, blob_offset, buffer_raw);
|
||||
UTL_SMTP.WRITE_RAW_DATA(conn, UTL_ENCODE.BASE64_ENCODE(buffer_raw));
|
||||
blob_offset := blob_offset + blob_amount;
|
||||
END LOOP;
|
||||
DBMS_LOB.FREETEMPORARY(blob_gzipped);
|
||||
--
|
||||
UTL_SMTP.WRITE_DATA(conn, UTL_TCP.CRLF || UTL_TCP.CRLF);
|
||||
ELSIF in_attach_name IS NOT NULL THEN
|
||||
-- regular attachment
|
||||
UTL_SMTP.WRITE_DATA(conn, '--' || boundary || UTL_TCP.CRLF);
|
||||
UTL_SMTP.WRITE_DATA(conn, 'Content-Transfer-Encoding: base64' || UTL_TCP.CRLF);
|
||||
UTL_SMTP.WRITE_DATA(conn, 'Content-Type: ' || in_attach_mime || '; name="' || in_attach_name || '"' || UTL_TCP.CRLF);
|
||||
UTL_SMTP.WRITE_DATA(conn, 'Content-Disposition: attachment; filename="' || in_attach_name || '"' || UTL_TCP.CRLF || UTL_TCP.CRLF);
|
||||
--
|
||||
FOR i IN 0 .. TRUNC((DBMS_LOB.GETLENGTH(in_attach_data) - 1) / 12000) LOOP
|
||||
UTL_SMTP.WRITE_RAW_DATA(conn, UTL_ENCODE.BASE64_ENCODE(UTL_RAW.CAST_TO_RAW(DBMS_LOB.SUBSTR(in_attach_data, 12000, i * 12000 + 1))));
|
||||
END LOOP;
|
||||
--
|
||||
UTL_SMTP.WRITE_DATA(conn, UTL_TCP.CRLF || UTL_TCP.CRLF);
|
||||
END IF;
|
||||
|
||||
-- close
|
||||
UTL_SMTP.WRITE_DATA(conn, '--' || boundary || '--' || UTL_TCP.CRLF);
|
||||
UTL_SMTP.CLOSE_DATA(conn);
|
||||
UTL_SMTP.QUIT(conn);
|
||||
EXCEPTION
|
||||
WHEN UTL_SMTP.TRANSIENT_ERROR OR UTL_SMTP.PERMANENT_ERROR THEN
|
||||
BEGIN
|
||||
UTL_SMTP.QUIT(conn);
|
||||
EXCEPTION
|
||||
WHEN UTL_SMTP.TRANSIENT_ERROR OR UTL_SMTP.PERMANENT_ERROR THEN
|
||||
NULL;
|
||||
END;
|
||||
END;
|
||||
|
||||
END;
|
||||
/
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user