A client of mine uses Oracle 9i's utl_smtp to send mails out notifications to managers when their employees have made travel requests and they woul like quite a few changes made to the mailouts done.
We're having a lot of problems getting utl_smtp to talk to any smtp server on our network. We've even tried installing free smtp server on the oracle box but it will not spot the mail server running on port 25. The error code is ORA-29278.
So two questions really.
Does anyone have any experience setting up email using Oracle's utl_smtp utility and have any suggestions as to where we might be going wrong.
Does anyone know if it is possible to get utl_smtp to dump text emails to a directory much as you can do if you're using system.net.mail's specifiedpickupdirectory config setting. This would be by far the preferable option.
Thanks, Dan
Looks like the HELO is the problem. Please can we check with a simple testcase...
set serveroutput on
declare
lConnection UTL_SMTP.CONNECTION;
begin
lConnection := UTL_SMTP.OPEN_CONNECTION(your_smtp_server);
DBMS_OUTPUT.PUT_LINE('Opened ok');
UTL_SMTP.HELO(lConnection, your_client_machine_name);
DBMS_OUTPUT.PUT_LINE('HELO ok');
UTL_SMTP.MAIL(lConnection, your_email_address);
UTL_SMTP.RCPT(lConnection, your_email_address);
DBMS_OUTPUT.PUT_LINE('Addressing ok');
end;
/
Looks like we've resolved this.
To answer the two questions.
Double check that the schema calling utl_smtp has execute permissions on sys.utl_smtp, sys.utl_tcp and sys.dbms_lob. Also check that at no time the message being sent is > 32Kb.
No there is no way to get utl_smtp to dump emails to a directory a la system.net.mail.
Thanks to cagcowboy for the help.
Yes, we can telnet to the server.
-- ****** Object: Stored Procedure TRAVELADMIN_DEV.HTML_EMAIL Script Date: 22/08/2008 12:41:02 ******
CREATE PROCEDURE "HTML_EMAIL" (
p_to in varchar2,
p_cc in varchar2,
p_from in varchar2,
p_subject in varchar2,
p_text in varchar2 default null,
p_html in varchar2 default null
)
is
l_boundary varchar2(255) default 'a1b2c3d4e3f2g1';
l_connection utl_smtp.connection;
l_body_html clob := empty_clob; --This LOB will be the email message
l_offset number;
l_ammount number;
l_temp varchar2(32767) default null;
p_smtp_hostname varchar2(30):= 'rockies';
p_smtp_portnum varchar2(2) := '25';
begin
l_connection := utl_smtp.open_connection( p_smtp_hostname, p_smtp_portnum );
utl_smtp.helo( l_connection, p_smtp_hostname );
utl_smtp.mail( l_connection, p_from );
utl_smtp.rcpt( l_connection, p_to );
l_temp := l_temp || 'MIME-Version: 1.0' || chr(13) || chr(10);
l_temp := l_temp || 'To: ' || p_to || chr(13) || chr(10);
IF ((p_cc <> NULL) OR (LENGTH(p_cc) > 0)) THEN
l_temp := l_temp || 'Cc: ' || p_cc || chr(13) || chr(10);
utl_smtp.rcpt( l_connection, p_cc );
END IF;
l_temp := l_temp || 'From: ' || p_from || chr(13) || chr(10);
l_temp := l_temp || 'Subject: ' || p_subject || chr(13) || chr(10);
l_temp := l_temp || 'Reply-To: ' || p_from || chr(13) || chr(10);
l_temp := l_temp || 'Content-Type: multipart/alternative; boundary=' ||
chr(34) || l_boundary || chr(34) || chr(13) ||
chr(10);
----------------------------------------------------
-- Write the headers
dbms_lob.createtemporary( l_body_html, false, 10 );
dbms_lob.write(l_body_html,length(l_temp),1,l_temp);
----------------------------------------------------
-- Write the text boundary
l_offset := dbms_lob.getlength(l_body_html) + 1;
l_temp := '--' || l_boundary || chr(13)||chr(10);
l_temp := l_temp || 'content-type: text/plain; charset=us-ascii' ||
chr(13) || chr(10) || chr(13) || chr(10);
dbms_lob.write(l_body_html,length(l_temp),l_offset,l_temp);
----------------------------------------------------
-- Write the plain text portion of the email
l_offset := dbms_lob.getlength(l_body_html) + 1;
dbms_lob.write(l_body_html,length(p_text),l_offset,p_text);
----------------------------------------------------
-- Write the HTML boundary
l_temp := chr(13)||chr(10)||chr(13)||chr(10)||'--' || l_boundary ||
chr(13) || chr(10);
l_temp := l_temp || 'content-type: text/html;' ||
chr(13) || chr(10) || chr(13) || chr(10);
l_offset := dbms_lob.getlength(l_body_html) + 1;
dbms_lob.write(l_body_html,length(l_temp),l_offset,l_temp);
----------------------------------------------------
-- Write the HTML portion of the message
l_offset := dbms_lob.getlength(l_body_html) + 1;
dbms_lob.write(l_body_html,length(p_html),l_offset,p_html);
----------------------------------------------------
-- Write the final html boundary
l_temp := chr(13) || chr(10) || '--' || l_boundary || '--' || chr(13);
l_offset := dbms_lob.getlength(l_body_html) + 1;
dbms_lob.write(l_body_html,length(l_temp),l_offset,l_temp);
----------------------------------------------------
-- Send the email in 1900 byte chunks to UTL_SMTP
l_offset := 1;
l_ammount := 1900;
utl_smtp.open_data(l_connection);
while l_offset < dbms_lob.getlength(l_body_html) loop
utl_smtp.write_data(l_connection,
dbms_lob.substr(l_body_html,l_ammount,l_offset));
l_offset := l_offset + l_ammount ;
l_ammount := least(1900,dbms_lob.getlength(l_body_html) - l_ammount);
end loop;
utl_smtp.close_data(l_connection);
utl_smtp.quit( l_connection );
dbms_lob.freetemporary(l_body_html);
end;
The OPEN_CONNECTION parameter should be the FQDN or IP address of the server you're connecting to.
The HELO parameter should be the FQDN of the machine you're connecting from.
If this doesn't work, do you know which line it errors on?
Related
Need help in sending excel file as an attachment which is stored in directory of a server.
I have a procedure which writes a file to server and need to send it as as attachement with HTML body message which includes multiple tables and excel attachement. but i am quite stuck in attachment part for now!.
CREATE OR REPLACE PROCEDURE p_send_email_with_attach as
file_handle utl_file.file_type;
output VARCHAR2(32767);
attachment_text VARCHAR2(32767);
v_dir VARCHAR2(300) := 'RPT_DIR';
v_recipients VARCHAR2(2000) := 'abc#gmail.com';
v_sub VARCHAR2(300) := 'Hello';
v_smtp_server VARCHAR2(255) := 'mailhost';
conn utl_smtp.connection;
c_mime_boundary CONSTANT VARCHAR2(256) := 'the boundary can be almost anything';
v_from_name VARCHAR2(100) := 'xyz#yahoo.com';
BEGIN
file_handle := utl_file.fopen(
location => v_dir,
filename => 'My_First_CSV.CSV',
open_mode => 'R'
);
LOOP
BEGIN
utl_file.get_line(
file_handle,
output
); -- we read the file, line by line
attachment_text := attachment_text || utl_tcp.crlf; --and store every line in
the attachment_text variable, separated by a ?new line? character.
EXCEPTION
WHEN no_data_found THEN
EXIT;
END;
END LOOP;
utl_file.fclose(file_handle);
conn := utl_smtp.open_connection('mailhost');
utl_smtp.helo(conn, 'mailhost');
utl_smtp.mail(conn, v_from_name);
FOR cur_r IN (
SELECT level AS id, regexp_substr(email_id, '[^;]+', 1, level) AS v_recipient
FROM
email_address
CONNECT BY regexp_substr( email_id, '[^;]+', 1, level) IS NOT NULL
) LOOP
utl_smtp.rcpt(conn,cur_r.v_recipient);
END LOOP;
UTL_SMTP.write_data(conn, '--' || c_mime_boundary || UTL_TCP.crlf);
UTL_SMTP.write_data(conn, 'Content-Type: text/plain' || UTL_TCP.crlf);
UTL_SMTP.write_data(
conn,
'Content-Disposition: attachment; filename="' || 'My_First_CSV.CSV' || '"' || UTL_TCP.crlf
);
utl_smtp.open_data(conn);
EXCEPTION
WHEN OTHERS THEN
raise_application_error(
-20001,
'Error: ' || sqlerrm
);
END;
i beleive i am missing something while writing, kindly help in fixing this. thanks :)
The following PL/SQL program that sends email, which uses basic authentication to authenticate to sendgrid, was working until yesterday.
create or replace PROCEDURE ENVIA_EMAIL( p_remetente IN VARCHAR2
,p_destinatario IN VARCHAR2
,p_titulo_email IN VARCHAR2
,p_mensagem IN VARCHAR2
,p_dsc_arquivo_atachado1 IN VARCHAR2 DEFAULT NULL
,p_tipo_arquivo1 IN VARCHAR2 DEFAULT 'TEXT'
,p_dsc_arquivo_atachado2 IN VARCHAR2 DEFAULT NULL
,p_tipo_arquivo2 IN VARCHAR2 DEFAULT 'TEXT'
,p_dsc_arquivo_atachado3 IN VARCHAR2 DEFAULT NULL
,p_tipo_arquivo3 IN VARCHAR2 DEFAULT 'TEXT'
,p_username IN VARCHAR2
,p_password IN VARCHAR2) IS
--
-- Declaracao de variaveis
w_usuario NUMBER(10);
w_smtp_ip VARCHAR2(30) := 'smtp.sendgrid.net';
w_smtp_porta NUMBER := 587;
boundary CONSTANT VARCHAR2(256) := 'CES.Boundary.DACA587499938897';
w_conexao UTL_SMTP.CONNECTION;
w_mensagem VARCHAR2(30000);
w_nova_linha VARCHAR(2) := chr(13)||chr(10);
wrk_local NUMBER;
w_destinatario VARCHAR2(500);
w_destinatario_todo VARCHAR2(500);
w_destin_todo_fixo VARCHAR2(500);
TYPE varchar2_table IS TABLE OF VARCHAR2(256) INDEX BY BINARY_INTEGER;
w_contador BINARY_INTEGER;
function subject_encode(s_string varchar2) return varchar2 is
temp_subject varchar2(6000);
lengthsubject pls_integer:= 40;
w_nova_linha VARCHAR(2) := chr(13)||chr(10);
count_length pls_integer;
begin
count_length:=CEIL(LENGTH(s_string)/lengthsubject);
temp_subject:='=?iso-8859-1?B?' ||
utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw(substr(s_string,1,lengthsubject ))))|| '?=';
for i in 2..count_length loop
temp_subject:=temp_subject||'=?iso-8859-1?B?'||
utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw( SUBSTR(s_string,1+(lengthsubject*(i-1)) ,lengthsubject ))))|| '?=';
end loop;
return temp_subject;
end;
BEGIN
w_destinatario_todo := p_destinatario||';';
w_destin_todo_fixo := p_destinatario;
LOOP
w_destinatario := substr(w_destinatario_todo,1,(instr(w_destinatario_todo,';')) - 1);
w_destinatario_todo := substr(w_destinatario_todo,(instr(w_destinatario_todo,';') + 1));
IF w_destinatario IS NOT NULL THEN
-- Abrindo Conexao SMTP e HTTP
w_conexao := utl_smtp.open_connection(w_smtp_ip,w_smtp_porta);
-- Comunicando SMTP
utl_smtp.helo(w_conexao, w_smtp_ip);
-- Autenticacao INICIO
utl_smtp.command(w_conexao,'AUTH LOGIN');
utl_smtp.command(w_conexao,utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw(('username')))));
utl_smtp.command(w_conexao,utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw(('password')))));
utl_smtp.mail(w_conexao,('<'||'myusername#myhost.com.br'||'>'));
utl_smtp.rcpt(w_conexao,('<'||w_destinatario||'>'));
utl_smtp.open_data (w_conexao);
-- Criando Cabeca do E-mail
w_mensagem := 'Date: '||TO_CHAR(SYSDATE,'dd Mon yy hh24:mi:ss')||w_nova_linha||
'From: '||p_remetente||w_nova_linha||
'To: '||w_destin_todo_fixo||w_nova_linha||
'Subject: '||subject_encode(p_titulo_email)||w_nova_linha;
--- 'To: '||w_destin_todo_fixo||w_nova_linha;
-- w_mensagem := w_mensagem || 'Mime-Version: 1.0' || w_nova_linha ||
-- 'Content-Type: multipart/mixed; boundary="' || boundary || '"' || w_nova_linha || w_nova_linha; --||
utl_smtp.write_data(w_conexao,w_mensagem);
--
IF p_mensagem IS not NULL THEN
w_mensagem := '--' || boundary || w_nova_linha ||
'Content-Type: text/html; charset=iso-8859-1' || w_nova_linha ||
'Content-Transfer-Encoding: base64' || w_nova_linha || w_nova_linha;
utl_smtp.write_data(w_conexao,w_mensagem);
utl_smtp.write_data(w_conexao,utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw(p_mensagem)))|| w_nova_linha);
END IF;
-- Append the final boundary line
-- w_mensagem := w_nova_linha || '--' || boundary || '--' || w_nova_linha;
-- utl_smtp.write_data(w_conexao,w_mensagem);
-- Fechando conexao SMTP
utl_smtp.close_data(w_conexao);
utl_smtp.quit(w_conexao);
-- Insere um registro de emails.
BEGIN
w_usuario := substr(USER,2,50);
EXCEPTION
WHEN OTHERS THEN
w_usuario := 0;
END;
END IF;
IF w_destinatario_todo IS NULL THEN
EXIT;
END IF;
END LOOP;
END;
Yesterday sendgrid stopped supporting basic authentication. Now sendgrid require that an api key is used to authenticate.
I followed sendgrid instructions and created an api key via UI portal. Also, I replaced the username and password in the e-mail program with the values of "apikey"(username) and "actualKey"(password) according to sendgrid documentation as illustrated below.
utl_smtp.command(w_conexao,utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw(('apikey')))));
utl_smtp.command(w_conexao,utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw(('Sdyg.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX')))));
However, I am getting the following error when attempting to send an e-mail.
"The provided authorization grant is invalid, expired or revoked"
Any advice on how I could fix that?
The issue was that a line break is added when the following is executed
select utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw(('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')))) from dual;
the output is
U0cuNkU5TExrMHNUamZ0YzZxbG04ZXpnUS5raXhJd2RTSWV0RGE4d0ZUYnNNZHFf
Z1hWeVgxM3dtSHhGdlU5SHZmOTlv
To remove that line break, I modified that statement to look like that
select replace(replace(replace(utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw(('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')))),chr(10),' '),chr(13),' '),' ','') from dual;
the output is
U0cuNkU5TExrMHNUamZ0YzZxbG04ZXpnUS5raXhJd2RTSWV0RGE4d0ZUYnNNZHFfZ1hWeVgxM3dtSHhGdlU5SHZmOTlv
I have a .txt file in which I have stored my data Semicolon-separated.
The file is stored at backend in a Clob.
File:
ABCD;HEAD; 1.0;00204;18.05.2015;00000000;00000000000.00;18.05.2015
I need to send this text file as an attachment via Stored Procedure in Oracle.
Problem:
I get this encoded file attached in the Email:
4546554C3B484541443B20202020202020312E303B30303634323B31382E30352E323031353B30303030303030313B30303030303030303032302E30303B31382E30352E323031350A4546554C3B444154413B20202020202020312E303B4546554C3B303030543130303030303335303B313B31382E30352E323031353B303030303032302C3030302E30303B504B523B3132363435363135313231313B303235303533313030310D0A
Procedure:
CREATE OR REPLACE PROCEDURE SENDMAIL_ATT
(
MSG_FROM VARCHAR2,
MSG_TO VARCHAR2,
MSG_SUBJECT VARCHAR2,
MSG_TEXT VARCHAR2,
MSG_ATT CLOB,
ATT_FILENAME VARCHAR2
) IS
V_MAILHOST VARCHAR2(50) := 'mail_server';
V_PORT NUMBER(2) := 25;
V_HELO VARCHAR2(50) := 'localhost';
C UTL_TCP.CONNECTION;
RC INTEGER;
CRLF VARCHAR2(2) := CHR(13) || CHR(10);
MESG VARCHAR2(32767);
V_BUFFER_SIZE CONSTANT PLS_INTEGER := 4000;
V_BUFFER_NEXT PLS_INTEGER := 4000;
V_BODY_BUFFER VARCHAR2(8000 CHAR);
BEGIN
C := UTL_TCP.OPEN_CONNECTION(V_MAILHOST, V_PORT); -- open the SMTP port
DBMS_OUTPUT.PUT_LINE(UTL_TCP.GET_LINE(C, TRUE));
RC := UTL_TCP.WRITE_LINE(C, 'HELO ' || V_HELO);
DBMS_OUTPUT.PUT_LINE(UTL_TCP.GET_LINE(C, TRUE));
RC := UTL_TCP.WRITE_LINE(C, 'MAIL FROM: ' || MSG_FROM); ----- MAIL BOX SENDING THE EMAIL
DBMS_OUTPUT.PUT_LINE(UTL_TCP.GET_LINE(C, TRUE));
RC := UTL_TCP.WRITE_LINE(C, 'RCPT TO: ' || MSG_TO); ----- MAIL BOX RECIEVING THE EMAIL
DBMS_OUTPUT.PUT_LINE(UTL_TCP.GET_LINE(C, TRUE));
RC := UTL_TCP.WRITE_LINE(C, 'DATA'); ----- EMAIL MESSAGE BODY START
DBMS_OUTPUT.PUT_LINE(UTL_TCP.GET_LINE(C, TRUE));
RC := UTL_TCP.WRITE_LINE(C,'Date: ' ||
TO_CHAR(SYSDATE, 'dd Mon yy hh24:mi:ss'));
RC := UTL_TCP.WRITE_LINE(C, 'From: ' || MSG_FROM);
RC := UTL_TCP.WRITE_LINE(C, 'MIME-Version: 1.0');
RC := UTL_TCP.WRITE_LINE(C, 'To: ' || MSG_TO);
RC := UTL_TCP.WRITE_LINE(C, 'Subject: ' || MSG_SUBJECT);
RC := UTL_TCP.WRITE_LINE(C, 'Content-Type: multipart/mixed;'); ----- INDICATES THAT THE BODY CONSISTS OF MORE THAN ONE PART
RC := UTL_TCP.WRITE_LINE(C, ' boundary="-----SECBOUND"'); ----- SEPERATOR USED TO SEPERATE THE BODY PARTS
RC := UTL_TCP.WRITE_LINE(C); ----- DO NOT REMOVE THIS BLANK LINE - PART OF MIME STANDARD
RC := UTL_TCP.WRITE_LINE(C, '-------SECBOUND');
RC := UTL_TCP.WRITE_LINE(C, 'Content-Type: text/html'); ----- 1ST BODY PART. EMAIL TEXT MESSAGE
RC := UTL_TCP.WRITE_LINE(C, 'Content-Transfer-Encoding: 7bit');
RC := UTL_TCP.WRITE_LINE(C);
RC := UTL_TCP.WRITE_LINE(C, MSG_TEXT); ----- TEXT OF EMAIL MESSAGE
RC := UTL_TCP.WRITE_LINE(C);
RC := UTL_TCP.WRITE_LINE(C, '-------SECBOUND');
RC := UTL_TCP.WRITE_LINE(C, 'Content-Type: text/plain;'); ----- 2ND BODY PART.
RC := UTL_TCP.WRITE_LINE(C, ' name="' || ATT_FILENAME || '"');
RC := UTL_TCP.WRITE_LINE(C, 'Content-Transfer_Encoding: 7bit');
RC := UTL_TCP.WRITE_LINE(C, 'Content-Disposition: attachment;'); ----- INDICATES THAT THIS IS AN ATTACHMENT
RC := UTL_TCP.WRITE_LINE(C, ' filename="' || ATT_FILENAME || '"'); ----- SUGGESTED FILE NAME FOR ATTACHMENT
RC := UTL_TCP.WRITE_LINE(C);
--CLOB
FOR I IN 0 .. FLOOR(DBMS_LOB.GETLENGTH(MSG_ATT) / V_BUFFER_SIZE)
LOOP
DBMS_LOB.READ(MSG_ATT,
V_BUFFER_NEXT,
I * V_BUFFER_SIZE + 1,
V_BODY_BUFFER);
RC := UTL_TCP.WRITE_TEXT(C, V_BODY_BUFFER);
END LOOP;
RC := UTL_TCP.WRITE_LINE(C);
RC := UTL_TCP.WRITE_LINE(C, '.'); ----- EMAIL MESSAGE BODY END
DBMS_OUTPUT.PUT_LINE(UTL_TCP.GET_LINE(C, TRUE));
RC := UTL_TCP.WRITE_LINE(C, 'QUIT'); ----- ENDS EMAIL TRANSACTION
DBMS_OUTPUT.PUT_LINE(UTL_TCP.GET_LINE(C, TRUE));
UTL_TCP.CLOSE_CONNECTION(C); ----- CLOSE SMTP PORT CONNECTION
EXCEPTION
WHEN OTHERS THEN
RAISE;
END SENDMAIL_ATT;
Procedure Call:
declare
-- Local variables here
l_clob clob;
fileName varchar2(100);
begin
SELECT file_name, file_content
INTO fileName, l_clob
FROM my_table
WHERE ID = 141;
SENDMAIL_ATT(MSG_FROM => 'myemail#myDomain.com',
MSG_TO => 'myemail#myDomain.com',
MSG_SUBJECT => 'Test Email',
MSG_TEXT => 'Some Subject',
MSG_ATT => l_clob,
ATT_FILENAME => fileName);
end;
I use this package to send out mails. It works fine with attachments, try it out:
CREATE OR REPLACE PACKAGE BODY SENDMAIL_PKG AS
PRIORITY_HIGH CONSTANT INTEGER := 1;
PRIORITY_NORMAL CONSTANT INTEGER := 3;
PRIORITY_LOW CONSTANT INTEGER := 5;
SMTP_PORT CONSTANT INTEGER := 25;
SMTP_SERVER CONSTANT VARCHAR2(50) := 'mailhost';
SMTP_DOMIAN CONSTANT VARCHAR2(50) := SYS_CONTEXT('USERENV', 'DB_DOMAIN');
MIME_BOUNDARY CONSTANT VARCHAR2(50) := '=====Boundary======';
MIME_MIXED CONSTANT VARCHAR2(50) := 'multipart/mixed;';
MIME_TEXT CONSTANT VARCHAR2(50) := 'text/plain;';
DEFAULT_FROM_NAME CONSTANT VARCHAR2(50) := SYS_CONTEXT('USERENV', 'CURRENT_SCHEMA');
DEFAULT_FROM_MAIL CONSTANT VARCHAR2(50) := DEFAULT_FROM_NAME||'#'||SMTP_DOMIAN;
FUNCTION OpenConnection(ToEmail IN VARCHAR2, FromEmail IN VARCHAR2) RETURN UTL_SMTP.connection IS
con UTL_SMTP.connection;
BEGIN
-- setup mail header
con := UTL_SMTP.OPEN_CONNECTION(SMTP_SERVER, SMTP_PORT);
UTL_SMTP.helo(con, SMTP_DOMIAN);
UTL_SMTP.Mail(con, LOWER(FromEmail));
UTL_SMTP.rcpt(con, LOWER(ToEmail));
UTL_SMTP.open_data(con);
RETURN con;
END OpenConnection;
PROCEDURE PutHeader(con IN OUT UTL_SMTP.connection,
Subject IN VARCHAR2, ToEmail IN VARCHAR2,
FromEmail IN VARCHAR2, FromName IN VARCHAR2,
Priority IN INTEGER) IS
BEGIN
UTL_SMTP.write_data(con, 'From: "'||FromName||'" <'||LOWER(FromEmail)||'>'||UTL_TCP.CRLF);
UTL_SMTP.write_data(con, 'To: <'||LOWER(ToEmail)||'>'||UTL_TCP.CRLF);
UTL_SMTP.write_data(con, 'Subject: '||Subject||UTL_TCP.CRLF);
UTL_SMTP.write_data(con, 'X-Priority: '||Priority||UTL_TCP.CRLF);
END PutHeader;
PROCEDURE CloseMail(con IN OUT UTL_SMTP.connection) IS
BEGIN
-- finish mail
UTL_SMTP.close_data(con);
UTL_SMTP.quit(con);
END CloseMail;
-- Append default footer at the end of mail
PROCEDURE PutFooter(con IN OUT UTL_SMTP.connection) IS
sender VARCHAR2(1000);
BEGIN
-- put footer to end of mail
UTL_SMTP.write_data(con, UTL_TCP.CRLF || UTL_TCP.CRLF);
sender := SYS_CONTEXT('USERENV', 'DB_NAME')||'.'||SYS_CONTEXT('USERENV', 'DB_DOMAIN');
UTL_SMTP.write_data(con, 'Message from '||sender||' sent at '||TO_CHAR(LOCALTIMESTAMP, 'yyyy-mm-dd hh24:mi:ss'));
UTL_SMTP.write_data(con, UTL_TCP.CRLF);
END PutFooter;
-- Send Mail with CLOB attachment
PROCEDURE SendMail(
Subject IN VARCHAR2,
Message IN VARCHAR2,
ToEmail IN VARCHAR2,
Attachment IN CLOB, FilenameAttachment IN VARCHAR2,
FromEmail IN VARCHAR2 DEFAULT DEFAULT_FROM_MAIL,
FromName IN VARCHAR2 DEFAULT DEFAULT_FROM_NAME,
Priority IN INTEGER DEFAULT PRIORITY_NORMAL) IS
con UTL_SMTP.connection;
AttachmentLength PLS_INTEGER;
amount BINARY_INTEGER := 30000;
BUFFER VARCHAR2(32000);
offset PLS_INTEGER := 1;
BEGIN
con := OpenConnection(ToEmail, FromEmail);
PutHeader(con, Subject, ToEmail, FromEmail, FromName, Priority);
UTL_SMTP.write_data(con, 'Mime-Version: 1.0' || UTL_TCP.CRLF);
UTL_SMTP.write_data(con, 'Content-Type: '||MIME_MIXED||' boundary="'||MIME_BOUNDARY||'"' || UTL_TCP.CRLF);
UTL_SMTP.write_data(con, '--'||MIME_BOUNDARY || UTL_TCP.CRLF);
UTL_SMTP.write_data(con, 'Content-type: text/plain' || UTL_TCP.CRLF);
-- Mail Body
UTL_SMTP.write_data(con, UTL_TCP.CRLF);
UTL_SMTP.write_raw_data(con, UTL_RAW.cast_to_raw(Message));
UTL_SMTP.write_data(con, UTL_TCP.CRLF);
PutFooter(con);
-- Mail Attachment
UTL_SMTP.write_data(con, UTL_TCP.CRLF);
UTL_SMTP.write_data(con, '--'||MIME_BOUNDARY || UTL_TCP.CRLF);
UTL_SMTP.write_data(con, 'Content-Type: '||MIME_TEXT||' name="'||FilenameAttachment||'"'|| UTL_TCP.CRLF);
UTL_SMTP.write_data(con, 'Content-Disposition: attachment; filename="'||FilenameAttachment||'"'|| UTL_TCP.CRLF);
UTL_SMTP.write_data(con, UTL_TCP.CRLF);
AttachmentLength := DBMS_LOB.GETLENGTH(Attachment);
LOOP
EXIT WHEN offset > AttachmentLength;
DBMS_LOB.READ(Attachment, 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);
UTL_SMTP.write_data(con, '--'||MIME_BOUNDARY||'--' || UTL_TCP.CRLF);
CloseMail(con);
END SendMail;
-- Send plain Mail without attachment
PROCEDURE SendMail(
Subject IN VARCHAR2,
Message IN VARCHAR2,
ToEmail IN VARCHAR2,
FromEmail IN VARCHAR2 DEFAULT DEFAULT_FROM_MAIL,
FromName IN VARCHAR2 DEFAULT DEFAULT_FROM_NAME,
Priority IN INTEGER DEFAULT PRIORITY_NORMAL) IS
con UTL_SMTP.connection;
BEGIN
con := OpenConnection(ToEmail, FromEmail);
PutHeader(con, Subject, ToEmail, FromEmail, FromName, Priority);
UTL_SMTP.write_data(con, 'Content-type: '||MIME_TEXT ||' charset='||GetCharset||UTL_TCP.CRLF );
UTL_SMTP.write_data(con, UTL_TCP.CRLF);
UTL_SMTP.write_raw_data(con, UTL_RAW.cast_to_raw(Message));
UTL_SMTP.write_data(con, UTL_TCP.CRLF);
PutFooter(con);
CloseMail(con);
END SendMail;
END SENDMAIL_PKG;
I'm attempting to use Oracle's 11.g's UTL_SMTP to send a message body that includes an embedded image. I have this process working for a standard text body, and for an eMail that may contain attachments (Word doc, JPG image, etc.). I'm stuck on making this work with an image embedded in the body of the eMail. When I include and embedded image, the eMail displays in Outlook 2013 as a red X where the image should be. The rest of the text appears fine. The html body of the eMail is passed in to the procedure via "p_html".
My Procedure looks like this:
create or replace procedure html_email_attachments(
p_to in varchar2,
p_from in varchar2,
p_subject in varchar2,
p_text in varchar2 default null,
p_html in varchar2 default null,
p_smtp_hostname in varchar2,
p_smtp_portnum in varchar2,
p_smtp_username in varchar2,
p_smtp_password in varchar2,
p_event_pkey in number
)
is
l_boundary varchar2(255) default 'a1b2c3d4e3f2g1';
l_connection utl_smtp.connection;
l_body_html clob := empty_clob; --This LOB will be the email message
l_offset number;
l_ammount number;
l_temp varchar2(32767) default null;
l_encoded_username varchar2(2048);
l_encoded_password varchar2(2048);
l_attach_mime varchar2(1024);
l_attach_name varchar2(1024);
l_attach_blob blob;
l_attachment_pkeys DBMS_SQL.varchar2_table;
l_step PLS_INTEGER := 12000; -- A multiple of 3 and <= 24573
crlf varchar2(2) := CHR(13) || CHR(10);
diag varchar2(4000);
v_raw raw(57);
v_length integer := 0;
v_buffer_size integer := 57;
v_offset integer := 1;
begin
-- Store all the attachment primary keys into l_attachment_pkeys
Select ma.prim_key Bulk Collect Into l_attachment_pkeys
From mail_attachment ma
Where ma.event_fkey = p_event_pkey;
-- Encode p_smtp_username and p_smtp_password
l_encoded_username := UTL_RAW.cast_to_varchar2
(UTL_ENCODE.base64_encode(UTL_RAW.cast_to_raw(p_smtp_username)));
l_encoded_password := UTL_RAW.cast_to_varchar2
(UTL_ENCODE.base64_encode(UTL_RAW.cast_to_raw(p_smtp_password)));
-- set the l_connection variable
l_connection := UTL_SMTP.open_connection(p_smtp_hostname, p_smtp_portnum);
-- begin the connection
utl_smtp.ehlo(l_connection, p_smtp_hostname);--DO NOT USE HELO
-- authenticate to the server using the encoded username and password
utl_smtp.command(l_connection, 'AUTH', 'LOGIN');
utl_smtp.command(l_connection, l_encoded_username);
utl_smtp.command(l_connection, l_encoded_password);
-- First, establish the mail's From and To. This is essential
utl_smtp.mail( l_connection, p_from );
utl_smtp.rcpt( l_connection, p_to );
-- Define the Header
l_temp := l_temp || 'MIME-Version: 1.0' || crlf;
l_temp := l_temp || 'To: ' || p_to || crlf;
l_temp := l_temp || 'From: ' || p_from || crlf;
l_temp := l_temp || 'Subject: ' || p_subject || crlf;
l_temp := l_temp || 'Reply-To: ' || p_from || crlf;
l_temp := l_temp || 'Content-Type: multipart/mixed; boundary=' ||
chr(34) || l_boundary || chr(34) || crlf;
----------------------------------------------------
-- Write the headers
dbms_lob.createtemporary( l_body_html, false, 10 );
dbms_lob.write(l_body_html,length(l_temp),1,l_temp);
----------------------------------------------------
-- Write the HTML boundary
-- Identify the content type as text/html
-- Determine the offset (initially it's 1)
-- Write out
l_temp := crlf || crlf ||'--' || l_boundary || crlf;
l_temp := l_temp || 'content-type: text/html;' || crlf || crlf;
l_offset := dbms_lob.getlength(l_body_html) + 1;
dbms_lob.write(l_body_html,length(l_temp),l_offset,l_temp);
----------------------------------------------------
-- Write the HTML portion of the message
l_offset := dbms_lob.getlength(l_body_html) + 1;
dbms_lob.write(l_body_html,length(p_html),l_offset,p_html);
----------------------------------------------------
-- Send the email body in 1900 byte chunks to UTL_SMTP
l_offset := 1;
l_ammount := 1900;
utl_smtp.open_data(l_connection);
while l_offset < dbms_lob.getlength(l_body_html) loop
utl_smtp.write_data(l_connection,
dbms_lob.substr(l_body_html,l_ammount,l_offset));
l_offset := l_offset + l_ammount ;
l_ammount := least(1900,dbms_lob.getlength(l_body_html) - l_ammount);
end loop;
--The following crlf is necessary after the body is written
utl_smtp.write_data(l_connection, crlf);
----------------------------------------------------
-- Write the attachments of the message
-- Loop through all the selected primary keys in l_attachment_pkeys
While l_attachment_pkeys is null
Loop
For i IN l_attachment_pkeys.FIRST .. l_attachment_pkeys.LAST
Loop
-- Determine the attachment variables for each instance of attachments
Select mime_type into l_attach_mime
from mail_attachment where prim_key = l_attachment_pkeys(i);
Select file_name into l_attach_name
from mail_attachment where prim_key = l_attachment_pkeys(i);
Select attachment into l_attach_blob
from mail_attachment where prim_key = l_attachment_pkeys(i);
v_length := dbms_lob.getlength(l_attach_blob);
-- Write out the boundary
UTL_SMTP.write_data(l_connection, '--' || l_boundary || crlf);
-- Write out the attachment metadata
UTL_SMTP.write_data(l_connection, 'Content-Type: ' || l_attach_mime ||
'; name=' || chr(34) || l_attach_name || chr(34) || crlf);
UTL_SMTP.write_data(l_connection, 'Content-Transfer-Encoding: base64' ||
crlf);
UTL_SMTP.write_data(l_connection, 'Content-Disposition: attachment;
filename="' || l_attach_name || '"' || crlf || crlf);
--Write out the attachment blob in portions of l_step length
FOR k IN 0 .. TRUNC((DBMS_LOB.getlength(l_attach_blob) - 1 )/l_step)
LOOP
UTL_SMTP.write_data(l_connection, UTL_RAW.cast_to_varchar2
(UTL_ENCODE.base64_encode(DBMS_LOB.substr(l_attach_blob,
l_step, k * l_step + 1))));
END LOOP;
UTL_SMTP.write_data(l_connection, crlf);
End Loop;
End Loop;
----------------------------------------------------
-- Write the final html boundary
utl_smtp.write_data(l_connection,
crlf || '--' || l_boundary || '--' || crlf);
----------------------------------------------------
-- Close the connection and end
utl_smtp.close_data(l_connection);
utl_smtp.quit( l_connection );
dbms_lob.freetemporary(l_body_html);
end;
A sample "p_html" field looks like this:
<p>
Text right before the image.</p>
<p>
<img alt="HarryPotter" src="data:image/jpeg;base64,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" /></p>
<p>
Text right after the image.</p>
the following code works for me:
DECLARE
conn utl_smtp.connection;
BOUNDARY VARCHAR2 (256) := '-----090303020209010600070908';
i pls_integer;
len pls_integer;
buff_size pls_integer := 57;
l_raw raw(57);
p_image blob;
MailServer VARCHAR2(50) := 'xxxxxx.xxxxx.xxxxxxx.xxxxx';
l_message VARCHAR2(32767) :='<html>
<body>
<img src="cid:banner" alt="banner"/>
<br>
Test HTML with Embedded Image-chk latest
<p>And here it is:</p>
<p>The end.</p>
</body>
</html>
';
begin
SELECT PIC
INTO p_image
FROM TEMP_MAIL_PIC_BLOB
WHERE PIC_ID = 1;
conn := utl_smtp.open_connection(MailServer, 25);
UTL_SMTP.helo (conn, MailServer);
UTL_SMTP.mail (conn, 'from#abc.com');
UTL_SMTP.rcpt (conn, 'to#abc.com');
UTL_SMTP.open_data (conn);
UTL_SMTP.write_data (conn, 'From' || ': ' || 'from#test.com'|| UTL_TCP.CRLF);
UTL_SMTP.write_data (conn, 'To' || ': ' || 'to#test.com'|| UTL_TCP.CRLF);
UTL_SMTP.write_data (conn, 'MIME-Version: 1.0' || UTL_TCP.CRLF);
UTL_SMTP.write_data (conn, 'Subject: image inline testing' || UTL_TCP.CRLF) ;
UTL_SMTP.write_data (conn, 'Content-Type: multipart/mixed; boundary="' || BOUNDARY || '"' || UTL_TCP.CRLF);
UTL_SMTP.write_data (conn, UTL_TCP.CRLF);
UTL_SMTP.write_data (conn, '--' || BOUNDARY || UTL_TCP.CRLF );
UTL_SMTP.write_data (conn, 'Content-Type: text/html; charset=US-ASCII'|| UTL_TCP.CRLF );
UTL_SMTP.write_data (conn, UTL_TCP.CRLF);
UTL_SMTP.write_data (conn, l_message);
UTL_SMTP.write_data (conn, UTL_TCP.CRLF);
UTL_SMTP.write_data (conn, '--' || BOUNDARY || UTL_TCP.CRLF );
UTL_SMTP.write_data (conn, 'Content-Type: image/jpg;'|| UTL_TCP.CRLF );
UTL_SMTP.write_data (conn, 'Content-Disposition: inline; filename="banner.jpg"' || UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA (conn, 'Content-ID: <banner> ' || UTL_TCP.CRLF);
UTL_SMTP.write_data (conn, 'Content-Transfer-Encoding' || ': ' || 'base64' || UTL_TCP.CRLF);
UTL_SMTP.write_data (conn, UTL_TCP.CRLF);
i := 1;
len := dbms_lob.getlength(p_image);
while i < len
loop
dbms_lob.read(p_image, buff_size, i, l_raw);
utl_smtp.write_raw_data(conn, utl_encode.base64_encode(l_raw));
utl_smtp.write_data(conn, utl_tcp.crlf);
i := i + buff_size;
end loop;
utl_smtp.write_data(conn, utl_tcp.crlf);
UTL_SMTP.write_data (conn, '--' || BOUNDARY || '--' || UTL_TCP.CRLF);
UTL_SMTP.write_data (conn, UTL_TCP.CRLF);
UTL_SMTP.close_data (conn);
UTL_SMTP.quit (conn);
end;
Regards
Giova
I have a problem, I am creating an CLOB variable with the contents of a query in oracle to email to users, the problem is that it does email as .csv but with no contents. I can not find the problems:
CREATE OR REPLACE PROCEDURE trackekr(cursor1 IN OUT SYS_REFCURSOR)
AS
v_connection UTL_SMTP.connection;
v_clob CLOB := EMPTY_CLOB();
v_len INTEGER;
v_index INTEGER;
c_mime_boundary CONSTANT VARCHAR2(256) := 'the boundary can be almost anything';
rec NUMBER(10, 0) := 0;
d_id NUMBER(10, 0) := 0;
customer VARCHAR2(20);
wife VARCHAR2(20);
date_rec DATE;
special_h VARCHAR2(20);
g_amount NUMBER(10, 0) := 0;
credit_amount NUMBER(10, 0) := 0;
a_number VARCHAR2(20);
a__name VARCHAR2(20);
BEGIN
OPEN cursor1 FOR
SELECT rec,
d_id,
customer,
wife,
date_rec,
special h,
g_amount
FROM (your query here);
WHILE cursor1%NOTFOUND
LOOP
FETCH cursor1
INTO rec,
d_id,
customer,
wife,
date_rec,
special_h,
g_amount,
credit_amount,
a_number,
a__name;
v_clob :=
v_clob
|| rec
|| ','
|| d_id
|| ','
|| customer
|| ','
|| wife
|| ','
|| date_rec
|| ','
|| special_h
|| ','
|| g_amount
|| ','
|| credit_amount
|| ','
|| a_number
|| ','
|| a__name
|| UTL_TCP.crlf;
END LOOP;
-- UTL
v_connection := UTL_SMTP.open_connection(mailhost, 25);
SMTP server name or ip address
UTL_SMTP.helo(v_connection, mail.exchange.mydomain.com);
UTL_SMTP.mail(v_connection, 'mylogin.Exchange.mydomain.com');
UTL_SMTP.rcpt(v_connection, 'mylogin.Exchange.mydomain.com');
UTL_SMTP.open_data(v_connection);
UTL_SMTP.write_data(v_connection, 'From: ' || 'mylogin.Exchange.mydomain.com' || UTL_TCP.crlf);
UTL_SMTP.write_data(v_connection, 'To: ' || 'mylogin.Exchange.mydomain.com' || UTL_TCP.crlf);
UTL_SMTP.write_data(v_connection, 'Subject: test subject' || UTL_TCP.crlf);
UTL_SMTP.write_data(v_connection, 'MIME-Version: 1.0' || UTL_TCP.crlf);
UTL_SMTP.write_data(
v_connection,
'Content-Type: multipart/mixed; boundary="' || c_mime_boundary || '"' || UTL_TCP.crlf
);
UTL_SMTP.write_data(v_connection, UTL_TCP.crlf);
UTL_SMTP.write_data(
v_connection,
'This is a multi-part message in MIME format.' || UTL_TCP.crlf
);
UTL_SMTP.write_data(v_connection, '--' || c_mime_boundary || UTL_TCP.crlf);
UTL_SMTP.write_data(v_connection, 'Content-Type: text/plain' || UTL_TCP.crlf);
-- Set up attachment header
UTL_SMTP.write_data(
v_connection,
'Content-Disposition: attachment; filename="' || 'FIRSTFILE.csv' || '"' || UTL_TCP.crlf
);
UTL_SMTP.write_data(v_connection, UTL_TCP.crlf);
-- Write attachment contents
v_len := DBMS_LOB.getlength(v_clob);
v_index := 1;
WHILE v_index <= v_len
LOOP
UTL_SMTP.write_data(v_connection, DBMS_LOB.SUBSTR(v_clob, 32000, v_index));
v_index := v_index + 32000;
END LOOP;
-- End attachment
UTL_SMTP.write_data(v_connection, UTL_TCP.crlf);
UTL_SMTP.write_data(v_connection, '--' || c_mime_boundary || '--' || UTL_TCP.crlf);
UTL_SMTP.close_data(v_connection);
UTL_SMTP.quit(v_connection);
END;
As I said, it emails a .csv file but empty.
Note this part in your code:
WHILE cursor1%NOTFOUND
Your loop will never be executed for non-empty dataset. Use this instead:
WHILE cursor1%FOUND
Or even better use implicit cursor:
FOR cursor1 in
(SELECT rec,
d_id,
customer,
wife,
date_rec,
special_h,
g_amount,
credit_amount,
a_number,
a__name
FROM (your query here))
LOOP
v_clob :=
v_clob
|| cursor1.rec
|| ','
|| cursor1.d_id
|| ','
|| cursor1.customer
|| ','
|| cursor1.wife
|| ','
|| cursor1.date_rec
|| ','
|| cursor1.special_h
|| ','
|| cursor1.g_amount
|| ','
|| cursor1.credit_amount
|| ','
|| cursor1.a_number
|| ','
|| cursor1.a__name
|| UTL_TCP.crlf;
END LOOP;
The example below, write the query to clob and then to blob to put in a file
You just need to use the first step, until the line 87
SELECT dbms_lob.getlength(l_clob) INTO len FROM dual;
DECLARE
l_output utl_file.file_type;
c1 INTEGER DEFAULT dbms_sql.open_cursor;
l_columnvalue VARCHAR2(4000);
l_status INTEGER;
l_colcnt NUMBER := 0;
l_separator VARCHAR2(30);
l_desctbl dbms_sql.desc_tab;
l_flag NUMBER;
l_dir VARCHAR2(50);
l_arq VARCHAR2(100);
l_clob CLOB;
l_query VARCHAR2(50);
vstart NUMBER := 1;
bytelen NUMBER := 32000;
len NUMBER;
my_vr RAW(32000);
x NUMBER;
dest_offset INTEGER;
src_offset INTEGER;
blob_csid NUMBER;
lang_context INTEGER;
blb BLOB;
warning INTEGER;
BEGIN
l_query := 'select * from safx07_v where rownum <=100';
SELECT 'safx07' || to_char(SYSDATE, 'DDMMYY_HH24MISS') || '.txt'
INTO l_arq
FROM dual;
l_dir := 'ORACLE_EXP';
l_output := utl_file.fopen(l_dir, l_arq, 'wb');
--l_output := utl_file.fopen('ORACLE_EXP', 'filename.txt', 'wb', 32760);
--l_separator := separator;
IF l_separator = '' OR l_separator IS NULL THEN
l_separator := chr(9);
END IF;
dbms_sql.parse(c1, l_query, dbms_sql.native);
dbms_sql.describe_columns(c1, l_colcnt, l_desctbl);
dbms_lob.createtemporary(l_clob, TRUE,DBMS_LOB.call);
/*
FOR cr IN (l_query) LOOP
dbms_lob.writeappend(l_clob, length(cr.txt), cr.txt);
END LOOP;*/
FOR i IN 1 .. l_colcnt LOOP
dbms_output.put_line(l_desctbl(i).col_name || l_separator);
dbms_output.put_line(length(l_desctbl(i).col_name || l_separator));
/* utl_file.put(l_output, l_desctbl(i).col_name || l_separator);
dbms_sql.define_column(c1, i, l_columnvalue, 4000);*/
dbms_lob.writeappend(l_clob,
length(l_desctbl(i).col_name || l_separator),
l_desctbl(i).col_name || l_separator);
dbms_sql.define_column(c1, i, l_columnvalue, 4000);
END LOOP;
--utl_file.new_line(l_output);
l_status := dbms_sql.execute(c1);
dbms_lob.writeappend(l_clob, length(chr(10)), chr(10));
WHILE (dbms_sql.fetch_rows(c1) > 0) LOOP
FOR i IN 1 .. l_colcnt LOOP
/* dbms_sql.column_value(c1, i, l_columnvalue);
utl_file.put(l_output, l_columnvalue || l_separator);*/
dbms_sql.column_value(c1, i, l_columnvalue);
dbms_lob.writeappend(l_clob, length(l_columnvalue || l_separator),
l_columnvalue || l_separator);
END LOOP;
dbms_lob.writeappend(l_clob, length(chr(10)), chr(10));
END LOOP;
--utl_file.fclose(l_output);
SELECT dbms_lob.getlength(l_clob) INTO len FROM dual;
dbms_lob.createtemporary(blb, FALSE);
dest_offset := 1;
src_offset := 1;
lang_context := 0;
-- convert to a BLOB here:
dbms_lob.converttoblob(blb, l_clob, dbms_lob.getlength(l_clob),
dest_offset, src_offset, 0, lang_context, warning);
-- if small enough for a single write
IF len < 32760 THEN
utl_file.put_raw(l_output, blb);
utl_file.fflush(l_output);
ELSE
-- write in pieces
vstart := 1;
WHILE vstart < len AND bytelen > 0 LOOP
dbms_lob.read(blb, bytelen, vstart, my_vr);
utl_file.put_raw(l_output, my_vr);
utl_file.fflush(l_output);
-- set the start position for the next cut
vstart := vstart + bytelen;
-- set the end position if less than 32000 bytes
x := x - bytelen;
IF x < 32000 THEN
bytelen := x;
END IF;
END LOOP;
END IF;
dbms_sql.close_cursor(c1);
utl_file.fclose(l_output);
EXCEPTION
WHEN OTHERS THEN
dbms_sql.close_cursor(c1);
utl_file.fclose(l_output);
RAISE;
END;