Reputation: 2520
Could anybody help me to correct code to send mail with attachment. As result I should send a mail with small table (prepared using html and css) in letter body and .csv as an attachment. The procedure works fine only with message body, but it does not want to send attachment =( :
CREATE OR REPLACE PROCEDURE test_send_mail(
p_sender IN VARCHAR2,
p_recipient IN VARCHAR2,
p_subject IN VARCHAR2,
p_message IN CLOB – table in html)
as
l_mailhost VARCHAR2(255) := 'localhost';
l_mail_conn utl_smtp.connection;
v_add_src VARCHAR2(4000);
v_addr VARCHAR2(4000);
slen number := 1;
crlf VARCHAR2(2) := chr(13)||chr(10);
i NUMBER(12);
len NUMBER (12);
part NUMBER(12) := 16384;
-- css for table in letter body
l_stylesheet CLOB := '
<html><head>
<style type="text/css">
body { font-family : Verdana, Arial;
font-size : 10pt;}
.green { color : #00AA00;
font-weight : bold;}
.red { color : #FF0000;
font-weight : bold;}
pre { margin-left : 10px;}
table { empty-cells : show;
border-collapse : collapse;
width : 100%;
border : solid 2px #444444;}
td { border : solid 1px #444444;
font-size : 12pt;
padding : 2px;}
th { background : #EEEEEE;
border : solid 1px #444444;
font-size : 12pt;
padding : 2px;}
dt { font-weight : bold; }
</style>
</head>
<body>';
-- variables for attachment
/*Table header in attachment*/
lv_mycolumns VARCHAR2(32000):= 'A1'||chr(9)||'A2'||chr(9)||'A3'||chr(13)||chr(10);
lv_message VARCHAR2(32000);
CURSOR cur_query
IS
SELECT 'help' as A1, 'me' as A3, 'please' as A3
from DUAL; -- I would like to see this table in the attachment
attached_file_name VARCHAR2(50):= 'REPORT_';
ddate VARCHAR2(16):= TO_CHAR (SYSDATE, 'YYYYMMDDHH24MISS');
filetype varchar(10):= '.xls'; -- really csv
BEGIN
l_mail_conn := utl_smtp.open_connection(l_mailhost, 25);
utl_smtp.helo(l_mail_conn, l_mailhost);
utl_smtp.mail(l_mail_conn, p_sender);
if(instr(p_recipient,';') = 0) then
utl_smtp.rcpt(l_mail_conn, p_recipient);
else
v_add_src := p_recipient || ';';
while(instr(v_add_src,';',slen) > 0) loop
v_addr := substr(v_add_src, slen, instr(substr(v_add_src, slen),';')-1);
slen := slen+instr(substr(v_add_src, slen),';');
Dbms_Output.put_line('rcpt ' || v_addr);
utl_smtp.rcpt(l_mail_conn, v_addr);
end loop;
end if;
utl_smtp.open_data(l_mail_conn );
utl_smtp.write_data(l_mail_conn,
'MIME-version: 1.0' || crlf ||
'Content-Type: text/html; charset=ISO-8859-15' || crlf ||
'Content-Transfer-Encoding: 8bit' || crlf ||
'Date: ' || to_char(sysdate, 'Dy, DD Mon YYYY hh24:mi:ss') || crlf ||
'From: ' || p_sender || crlf ||
'Subject: '|| p_subject || crlf ||
'To: ' || p_recipient || crlf);
utl_smtp.write_raw_data(l_mail_conn, utl_raw.cast_to_raw(l_stylesheet));
i := 1;
len := DBMS_LOB.getLength(p_message);
WHILE (i < len) LOOP
utl_smtp.write_raw_data(l_mail_conn, utl_raw.cast_to_raw(DBMS_LOB.SubStr(p_message,part, i)));
i := i + part;
END LOOP;
utl_smtp.write_raw_data(l_mail_conn, utl_raw.cast_to_raw('</body></html>'));
-- begin the attachment. This part I need to correct. How?
FOR rec IN cur_query
LOOP
lv_message := rec.A1||chr(9)||rec.A2||chr(9)||rec.A3||chr(13)||chr(10);
END LOOP;
-- end connectin
utl_smtp.close_data(l_mail_conn );
utl_smtp.quit(l_mail_conn);
end;
Thank you in advance.
Upvotes: 0
Views: 9792
Reputation: 21973
you are not setting the correct content type, nor are you defining boundaries correctly (read up on Content-Type: multipart/mixed).
eg (also remember, if you want to attach binary, you have to base64 encode it):
the boundary "---YOURBOUNDARY" should not occur in the email body at all , so make sure you pick something that would never appear :)
utl_smtp.open_data(l_mail_conn );
utl_smtp.write_data(l_mail_conn,
'MIME-version: 1.0' || crlf ||
'Date: ' || to_char(sysdate, 'Dy, DD Mon YYYY hh24:mi:ss') || crlf ||
'From: ' || p_sender || crlf ||
'Subject: '|| p_subject || crlf ||
'To: ' || p_recipient || crlf ||
'Content-Type: multipart/mixed;' || crlf ||
' boundary="---YOURBOUNDARY"' || crlf ||crlf);
utl_smtp.write_data(l_mail_conn, '-----YOURBOUNDARY'||crlf);
utl_smtp.write_data(l_mail_conn, 'Content-Type: text/html' || crlf);
utl_smtp.write_data(l_mail_conn, 'Content-Transfer-Encoding: 8bit' || crlf || crlf);
utl_smtp.write_raw_data(l_mail_conn, utl_raw.cast_to_raw(l_stylesheet));
i := 1;
len := DBMS_LOB.getLength(p_message);
WHILE (i < len) LOOP
utl_smtp.write_raw_data(l_mail_conn, utl_raw.cast_to_raw(DBMS_LOB.SubStr(p_message,part, i)));
i := i + part;
END LOOP;
utl_smtp.write_raw_data(l_mail_conn, utl_raw.cast_to_raw('</body></html>'));
utl_smtp.write_data(l_mail_conn, crlf || crlf);
-- begin the attachment. This part I need to correct. How?
utl_smtp.write_data(l_mail_conn, '-----YOURBOUNDARY'||crlf);
utl_smtp.write_data(l_mail_conn, 'Content-Type: text/plain;'||crlf);
utl_smtp.write_data(l_mail_conn, 'Content-Transfer-Encoding: 8bit' || crlf);
utl_smtp.write_data(l_mail_conn,'Content-Disposition: attachment;'|| crlf);
utl_smtp.write_data(l_mail_conn, ' filename="attach.txt"'|| crlf|| crlf);
FOR rec IN cur_query
LOOP
utl_smtp.write_data(l_mail_conn, rec.A1||chr(9)||rec.A2||chr(9)||rec.A3||crlf);
END LOOP;
utl_smtp.write_data(l_mail_conn, crlf||'-----YOURBOUNDARY--');
-- end connectin
utl_smtp.close_data(l_mail_conn );
utl_smtp.quit(l_mail_conn);
ie the body output with my code sample would be like:
-----YOURBOUNDARY
Content-Type: text/html
<html><head>
<style type="text/css">
body { font-family : Verdana, Arial;
font-size : 10pt;}
.green { color : #00AA00;
font-weight : bold;}
.red { color : #FF0000;
font-weight : bold;}
pre { margin-left : 10px;}
table { empty-cells : show;
border-collapse : collapse;
width : 100%;
border : solid 2px #444444;}
td { border : solid 1px #444444;
font-size : 12pt;
padding : 2px;}
th { background : #EEEEEE;
border : solid 1px #444444;
font-size : 12pt;
padding : 2px;}
dt { font-weight : bold; }
</style>
</head>
<body>test123</body></html>
-----YOURBOUNDARY
Content-Type: text/plain;
Content-Disposition: attachment;
filename="attach.txt"
help me please
-----YOURBOUNDARY--
Upvotes: 1