This is example of procedure that I'm using to send mail
BEGIN
l_mail_conn := UTL_SMTP.OPEN_CONNECTION(c_mailhost, c_port);
UTL_SMTP.HELO(l_mail_conn, c_mailhost);
UTL_SMTP.MAIL(l_mail_conn, p_sender);
UTL_SMTP.RCPT(l_mail_conn, p_recipient);
--Create HEADER
l_head := 'MIME-Version: 1.0' || UTL_TCP.crlf
|| 'To: ' || p_recipient || UTL_TCP.crlf
|| 'From: ' || p_sender || UTL_TCP.crlf
|| 'Subject: ' || p_subject || UTL_TCP.crlf
|| 'Content-Type: multipart/mixed; boundary="' || g_mime_bound || '"' || UTL_TCP.crlf
--|| UTL_TCP.crlf
|| 'This is a multi-part message in MIME format.' || UTL_TCP.crlf
|| '--' || g_mime_bound || UTL_TCP.crlf
|| 'Content-Type: ' || p_type || UTL_TCP.crlf || UTL_TCP.crlf
--|| 'Content-Transfer-Encoding: quoted-printable ' || UTL_TCP.crlf || UTL_TCP.crlf
;
--DBMS_OUTPUT.PUT_LINE(l_head);
--Write HEADER
DBMS_LOB.CREATETEMPORARY(l_body, false, 10);
DBMS_LOB.WRITE(l_body, LENGTH(l_head), 1, l_head);
--DBMS_OUTPUT.PUT_LINE(l_body);
--Write BODY
l_offset := DBMS_LOB.GETLENGTH(l_body) + 1;
DBMS_LOB.WRITE(l_body, LENGTH(p_data), l_offset, p_data);
--DBMS_OUTPUT.PUT_LINE(l_body);
l_offset := 1;
UTL_SMTP.OPEN_DATA(l_mail_conn);
WHILE l_offset < DBMS_LOB.GETLENGTH(l_body)
LOOP
UTL_SMTP.WRITE_RAW_DATA(l_mail_conn, UTL_RAW.CAST_TO_RAW(DBMS_LOB.SUBSTR(l_body, l_ammount, l_offset)));
l_offset := l_offset + l_ammount;
l_ammount := LEAST(1900, DBMS_LOB.GETLENGTH(l_body) - l_ammount);
END LOOP;
--Clear DATA
UTL_SMTP.CLOSE_DATA(l_mail_conn);
UTL_SMTP.QUIT(l_mail_conn);
DBMS_LOB.FREETEMPORARY(l_body);
END;
And it works as intended, problem is with closing connections. My best guess is that if procedure breaks somewhere between opening connection and closing it, connection stays open. When that happens enough times, I get
ERROR: ORA-30678: too many open connections
ORA-06512: at "SYS.UTL_TCP", line 17
ORA-06512: at "SYS.UTL_TCP", line 267
ORA-06512: at "SYS.UTL_SMTP", line 161
ORA-06512: at "SYS.UTL_SMTP", line 197
So I've decided to add closing connection to my EXCEPTION block. But while I was testing, I realized that I can't run UTL_SMTP.QUIT(l_mail_conn) if connection is not open, if I try it I get
ORA-29278: SMTP transient error: 421 Service not available
ORA-06512: at "SYS.UTL_SMTP", line 54
ORA-06512: at "SYS.UTL_SMTP", line 138
ORA-06512: at "SYS.UTL_SMTP", line 699
So then I found out there is function called NOOP I can use to determine if connection is open or not, so I tried that one, and it works some times, if I call it before connection is open, I get
421
Service not available
And if I call it after connection is open, I get
250
Ok
But if I try to call it after while loop or inside it (before data is closed), procedure breaks again with following error
ORA-29277: invalid SMTP operation
ORA-06512: at "SYS.UTL_SMTP", line 80
ORA-06512: at "SYS.UTL_SMTP", line 210
ORA-06512: at "SYS.UTL_SMTP", line 677
As a temporary fix, I simply added utl_tcp.close_all_connections; in my exception block, but it's not something I would like to do (cause it could potentially break other procedured using UTL_SMTP at the same time)
So I just need a way to make sure connection is closed no matter what happens. Does anyone knows how it should be done?
Thanks
Related
I have a procedure that reads value from the table and generate a csv file and mail them . The procedure was working fine until I entered new entries in DB and it fails to generate CSV file after that. The procedure is throwing an exception " ORA-06502: PL/SQL: numeric or value error: character string buff" and I have tried to print the value that is read from table to check if it was working properly .
By printing the values I could see that one of the new entry is not being read properly and I believe this could be the reason for the issue .
I have checked for the reason why the values after O Brien being printed in new line and I could see that that value sits in the table like this with cursor on new line :
Error that got printed in log :
Error raised: ORA-06512: at "UPDATER.mypro", line 50
ORA-06502: PL/SQL: numeric or value error: character string buffer too small
Here is my code :
create or replace PROCEDURE mypro AS
O_ErrorCode Number;
O_ErrorDesc VARCHAR2(100);
l_clob2 VARCHAR2 (32767);
l_attach_text2 VARCHAR2 (32767);
l_attach_text_h2 VARCHAR2 (32767);
v_From VARCHAR2(280) := ' abc';
v_Recipient VARCHAR2(280) := 'efggg';
v_Subject VARCHAR2(280) := 'Entry & Details';
v_Mail_Host VARCHAR2(230) := 'abcd';
v_Mail_Conn utl_smtp.Connection;
crlf VARCHAR2(200) := chr(13)||chr(10);
FC_SV_STATUS_DESC VARCHAR2(100) := 'open';
CURSOR c2 IS
select FC_CA_RECORD_ID,to_char(FC_CA_INPUT_DATE ,'DD-MM-YY')as FC_CA_INPUT_DATE,FC_CA_PAYER,FC_CA_AMOUNT,FC_CA_TYPE,FC_CA_PAYEE,FC_CA_ADD_REMARKS,FC_CA_COMMENTS,FC_CA_ACC_NO,FC_CA_POLICY_NO,to_char(FC_CA_BRANCHCONF_DATE ,'DD-MM-YY')as FC_CA_BRANCHCONF_DATE,FC_CA_CONFIRMED_BY,to_char(FC_CA_SHEETUPDATE_DATE ,'DD-MM-YY')as FC_CA_SHEETUPDATE_DATE,to_char(FC_CA_MAILUPDATE_DATE ,'DD-MM-YY')as FC_CA_MAILUPDATE_DATE,to_char(FC_CA_UPLOAD_TIME ,'DD-MM-YY')as FC_CA_UPLOAD_TIME,FC_CA_UPLOAD_ID FROM Abcd where FC_CA_STATUS =1 ;
BEGIN
l_attach_text_h2 :=
'ID ,INPUT DATE ,PAYER ,AMOUNT ,TYPE ,PAYEE - SORT CODE & BANK ACCOUNT NO ,ADDITIONAL REMARKS ,COMMENTS ,ACCOUNT NUMBER ,POLICY NUMBER ,DATE OF BRANCH CONFIRMATION ,CONFIRMED BY ,SHEETUPDATE DATE ,MAILUPDATE DATE ,DATE-TIME ,USER ID ,STATUS ';
FOR employee_rec2 in c2
LOOP
l_attach_text2 := '"' ||
employee_rec2.FC_CA_RECORD_ID || '","' ||
employee_rec2.FC_CA_INPUT_DATE || '","' ||
employee_rec2.FC_CA_PAYER || '","' ||
employee_rec2.FC_CA_AMOUNT || '","' ||
employee_rec2.FC_CA_TYPE || '","' ||
employee_rec2.FC_CA_PAYEE || '","' ||
employee_rec2.FC_CA_ADD_REMARKS || '","' ||
employee_rec2.FC_CA_COMMENTS || '","' ||
employee_rec2.FC_CA_ACC_NO || '","' ||
employee_rec2.FC_CA_POLICY_NO || '","' ||
employee_rec2.FC_CA_BRANCHCONF_DATE || '","' ||
employee_rec2.FC_CA_CONFIRMED_BY || '","' ||
employee_rec2.FC_CA_SHEETUPDATE_DATE || '","' ||
employee_rec2.FC_CA_MAILUPDATE_DATE || '","' ||
employee_rec2.FC_CA_UPLOAD_TIME || '","' ||
employee_rec2.FC_CA_UPLOAD_ID || '","' ||
FC_SV_STATUS_DESC || '"' ||chr(13);
l_clob2 := l_clob2||chr(10)||l_attach_text2;
END LOOP;
l_clob2 := l_attach_text_h2 ||chr(13)|| l_clob2;
DBMS_OUTPUT.put_line(' entries processing completed...');
v_Mail_Conn := utl_smtp.Open_Connection(v_Mail_Host, 25);
utl_smtp.Helo(v_Mail_Conn, v_Mail_Host);
utl_smtp.Mail(v_Mail_Conn, v_From);
utl_smtp.Rcpt(v_Mail_Conn, v_Recipient);
utl_smtp.Data(v_Mail_Conn,
'Date: ' || to_char(sysdate, 'Dy, DD Mon YYYY hh24:mi:ss') || crlf ||
'From: ' || v_From || crlf ||
'Subject: '|| v_Subject || crlf ||
'To: ' || v_Recipient || crlf ||
'MIME-Version: 1.0'|| crlf || -- Use MIME mail standard
'Content-Type: multipart/mixed;'|| crlf ||
' boundary="-----SECBOUND"'|| crlf ||
crlf ||
'-------SECBOUND'|| crlf ||
'Content-Type: text/plain;'|| crlf ||
'Content-Transfer_Encoding: 7bit'|| crlf ||
crlf ||
'Please find the following in the attachments :'|| crlf || -- Message body
'Entry details'|| crlf ||
crlf ||
'-------SECBOUND'|| crlf ||
'Content-Type: text/plain;'|| crlf ||
' name="myfile.csv"'|| crlf ||
'Content-Transfer_Encoding: 8bit'|| crlf ||
'Content-Disposition: attachment;'|| crlf ||
' filename="myfile.csv"'|| crlf ||
crlf ||
l_clob2 || crlf || -- Content of attachment
crlf ||
'-------SECBOUND--' -- End MIME mail
);
utl_smtp.Quit(v_mail_conn);
DBMS_OUTPUT.put_line('mail send completed...');
EXCEPTION
WHEN OTHERS THEN
O_ErrorCode := SQLCODE;
O_ErrorDesc := SUBSTR(SQLERRM, 1, 64);
DBMS_OUTPUT.put_line(O_ErrorCode);
DBMS_OUTPUT.put_line(O_ErrorDesc);
SYSTEM.intranet_utils.intranet_log_errors
(
'Exception',
SYSTEM.intranet_utils.intranet_get_errmsg
);
dba_utils.dba_log_batch ( 'Complete', 'Erred');
system.intranet_utils.INTRANET_LOG_ERRORS('procedure mypro',
system.intranet_utils.INTRANET_GET_ERRMSG, 'Error in mypro');
END mypro;
Can anyone tell me how can I fix this issue in my code and how can properly print the errors in logs ??
The reason it worked before but stopped working is most probably that you reached the buffer value for dbms_output. The default buffer size is 20000 (check docs) and when that is exceeded the error ORU-10027 is thrown. I suggest you remove those calls - for this reason no production code should have calls to dbms_output.
the second parameter on procedure "data" in package "utl_smtp" is of type VARCHAR2 so the limit is 32767 bytes.
for large data you must use
open_data
write_data
close_data
read documentation
I have an ORDS POST API where the front end developer will send 2 pdf files in multipart/form-data. I then have to send email with two pdf attachments using UTL_SMTP. I am on Oracle 12.1
I have the below utl smtp proc which can attach blobs in email from a table and it works fine by calling multiple times.But, I am not able to make it work when I have to read the files coming from multipart/form-data in POST API.
How should I read the form-data files?
....
...
PROCEDURE multiple_attachment( p_conn IN OUT utl_smtp.connection
,p_boundary IN VARCHAR2
,p_FileName IN VARCHAR2
,p_FileData IN BLOB)
AS
l_len integer := 0 ;
l_idx integer := 1 ;
l_buff_size integer := 57 ;
l_raw raw(57) ;
BEGIN
-- Attachment
utl_smtp.write_data( p_conn, '--' || p_boundary || utl_tcp.crlf );
utl_smtp.write_data( p_conn, 'Content-Type: application/pdf' || utl_tcp.crlf );
utl_smtp.write_data( p_conn, 'Content-Disposition: attachment; ' || utl_tcp.crlf );
utl_smtp.write_data( p_conn, ' filename="' || p_FileName || '"' || utl_tcp.crlf );
utl_smtp.write_data( p_conn, 'Content-Transfer-Encoding: base64' || utl_tcp.crlf );
utl_smtp.write_data( p_conn, utl_tcp.crlf );
l_len := dbms_lob.getlength(p_FileData);
l_buff_size := 57 ;
l_idx := 1;
WHILE l_idx < l_len LOOP
dbms_lob.read( p_FileData , l_buff_size, l_idx, l_raw );
utl_smtp.write_raw_data( p_conn, utl_encode.base64_encode(l_raw) );
utl_smtp.write_data( p_conn, utl_tcp.crlf );
l_idx := l_idx + l_buff_size;
END LOOP;
END;
UTL_SMTP.write_data(l_mail_conn, '--' || l_boundary || '--' || UTL_TCP.crlf);
UTL_SMTP.close_data(l_mail_conn);
....
...
I am getting service not available message when I am sending mail with large size attachment.
The requirement is to write a procedure which will extract the data of the whole table and send the extract as excel attachment in mail. table_name and email id will be passed as a parameter.
I tried with the CLOB. fetched the data from the table and put it into a CLOB as an XML structure. Then I am sending the mail with attachment as xls with the data present in CLOB.
For a lesser number of records(max around 2k) is working fine. But when I am checking for more number of records, the program is throwing an error of UTL_SMTP transient error - Service not available.
Following is the part of code where I am utilising UTL_SMTP.
BEGIN
vsql := 'SELECT * from test_table';
V_CLOB := get_query_output(vsql);
v_lob := v_clob;
v_connection := UTL_SMTP.open_connection('abcd.efgh.com');
UTL_SMTP.helo(v_connection, 'abcd.efgh.com');
UTL_SMTP.mail(v_connection, p_from);
UTL_SMTP.rcpt(v_connection, p_to);
UTL_SMTP.open_data(v_connection);
UTL_SMTP.write_data(v_connection, 'From: ' || p_from || UTL_TCP.crlf);
UTL_SMTP.WRITE_DATA(V_CONNECTION, 'To: ' || P_TO || UTL_TCP.CRLF);
utl_smtp.write_data(v_connection, 'Cc: ' || p_cc || utl_tcp.crlf);
UTL_SMTP.write_data(v_connection,
'Subject: NPI Error Report' || UTL_TCP.crlf);
UTL_SMTP.write_data(v_connection, 'MIME-Version: 1.0' || UTL_TCP.crlf);
DBMS_OUTPUT.PUT_LINE('at position 4');
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="' ||
'Error_Report.xls' || '"' || UTL_TCP.crlf);
UTL_SMTP.write_data(v_connection, UTL_TCP.crlf);
-- start attachment
V_LEN := DBMS_LOB.GETLENGTH(V_CLOB);
DBMS_OUTPUT.PUT_LINE('V_LEN :=' || V_LEN);
for I in 0 .. TRUNC((V_LEN - 1) / V_INDEX) LOOP
UTL_SMTP.WRITE_DATA(v_connection,
DBMS_LOB.SUBSTR(V_LOB, V_INDEX, I * V_INDEX + 1));
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);
EXCEPTION WHEN OTHERS THEN
BEGIN
UTL_SMTP.QUIT(v_connection);
raise;
END;
END;
Error Codes which I am getting when there are huge records(almost >2k) in the table:
enter image description here
Error report -
ORA-29277: invalid SMTP operation
ORA-06512: at "SYS.UTL_SMTP", line 82
ORA-06512: at "SYS.UTL_SMTP", line 212
ORA-06512: at "SYS.UTL_SMTP", line 622
ORA-06512: at "SYS.UTL_SMTP", line 633
ORA-06512: at line 328
ORA-29278: SMTP transient error: 421 Service not available
29277. 00000 - "invalid SMTP operation"
*Cause: The SMTP operation was invalid at the current stage of the SMTP
transaction.
*Action: Retry the SMTP operation at the appropriate stage of the SMTP
transaction.
The error is strange, usually this is not related to size of attached file.
Maybe your attachment causes problems with special characters, try to send the mail like this:
ClobLen PLS_INTEGER;
amount BINARY_INTEGER := 8192;
buffer VARCHAR2(16384);
offset PLS_INTEGER := 1;
BEGIN
....
UTL_SMTP.write_data(con, Utl_Tcp.CRLF);
UTL_SMTP.write_data(con, '--'||C_MIME_BOUNDARY || Utl_Tcp.CRLF);
UTL_SMTP.write_data(con, 'Content-Type: text/plain; name="Error_Report.xls"'|| Utl_Tcp.CRLF);
UTL_SMTP.write_data(con, 'Content-Disposition: attachment; filename="Error_Report.xls"'|| Utl_Tcp.CRLF);
UTL_SMTP.write_data(con, Utl_Tcp.CRLF);
offset := 1;
ClobLen := DBMS_LOB.GETLENGTH(V_LOB);
LOOP
EXIT WHEN offset > ClobLen;
DBMS_LOB.READ(V_LOB, 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, '--'||C_MIME_BOUNDARY||'--' || Utl_Tcp.CRLF);
Perhaps the error is not caused by main block but by exception handler. Change your exception handler from
EXCEPTION WHEN OTHERS THEN
BEGIN
UTL_SMTP.QUIT(v_connection);
raise;
END;
END;
to
EXCEPTION
WHEN UTL_SMTP.TRANSIENT_ERROR OR UTL_SMTP.PERMANENT_ERROR THEN
UTL_SMTP.quit(v_connection);
RAISE;
END;
I have an oracle procedure that sends emails and there are some inconsistencies happening with dots(.) in the messages.
The problem is that in this specific case the email body is being built as an HTML and there is a link in the body of the email message and one of the dots is being removed from this link. For instance xxx.xxx.xxx is showing in the email as xxxxxx.xxx. This results in the receiver being unable to access the wanted link.
During my research for solutions to this problem I stumbled on the section 4.5.2 of SMTP standard RFC2821 that says:
When a line of mail text is received by the SMTP server, it checks
the line. If the line is composed of a single period, it is treated
as the end of mail indicator. If the first character is a period and
there are other characters on the line, the first character is
deleted.
But how do I deal with this in order to make the links in the emails work properly?
Below the code of the procedure used to send emails:
CREATE OR REPLACE PROCEDURE SEND_MAIL (p_from in VARCHAR2,
p_to in VARCHAR2,
p_subject in VARCHAR2,
p_message in VARCHAR2)
IS
lv_server VARCHAR2(255) := 'xxx.xxx.xxx.xxx';
lv_port NUMBER(10) := 25;
lv_rcpt VARCHAR2(255) := p_to;
lv_from VARCHAR2(255) := p_from;
lv_subject VARCHAR2(255) := p_subject;
lv_message VARCHAR2(20000) := p_message;
lv_conn UTL_SMTP.CONNECTION;
BEGIN
lv_Conn := UTL_SMTP.Open_Connection(lv_server, lv_port);
UTL_SMTP.Helo(lv_conn, lv_server);
UTL_SMTP.Mail(lv_conn, lv_from);
UTL_SMTP.Rcpt(lv_conn, lv_rcpt);
UTL_SMTP.OPEN_DATA(lv_conn);
UTL_SMTP.WRITE_DATA(lv_conn, 'Subject: =?ISO-8859-1?Q?' ||
UTL_RAW.CAST_TO_VARCHAR2(UTL_ENCODE.QUOTED_PRINTABLE_ENCODE(UTL_RAW.CAST_TO_RAW(lv_subject))) ||
'?=' || UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(lv_conn, 'MIME-version: 1.0' || UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(lv_conn, 'Content-Type: text/html;charset=iso-8859-1' || UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(lv_conn, 'Content-Transfer-Encoding: quoted-printable '|| UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(lv_conn, 'From: ' || lv_from || UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(lv_conn, 'To: ' || lv_rcpt || UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(lv_conn, UTL_TCP.CRLF);
UTL_SMTP.WRITE_RAW_DATA(lv_conn, UTL_ENCODE.QUOTED_PRINTABLE_ENCODE(UTL_RAW.CAST_TO_RAW(Utl_Tcp.Crlf || lv_message)));
UTL_SMTP.WRITE_DATA(lv_conn, UTL_TCP.CRLF);
UTL_SMTP.CLOSE_DATA(lv_conn);
UTL_SMTP.QUIT(lv_conn);
END;
we have a table with files saved as BLOB
I write a code that email these files as an attachment!
everything works fine so far, but the files (EXCEL,PDF, ... what ever) are not readable by the programs, only text files and excel will open but after some error message, where PDFs all not be opened at all!
here is the part of the code in question!
utl_smtp.write_data( l_connection, '--'|| l_boundary || utl_tcp.crlf);
utl_smtp.write_data( l_connection, 'Content-Type: application/octet-stream' || utl_tcp.crlf);
utl_smtp.write_data( l_connection, 'Content-Disposition: attachment; filename="' || V_NAME || '"' || utl_tcp.crlf);
utl_smtp.write_data( l_connection, 'Content-Transfer-Encoding: base64' || utl_tcp.crlf );
utl_smtp.write_data( l_connection, utl_tcp.crlf );
v_length := dbms_lob.getlength(V_BLOB_CONTENT);
while v_offset < v_length loop
dbms_lob.read( V(i).BLOB_CONTENT, v_buffer_size, v_offset, v_raw );
utl_smtp.write_raw_data( l_connection, utl_encode.base64_encode(v_raw) );
utl_smtp.write_data( l_connection, utl_tcp.crlf );
v_offset := v_offset + v_buffer_size;
end loop while_loop;
utl_smtp.write_data( l_connection, utl_tcp.crlf );
any suggestions?
here is a procedure that I use to do just that
PROCEDURE StreamAttachmentToConn( p_conn IN OUT utl_smtp.connection
,p_boundary IN raw
,p_FileName IN VARCHAR2
,p_FileData IN BLOB) PARALLEL_ENABLE
AS
l_len integer := 0 ;
l_idx integer := 1 ;
l_buff_size integer := 57 ;
l_raw raw(57) ;
BEGIN
-- Attachment
utl_smtp.write_data( p_conn, '--' || p_boundary || utl_tcp.crlf );
utl_smtp.write_data( p_conn, 'Content-Type: application/octet-stream' || utl_tcp.crlf );
utl_smtp.write_data( p_conn, 'Content-Disposition: attachment; ' || utl_tcp.crlf );
utl_smtp.write_data( p_conn, ' filename="' || p_FileName || '"' || utl_tcp.crlf );
utl_smtp.write_data( p_conn, 'Content-Transfer-Encoding: base64' || utl_tcp.crlf );
utl_smtp.write_data( p_conn, utl_tcp.crlf );
-- Loop through the blob
-- chuck it up into 57-byte pieces
-- and base64 encode it and write it into the mail buffer
l_len := dbms_lob.getlength(p_FileData);
-- force reinit on this may change
l_buff_size := 57 ;
l_idx := 1;
while l_idx < l_len loop
dbms_lob.read( p_FileData , l_buff_size, l_idx, l_raw );
utl_smtp.write_raw_data( p_conn, utl_encode.base64_encode(l_raw) );
utl_smtp.write_data( p_conn, utl_tcp.crlf );
l_idx := l_idx + l_buff_size;
end loop;
END StreamAttachmentToConn;
I use this to add multiple attachments to a single email. works like a champ for me.
one thing, the p_boundary is passed in as
l_boundary raw(32) := sys_guid();
I see that you already have an l_boundary and that is what you should use.
this is based on http://christopherbeck.wordpress.com/category/plsql/ as well as http://www.oracle-base.com/articles/misc/EmailFromOraclePLSQL.php#attachment
.
then in your code, just pass in your smtp connection, the l_boundary (ie RAW sys_guid or whatever you are using, the name of the file (as it will appear on the email attachment), and the BLOB.
*EDIT --> additional information *
Ours are the same with the assumption of:
--> assume v_offset starts with 1
--> v_buffer_size assume 57
But I have noticed that there is an order that you must follow to get it to work (notably, put the attachments next to the END after body!!!
Connect LOGIC
add all of the recipients
Header LOGIC :"FROM", Subject
Body logic (body text etc)
Attachments
then after the attachments close the email (this is specifically what I have after my attachments:
utl_smtp.write_data( l_conn, utl_tcp.crlf );
-- Close Email
utl_smtp.write_data( l_conn, '--' || l_boundary || '--' || utl_tcp.crlf );
utl_smtp.write_data( l_conn, utl_tcp.crlf || '.' || utl_tcp.crlf );
utl_smtp.close_data( l_conn );
utl_smtp.quit( l_conn );
Tim Hall has a great site (oracle-base) that has what you're looking for. Note in particular how the encoding is done.
I've used similar code to send emails via pl/sql without problem