I am trying to send a mail with an attachment through oracle. But I am getting
Oracle error - ORA-29279: SMTP permanent error: 554 Transaction failed: Expected ';', got "/"message
in my code at below mentioned step.
L_STEP := 32;
UTL_SMTP.CLOSE_DATA(L_CONNECTION);
I am not able to understand where I am making a mistake.
Calling procedure like -
USP_SEND_MAIL(P_TO => 'rahul.more#XYZ.com',
P_CC => 'vishal.patil#XYZ.com',
P_BCC => NULL,
P_FROM =>'abc#xyz.com',
P_SUBJECT => 'Test mail',
P_FILENAME1 => 'Test_File-27 APR 2022 - 12 PM.xls',
P_HTML => '<BR> Dear Sir/Madam <BR>
<BR> Please find attached file.<BR>
<BR> Total count-66<BR>
<BR>Regards <BR> System generated Mailer',
P_ERR_FLAG => L_ERR_FLAG);
Below is my code
PROCEDURE USP_SEND_MAIL (P_TO IN VARCHAR2,
P_CC IN VARCHAR2,
P_BCC IN VARCHAR2,
P_FROM IN VARCHAR2,
P_SUBJECT IN VARCHAR2,
P_FILENAME1 VARCHAR2,
P_HTML LONG,
P_ERR_FLAG OUT NUMBER) IS
L_CONNECTION UTL_SMTP.CONNECTION;
P_SMTP_HOSTNAME VARCHAR2(100);
P_SMTP_PORTNUM VARCHAR2(100);
L_STEP INTEGER := 0;
L_TO VARCHAR2(4000);
L_CC VARCHAR2(4000);
L_BCC VARCHAR2(4000);
CURSOR C1 IS
SELECT 0,
'CERTIFICATE' EBIZ_DATA
FROM DUAL
UNION ALL
SELECT *
FROM (SELECT 1, t.CERT_NO
FROM CERTIFICATE t
ORDER BY 1)
ORDER BY 1;
BEGIN
L_STEP := 1;
-----***** STAGING MAILER CONFIG ****--------
P_SMTP_HOSTNAME := 'email-*********.amazonaws.com';
P_SMTP_PORTNUM := '000';
L_CONNECTION := UTL_SMTP.open_connection(P_SMTP_HOSTNAME,
P_SMTP_PORTNUM,
wallet_path => '*****/oracle19c/owm/wallets',
wallet_password => '********',
secure_connection_before_smtp => FALSE);
L_STEP := 2;
-----***** STAGING MAILER CONFIG ****--------
utl_smtp.helo(L_CONNECTION, P_SMTP_HOSTNAME);
--utl_smtp.command(L_CONNECTION, 'STARTTLS');
utl_smtp.starttls(L_CONNECTION);
utl_smtp.command(L_CONNECTION, 'AUTH LOGIN');
utl_smtp.command(L_CONNECTION,
utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw('********'))));
utl_smtp.command(L_CONNECTION,
utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw('********'))));
L_STEP := 3;
UTL_SMTP.HELO(L_CONNECTION, P_SMTP_HOSTNAME);
UTL_SMTP.MAIL(L_CONNECTION, P_FROM);
FOR x IN (SELECT LEVEL AS id,
REGEXP_SUBSTR(P_TO, '[^;]+', 1, LEVEL) AS TO_EMAIL_NAME
FROM DUAL
CONNECT BY REGEXP_SUBSTR(P_TO, '[^;]+', 1, LEVEL) IS NOT NULL) LOOP
utl_smtp.Rcpt(L_CONNECTION, x.TO_EMAIL_NAME);
END LOOP;
IF P_CC IS NOT NULL THEN
FOR x IN (SELECT LEVEL AS id,
REGEXP_SUBSTR(P_CC, '[^;]+', 1, LEVEL) AS CC_EMAIL_NAME
FROM DUAL
CONNECT BY REGEXP_SUBSTR(P_CC, '[^;]+', 1, LEVEL) IS NOT NULL) LOOP
utl_smtp.Rcpt(L_CONNECTION, x.CC_EMAIL_NAME);
L_CC := L_CC || 'CC: ' || x.CC_EMAIL_NAME || CRLF;
END LOOP;
ELSE
L_CC := '';
END IF;
IF P_BCC IS NOT NULL THEN
FOR x IN (SELECT LEVEL AS id,
REGEXP_SUBSTR(P_BCC, '[^;]+', 1, LEVEL) AS BCC_EMAIL_NAME
FROM DUAL
CONNECT BY REGEXP_SUBSTR(P_BCC, '[^;]+', 1, LEVEL) IS NOT NULL) LOOP
utl_smtp.Rcpt(L_CONNECTION, x.BCC_EMAIL_NAME);
L_BCC := L_BCC || 'BCC: ' || x.BCC_EMAIL_NAME || CRLF;
END LOOP;
ELSE
L_BCC := '';
END IF;
L_STEP := 8;
UTL_SMTP.OPEN_DATA(L_CONNECTION);
L_STEP := 9;
-- Use MIME mail header
UTL_SMTP.WRITE_DATA(L_CONNECTION, 'MIME-Version: 1.0' || UTL_TCP.crlf);
L_STEP := 10;
UTL_SMTP.WRITE_DATA(L_CONNECTION,
'Date: ' ||
TO_CHAR(SYSDATE, 'Dy, DD Mon YYYY hh24:mi:ss') || UTL_TCP.crlf);
L_STEP := 11;
UTL_SMTP.WRITE_DATA(L_CONNECTION, 'TO: ' || P_TO || UTL_TCP.crlf);
IF L_CC IS NOT NULL THEN
L_STEP := 12;
--UTL_SMTP.WRITE_DATA(L_CONNECTION, 'Cc: ' || P_CC || UTL_TCP.crlf);
UTL_SMTP.WRITE_DATA(L_CONNECTION, L_CC);
END IF;
IF L_BCC IS NOT NULL THEN
L_STEP := 13;
--UTL_SMTP.WRITE_DATA(L_CONNECTION, 'Bcc: ' || P_BCC || UTL_TCP.crlf);
UTL_SMTP.WRITE_DATA(L_CONNECTION, L_BCC);
END IF;
L_STEP := 14;
UTL_SMTP.WRITE_DATA(L_CONNECTION, 'From: ' || P_FROM || UTL_TCP.crlf);
L_STEP := 15;
UTL_SMTP.WRITE_DATA(L_CONNECTION, 'Subject: ' || P_SUBJECT || UTL_TCP.crlf);
L_STEP := 16;
UTL_SMTP.WRITE_DATA(L_CONNECTION, 'Reply-To: ' || P_FROM || UTL_TCP.crlf);
L_STEP := 17;
UTL_SMTP.WRITE_DATA(L_CONNECTION,
'Content-Type: multipart/mixed; boundary="EBIZ_BOUNDARY"' || UTL_TCP.crlf || UTL_TCP.crlf);
L_STEP := 18;
UTL_SMTP.WRITE_DATA(L_CONNECTION, 'This is multipart message' || UTL_TCP.crlf);
L_STEP := 19;
UTL_SMTP.WRITE_DATA(L_CONNECTION, '--EBIZ_BOUNDARY' || UTL_TCP.crlf);
L_STEP := 20;
-- Message body
UTL_SMTP.WRITE_DATA(L_CONNECTION, 'Content-Type: text/html;' || UTL_TCP.crlf);
L_STEP := 21;
UTL_SMTP.WRITE_DATA(L_CONNECTION, 'Content-Transfer_Encoding: 7bit' || UTL_TCP.crlf || UTL_TCP.crlf);
L_STEP := 22;
UTL_SMTP.WRITE_DATA(L_CONNECTION, P_HTML || UTL_TCP.crlf);
L_STEP := 23;
UTL_SMTP.WRITE_DATA(L_CONNECTION, ' ' || UTL_TCP.crlf || UTL_TCP.crlf || UTL_TCP.crlf || UTL_TCP.crlf || UTL_TCP.crlf);
L_STEP := 24;
-- Attachment section 1
UTL_SMTP.WRITE_DATA(L_CONNECTION, '--EBIZ_BOUNDARY' || UTL_TCP.CRLF);
L_STEP := 25;
--UTL_SMTP.WRITE_DATA(L_CONNECTION, 'CONTENT-TYPE: TEXT/PLAIN;' || UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(L_CONNECTION,
'CONTENT-TYPE: APPLICATION/APPLICATION/VND.OPENXMLFORMATS-OFFICEDOCUMENT.SPREADSHEETML.SHEET;' || UTL_TCP.CRLF);
L_STEP := 26;
UTL_SMTP.WRITE_DATA(L_CONNECTION,
' NAME="' || P_FILENAME1 || '"' || UTL_TCP.CRLF);
L_STEP := 27;
UTL_SMTP.WRITE_DATA(L_CONNECTION,
'CONTENT-TRANSFER_ENCODING: 8BIT' || UTL_TCP.CRLF);
L_STEP := 28;
UTL_SMTP.WRITE_DATA(L_CONNECTION,
'CONTENT-DISPOSITION: ATTACHMENT;' || UTL_TCP.CRLF);
L_STEP := 29;
UTL_SMTP.WRITE_DATA(L_CONNECTION,
' FILENAME="' || P_FILENAME1 || '"' || UTL_TCP.CRLF || UTL_TCP.CRLF);
L_STEP := 30;
FOR X IN C1 LOOP
UTL_SMTP.WRITE_DATA(L_CONNECTION, X.EBIZ_DATA || UTL_TCP.CRLF);
END LOOP;
-- End MIME mail
L_STEP := 31;
UTL_SMTP.WRITE_DATA(L_CONNECTION, UTL_TCP.crlf || UTL_TCP.crlf || '--EBIZ_BOUNDARY--');
L_STEP := 32; **GETTING AN ERROR HERE**
UTL_SMTP.CLOSE_DATA(L_CONNECTION);
L_STEP := 33;
UTL_SMTP.QUIT(L_CONNECTION);
P_ERR_FLAG := 0;
EXCEPTION
WHEN UTL_SMTP.INVALID_OPERATION THEN
P_ERR_FLAG := 1;
IL_ERROR_LOGGING.ERROR(MESSAGE => SQLERRM || 'message',
MODULE => 'RETAIL UNSYNC POLICY MAILER',
V_PARAMATER => (PARAMS(' L_STEP =>' || L_STEP)));
UTL_SMTP.QUIT(L_CONNECTION);
WHEN UTL_SMTP.TRANSIENT_ERROR THEN
P_ERR_FLAG := 1;
IL_ERROR_LOGGING.ERROR(MESSAGE => SQLERRM || 'message',
MODULE => 'RETAIL UNSYNC POLICY MAILER',
V_PARAMATER => (PARAMS(' L_STEP =>' || L_STEP)));
UTL_SMTP.QUIT(L_CONNECTION);
WHEN UTL_SMTP.PERMANENT_ERROR THEN
P_ERR_FLAG := 1;
IL_ERROR_LOGGING.ERROR(MESSAGE => SQLERRM || 'message',
MODULE => 'RETAIL UNSYNC POLICY MAILER',
V_PARAMATER => (PARAMS(' L_STEP =>' || L_STEP)));
UTL_SMTP.QUIT(L_CONNECTION);
WHEN OTHERS THEN
P_ERR_FLAG := 99;
IL_ERROR_LOGGING.ERROR(MESSAGE => SQLERRM || 'message',
MODULE => 'RETAIL UNSYNC POLICY MAILER',
V_PARAMATER => (PARAMS(' L_STEP =>' || L_STEP)));
UTL_SMTP.QUIT(L_CONNECTION);
END;
Related
Can someone help me with UTL_SMTP.WRITE_DATA for sending email with attachment. I am not able to send attachment with multiple lines inside code.
When I write UTL_SMTP.WRITE_DATA to write data inside attachment it doesn't work.
Below is the attached code which sends attachment for only 1 row from second cursor when i=1.
Someone please help.
CREATE OR REPLACE PACKAGE BODY xx_common_alerts_pkg AS
gv_process_name CONSTANT VARCHAR2(100) := 'Common Alert Functionality';
PROCEDURE main (
po_errbuf OUT VARCHAR2,
po_retcode OUT NUMBER,
-- p_debug IN NUMBER,
p_alert_name IN VARCHAR2
) IS
lv_procedure CONSTANT VARCHAR2(200) := 'XX_COMMON_ALERTS_PKG.main';
lv_to_recipients alr_actions.to_recipients%TYPE;
lv_cc_recipients alr_actions.cc_recipients%TYPE;
lv_bcc_recipients alr_actions.bcc_recipients%TYPE;
lv_subject alr_actions.subject%TYPE;
lv_alert_id alr_alerts.alert_id%TYPE;
lv_row_count alr_action_set_checks.row_count%TYPE;
lv_check_id alr_action_set_checks.alert_check_id%TYPE;
v_clob CLOB := empty_clob();
v_clob_lines CLOB := empty_clob();
lv_mail_body_lines VARCHAR2(30000);
lv_ctxh dbms_xmlgen.ctxhandle;
lv_queryresult XMLTYPE;
lv_xslt_transform XMLTYPE;
lv_message VARCHAR2(30000);
lv_error_msg VARCHAR2(3000);
lv_inst_name VARCHAR2(50);
lv_from_email VARCHAR2(100);
lv_to_email VARCHAR2(100);
lv_recipients_mail VARCHAR2(100);
lv_status VARCHAR2(30000);
lv_alert_check_id VARCHAR2(2000);
lv_list_id alr_actions.list_id%TYPE;
lv_list_application_id alr_actions.list_application_id%TYPE;
lv_body alr_actions.body%TYPE;
lv_ret_message VARCHAR2(2000);
lv_ret_status VARCHAR2(2000);
lv_attach_tab t_attach_tab := t_attach_tab();
v_from VARCHAR2(80) := 'abc#gmail.com';
v_recipient VARCHAR2(80) := 'def#gmail.com';
v_subject VARCHAR2(80) := 'test';
v_mail_host VARCHAR2(80) := 'mlocalhost'; --localhost';
v_smtp_port NUMBER := 25;
v_mail_conn utl_smtp.connection;
l_step PLS_INTEGER := 12000;
crlf VARCHAR2(2) := chr(13)
|| chr(10);
v_len INTEGER;
v_index INTEGER := 1;
le_mail_excp EXCEPTION;
CURSOR c_get_alert_outputs (
pi_alert_id VARCHAR2
) IS
SELECT
name,
title
FROM
alr_alert_outputs
WHERE
alert_id = pi_alert_id
AND end_date_active IS NULL
ORDER BY
name DESC;
CURSOR c_output_lines (
pi_check_id NUMBER,
pi_row_number NUMBER
) IS
SELECT DISTINCT
value,
name
FROM
alr_output_history
WHERE
check_id = pi_check_id
AND row_number = pi_row_number
ORDER BY
name DESC;
BEGIN
SELECT
actions.to_recipients,
actions.cc_recipients,
actions.bcc_recipients,
actions.subject,
alr.alert_id,
actions.list_id,
actions.list_application_id,
actions.body
INTO
lv_to_recipients,
lv_cc_recipients,
lv_bcc_recipients,
lv_subject,
lv_alert_id,
lv_list_id,
lv_list_application_id,
lv_body
FROM
alr_alerts alr,
alr_actions actions
WHERE
alr.alert_name = p_alert_name
AND alr.alert_id = actions.alert_id
AND actions.name = 'Send Email'
AND actions.enabled_flag = 'Y'
AND actions.end_date_active IS NULL;
IF lv_list_id IS NOT NULL THEN
SELECT
to_recipients,
cc_recipients,
bcc_recipients
INTO
lv_to_recipients,
lv_cc_recipients,
lv_bcc_recipients
FROM
alr_distribution_lists
WHERE
list_id = lv_list_id
AND application_id = lv_list_application_id
AND enabled_flag = 'Y'
AND end_date_active IS NULL;
END IF;
SELECT
row_count,
check_id,
alert_check_id
INTO
lv_row_count,
lv_check_id,
lv_alert_check_id
FROM
alr_action_set_checks
WHERE
alert_id = lv_alert_id
AND alert_check_id = (
SELECT
MAX(alert_check_id)
FROM
alr_action_set_checks
WHERE
alert_id = lv_alert_id
);
-- lv_attach_tab.DELETE;
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);
FOR rec_alert_outputs IN c_get_alert_outputs(lv_alert_id) LOOP
v_clob := rec_alert_outputs.title
|| ','
|| v_clob;
END LOOP;
FOR i IN 1..lv_row_count LOOP
v_clob_lines := empty_clob();
FOR rec_lines IN c_output_lines(lv_check_id, i) LOOP
v_clob_lines := rec_lines.value
|| ','
|| v_clob_lines;
END LOOP;
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
|| lv_body
|| crlf
|| crlf
|| '-------SECBOUND'
|| crlf
|| 'Content-Type: text/plain;'
|| crlf
|| ' name="ASL_Mismatch.csv"'
|| crlf
|| 'Content-Transfer_Encoding: 8bit'
|| crlf
|| 'Content-Disposition: attachment;'
|| crlf
|| ' filename="Mismatch.csv"'
|| crlf
|| crlf
|| v_clob
|| crlf
|| v_clob_lines
|| crlf);
fnd_file.put_line(fnd_file.output, 'v_clob ' || v_clob);
utl_smtp.data(v_mail_conn, v_clob);
utl_smtp.data(v_mail_conn, v_clob_lines);
--UTL_SMTP.write_data(v_Mail_Conn, UTL_RAW.cast_to_varchar2(UTL_ENCODE.base64_encode(DBMS_LOB.substr(v_clob_lines, 1, i * 1))) || UTL_TCP.crlf);
--UTL_SMTP.write_data(v_Mail_Conn,UTL_RAW.cast_to_varchar2(v_clob_lines));
-- utl_smtp.write_data(v_Mail_Conn, v_clob_lines);
-- UTL_SMTP.write_data(v_Mail_Conn, DBMS_LOB.SUBSTR(v_clob_lines, 32000, v_index));
fnd_file.put_line(fnd_file.output, 'v_clob_lines '
|| v_clob_lines
|| ' Row: '
|| i);
END LOOP;
utl_smtp.write_data(v_mail_conn, utl_tcp.crlf);
utl_smtp.write_data(v_mail_conn, '--'
|| ' boundary="-----SECBOUND"'
|| '--'
|| utl_tcp.crlf);
utl_smtp.close_data(v_mail_conn);
utl_smtp.quit(v_mail_conn);
EXCEPTION
WHEN OTHERS THEN
lv_error_msg := p_alert_name
|| '-'
|| lv_status
|| ': '
|| sqlerrm;
--debug(pi_message => lv_error_msg
-- );
END main;
END xx_common_alerts_pkg;
Rather than try to debug your code, I'll share with you my own sendmail function and you can use it to figure out what you're doing wrong. One difference that stands out to me immediately is I'm using base64 encoding rather than 8-bit, to prevent anything in the attachment from messing up SMTP. I'm sure there are multiple ways to do it, but this has been working for me for many years:
CREATE OR REPLACE PROCEDURE sendmail_html(sender_email IN varchar2,
recipient_email IN varchar2,
message_in IN clob,
subject_in IN varchar2 := NULL,
sender_name IN varchar2 :=NULL,
recipient_name IN varchar2 := NULL,
attachment_name_1 IN varchar2 := NULL,
attachment_mime_1 IN varchar2 := NULL,
attachment_clob_1 IN clob := NULL,
attachment_name_2 IN varchar2 := NULL,
attachment_mime_2 IN varchar2 := NULL,
attachment_clob_2 IN clob := NULL,
attachment_name_3 IN varchar2 := NULL,
attachment_mime_3 IN varchar2 := NULL,
attachment_clob_3 IN clob := NULL,
attachment_name_4 IN varchar2 := NULL,
attachment_mime_4 IN varchar2 := NULL,
attachment_clob_4 IN clob := NULL,
attachment_name_5 IN varchar2 := NULL,
attachment_mime_5 IN varchar2 := NULL,
attachment_clob_5 IN clob := NULL)
AS
PRAGMA AUTONOMOUS_TRANSACTION;
mail_host varchar2(30) := 'localhost';
mail_connection utl_smtp.connection;
message clob;
message_piece varchar2(2000);
boundary VARCHAR2(50) := '----=*#abc1234321cba#*=';
step PLS_INTEGER := 12000; -- make sure you set a multiple of 3 not higher than 24573
var_start_pos integer;
var_unencoded_raw raw(32767);
var_encoded_raw raw(32767);
var_encoded_string varchar2(32767);
BEGIN
message := message_in;
mail_connection := utl_smtp.open_connection(mail_host, 25);
utl_smtp.helo(mail_connection, mail_host);
utl_smtp.mail(mail_connection, sender_email);
utl_smtp.rcpt(mail_connection, recipient_email);
utl_smtp.open_data(mail_connection);
utl_smtp.write_data(mail_connection,'Date: '||TO_CHAR(SYSDATE,'dd Mon yy hh24:mi:ss')||utl_tcp.CRLF);
utl_smtp.write_data(mail_connection,'From: '||NVL(sender_name,sender_email)||' <'||sender_email||'>'||utl_tcp.CRLF);
utl_smtp.write_data(mail_connection,'To: '||NVL(recipient_name,recipient_email)||' <'||recipient_email||'>'||utl_tcp.CRLF);
utl_smtp.write_data(mail_connection,'Subject: '||NVL(subject_in,' ')|| utl_tcp.CRLF);
utl_smtp.write_data(mail_connection, 'MIME-Version: 1.0' || utl_tcp.CRLF);
utl_smtp.write_data(mail_connection, 'Content-Type: multipart/mixed; boundary="' || boundary || '"' || utl_tcp.CRLF || utl_tcp.CRLF);
IF dbms_lob.getlength(message) > 0
THEN
utl_smtp.write_data(mail_connection, '--' || boundary || utl_tcp.CRLF);
utl_smtp.write_data(mail_connection, 'Content-Type: text/html; charset=us-ascii ' || utl_tcp.CRLF);
utl_smtp.write_data(mail_connection, 'Content-Disposition: inline' || utl_tcp.CRLF || utl_tcp.CRLF);
utl_smtp.write_data(mail_connection, '<html>'|| utl_tcp.CRLF);
utl_smtp.write_data(mail_connection, '<head>'|| utl_tcp.CRLF);
utl_smtp.write_data(mail_connection, '<title>'||NVL(subject_in,' ')||'</title>'|| utl_tcp.CRLF);
utl_smtp.write_data(mail_connection, '</head>'|| utl_tcp.CRLF);
utl_smtp.write_data(mail_connection, '<body>'|| utl_tcp.CRLF);
utl_smtp.write_data(mail_connection, '<pre style="font: monospace">'|| utl_tcp.CRLF);
FOR chunk IN 1..CEIL(dbms_lob.getlength(message)/1000)
LOOP
var_start_pos := 1+(chunk-1)*1000;
utl_smtp.write_data(mail_connection,dbms_lob.substr(message,1000,var_start_pos));
END LOOP;
utl_smtp.write_data(mail_connection, '</pre>'|| utl_tcp.CRLF);
utl_smtp.write_data(mail_connection, '</body>'|| utl_tcp.CRLF);
utl_smtp.write_data(mail_connection, '</html>'|| utl_tcp.CRLF);
utl_smtp.write_data(mail_connection,utl_tcp.CRLF||utl_tcp.CRLF);
utl_smtp.write_data(mail_connection, '--' || boundary || utl_tcp.CRLF);
utl_smtp.write_data(mail_connection, 'Content-Type: text/plain; charset="iso-8859-1"; format=flowed' || utl_tcp.CRLF);
utl_smtp.write_data(mail_connection, 'Content-Disposition: inline' || utl_tcp.CRLF || utl_tcp.CRLF);
FOR chunk IN 1..CEIL(dbms_lob.getlength(message)/1000)
LOOP
var_start_pos := 1+(chunk-1)*1000;
utl_smtp.write_data(mail_connection,dbms_lob.substr(message,1000,var_start_pos));
END LOOP;
utl_smtp.write_data(mail_connection,utl_tcp.CRLF||utl_tcp.CRLF);
END IF;
IF LENGTH(attachment_clob_1) > 0
THEN
utl_smtp.write_data(mail_connection, '--' || boundary || utl_tcp.CRLF);
utl_smtp.write_data(mail_connection, 'Content-Type: ' || attachment_mime_1 || '; name="' || attachment_name_1 || '"' || utl_tcp.CRLF);
utl_smtp.write_data(mail_connection, 'Content-Transfer-Encoding: base64' || utl_tcp.CRLF);
utl_smtp.write_data(mail_connection, 'Content-Disposition: attachment; filename="' || attachment_name_1 || '"' || utl_tcp.CRLF || utl_tcp.CRLF);
FOR i IN 0 .. TRUNC((dbms_lob.getlength(attachment_clob_1) - 1 )/step)
LOOP
var_unencoded_raw := utl_raw.cast_to_raw(dbms_lob.substr(attachment_clob_1, step, i * step + 1));
var_encoded_raw := utl_encode.base64_encode(var_unencoded_raw);
var_encoded_string := utl_raw.cast_to_varchar2(var_encoded_raw);
utl_smtp.write_data(mail_connection, var_encoded_string);
END LOOP;
utl_smtp.write_data(mail_connection, utl_tcp.CRLF || utl_tcp.CRLF);
END IF;
IF LENGTH(attachment_clob_2) > 0
THEN
utl_smtp.write_data(mail_connection, '--' || boundary || utl_tcp.CRLF);
utl_smtp.write_data(mail_connection, 'Content-Type: ' || attachment_mime_2 || '; name="' || attachment_name_2 || '"' || utl_tcp.CRLF);
utl_smtp.write_data(mail_connection, 'Content-Transfer-Encoding: base64' || utl_tcp.CRLF);
utl_smtp.write_data(mail_connection, 'Content-Disposition: attachment; filename="' || attachment_name_2 || '"' || utl_tcp.CRLF || utl_tcp.CRLF);
FOR i IN 0 .. TRUNC((dbms_lob.getlength(attachment_clob_2) - 1 )/step)
LOOP
var_unencoded_raw := utl_raw.cast_to_raw(dbms_lob.substr(attachment_clob_2, step, i * step + 1));
var_encoded_raw := utl_encode.base64_encode(var_unencoded_raw);
var_encoded_string := utl_raw.cast_to_varchar2(var_encoded_raw);
utl_smtp.write_data(mail_connection, var_encoded_string);
END LOOP;
utl_smtp.write_data(mail_connection, utl_tcp.CRLF || utl_tcp.CRLF);
END IF;
IF LENGTH(attachment_clob_3) > 0
THEN
utl_smtp.write_data(mail_connection, '--' || boundary || utl_tcp.CRLF);
utl_smtp.write_data(mail_connection, 'Content-Type: ' || attachment_mime_3 || '; name="' || attachment_name_3 || '"' || utl_tcp.CRLF);
utl_smtp.write_data(mail_connection, 'Content-Transfer-Encoding: base64' || utl_tcp.CRLF);
utl_smtp.write_data(mail_connection, 'Content-Disposition: attachment; filename="' || attachment_name_3 || '"' || utl_tcp.CRLF || utl_tcp.CRLF);
FOR i IN 0 .. TRUNC((dbms_lob.getlength(attachment_clob_3) - 1 )/step)
LOOP
var_unencoded_raw := utl_raw.cast_to_raw(dbms_lob.substr(attachment_clob_3, step, i * step + 1));
var_encoded_raw := utl_encode.base64_encode(var_unencoded_raw);
var_encoded_string := utl_raw.cast_to_varchar2(var_encoded_raw);
utl_smtp.write_data(mail_connection, var_encoded_string);
END LOOP;
utl_smtp.write_data(mail_connection, utl_tcp.CRLF || utl_tcp.CRLF);
END IF;
IF LENGTH(attachment_clob_4) > 0
THEN
utl_smtp.write_data(mail_connection, '--' || boundary || utl_tcp.CRLF);
utl_smtp.write_data(mail_connection, 'Content-Type: ' || attachment_mime_4 || '; name="' || attachment_name_4 || '"' || utl_tcp.CRLF);
utl_smtp.write_data(mail_connection, 'Content-Transfer-Encoding: base64' || utl_tcp.CRLF);
utl_smtp.write_data(mail_connection, 'Content-Disposition: attachment; filename="' || attachment_name_4 || '"' || utl_tcp.CRLF || utl_tcp.CRLF);
FOR i IN 0 .. TRUNC((dbms_lob.getlength(attachment_clob_4) - 1 )/step)
LOOP
var_unencoded_raw := utl_raw.cast_to_raw(dbms_lob.substr(attachment_clob_4, step, i * step + 1));
var_encoded_raw := utl_encode.base64_encode(var_unencoded_raw);
var_encoded_string := utl_raw.cast_to_varchar2(var_encoded_raw);
utl_smtp.write_data(mail_connection, var_encoded_string);
END LOOP;
utl_smtp.write_data(mail_connection, utl_tcp.CRLF || utl_tcp.CRLF);
END IF;
IF LENGTH(attachment_clob_5) > 0
THEN
utl_smtp.write_data(mail_connection, '--' || boundary || utl_tcp.CRLF);
utl_smtp.write_data(mail_connection, 'Content-Type: ' || attachment_mime_5 || '; name="' || attachment_name_5 || '"' || utl_tcp.CRLF);
utl_smtp.write_data(mail_connection, 'Content-Transfer-Encoding: base64' || utl_tcp.CRLF);
utl_smtp.write_data(mail_connection, 'Content-Disposition: attachment; filename="' || attachment_name_5 || '"' || utl_tcp.CRLF || utl_tcp.CRLF);
FOR i IN 0 .. TRUNC((dbms_lob.getlength(attachment_clob_5) - 1 )/step)
LOOP
var_unencoded_raw := utl_raw.cast_to_raw(dbms_lob.substr(attachment_clob_5, step, i * step + 1));
var_encoded_raw := utl_encode.base64_encode(var_unencoded_raw);
var_encoded_string := utl_raw.cast_to_varchar2(var_encoded_raw);
utl_smtp.write_data(mail_connection, var_encoded_string);
END LOOP;
utl_smtp.write_data(mail_connection, utl_tcp.CRLF || utl_tcp.CRLF);
END IF;
utl_smtp.write_data(mail_connection, '--' || boundary || '--' || utl_tcp.crlf);
utl_smtp.close_data(mail_connection);
utl_smtp.quit(mail_connection);
END;
/
This is HTML enabled in the body. I have another one that is plain text. I like having HTML so I can do some simple formatting like bold and italics and such.
My attachments however tend to be text, even if CSV or XML intended for Excel. So, I always use the mime 'text/plain' for my attachments. Compile your attachment as a CLOB and pass it into one of the attachment parameters.
I'm trying to send a pdf document and a small description about it from my server to a Telegram group using a Telegram bot user. I'm able to send a document by itself using the method /sendDocument. However, that is not exactly what I want. I wonder is that even possible to do ?
The actual output message is "ORA-29263: HTTP protocol error."
declare
l_attachment blob;
l_newline varchar2(50) := chr(13) || chr(10);
lco_boundary constant varchar2(30) := '----=*#abc1234321cba#*=';
l_http_request utl_http.req;
l_request_body clob;
l_request_body_length number;
l_http_response utl_http.resp;
l_response_header_name varchar2(256);
l_response_header_value varchar2(1024);
l_response_body varchar2(32767);
l_offset number := 1;
l_amount number := 2000;
l_buffer varchar2(2000);
postData clob;
p_id varchar2(50) := '********';
begin
select invoce into l_attachment from some_table;
l_request_body := l_newline
|| '--' || lco_boundary || l_newline
|| 'Content-Disposition: form-data; name="document"; filename="file.pdf"' || l_newline
|| 'Content-Type: application/pdf' || l_newline
|| l_newline
|| apex_web_service.blob2clobbase64(l_attachment) || l_newline
|| '--' || lco_boundary || l_newline
|| 'Content-Disposition: form-data; name="document"' || l_newline
|| l_newline
|| 'file.pdf' || l_newline
|| '--' || lco_boundary || l_newline
|| 'Content-Disposition: form-data; name="MAX_FILE_SIZE"' || l_newline
|| l_newline
|| '4000000' || l_newline
|| '--' || lco_boundary || '--';
dbms_output.put_line('Request body>');
dbms_output.put_line(dbms_lob.substr(l_request_body, 4000, 1));
l_request_body_length := dbms_lob.getlength(l_request_body);
utl_http.set_wallet('file:/u02/oracle/upload/WALLET_TELEGRAM/', '******');
l_http_request := utl_http.begin_request(
url => 'https://api.telegram.org/bot<MY_KEY>/sendDocument',
method => 'POST',
http_version => 'HTTP/1.1'
);
postData := postData || 'chat_id=' || p_id || '&';
postData := postData || 'document=';
utl_http.set_header(l_http_request, 'Content-Type', 'multipart/form-data; boundary="' || lco_boundary || '"');
utl_http.set_header(l_http_request, 'Content-Length', l_request_body_length);
utl_http.write_text(l_http_request, postData);
while l_offset < l_request_body_length loop
dbms_lob.read(l_request_body, l_amount, l_offset, l_buffer);
utl_http.write_text(l_http_request, l_buffer);
l_offset := l_offset + l_amount;
end loop;
l_http_response := utl_http.get_response(l_http_request);
for i in 1 .. utl_http.get_header_count(l_http_response) loop
utl_http.get_header(l_http_response, i, l_response_header_name, l_response_header_value);
l_response_header_value);
end loop;
utl_http.read_text(l_http_response, l_response_body, 32767);
dbms_output.put_line(l_response_body);
if l_http_request.private_hndl is not null then
utl_http.end_request(l_http_request);
end if;
if l_http_response.private_hndl is not null then
utl_http.end_response(l_http_response);
end if;
exception
when others then
if l_http_request.private_hndl is not null then
utl_http.end_request(l_http_request);
end if;
if l_http_response.private_hndl is not null then
utl_http.end_response(l_http_response);
end if;
raise;
end;
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,/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAoHBwkHBgoJCAkLCwoMDxkQDw4ODx4WFxIZJCAmJSMgIyIoLTkwKCo2KyIjMkQyNjs9QEBAJjBGS0U+Sjk/QD3/2wBDAQsLCw8NDx0QEB09KSMpPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT3/wAARCACxARkDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwB9scOF3N781pQoFQHt6n/PWuJ/tCaxkjjjYk8ck5zzW5ZeII2IhvS0c+/G3HSuVprY+i5ovc2HXzOhAOe9AYQPs6lh1XmlRTuO0ZBJOSakZBtYeWNzEEMM5HtTizmrU9CMMCMZwPcUM8YVVXAx945zmnNukJRVy3rio7keVGBclIwvygswX/8AXW8Ty6sCHeglJHUHrmnOUkHysPWq08lvA6iSaFd/QGQZ+tLFcW0mNlzDuyRt3AE1qcrihjwHPSo2tQ3UVfVS6bldGX1Vwf5UGI7wAynPpTJcTIlsRg8Gs+4s8A4BxXVCEY5HNRSWivztppkWOMeyY9FP5VF9kIPQ11cunsCSOnpVM2R3H5aq4XRhC0LdQaT7IR0BrpYdNLjIWrUegmQ/dxRcNznLLT/MmAYECugh0kR42jNbNj4bIwcc5rWj0ZkHzVLkUkc5FZeXhsHNWRuVetal1ZmMEKMsKzJIZzgqnfrU3uFrFCVyXPrT4ppF6k4qwLE7izd6JbXAGxM+tJk3HQzhiNrDmla9cYVkYvnoPSqGoTLbQZRgFXqx4xWN/wAJa9vJmP8AeMDjIXgfnQJXZ23kl0yQRn1qtcIYOPU4BFcbeeOL5VRowokbksy5TbnHOO/FVh4vnu08y5XKg4XB4FKxXKzuhkxjd3qFkJbgViaX4otmlWC+kKb/APVueR9DXVxoigMMEHoaZLViBLffgMOMUtxH5cG2NRjuas7h2oIBUg96LgZEcRIUsKtpagndg+tWVgwMKw/KpNm1MZJ9TVXCxQkXEme1MbrnFWZYyTwOKi8onvx6U7k2IqM08IQ3QfjTsf7MdIR5a3mM3mg4ZTx61UluJZZy8kjZY5Ld69BXTrSNyRAqn1AqvN4cs7gFkRl4wMEYzXFGvFvY+wq4CpbSRydprl9aSbobiRlQ5Cljhq6ODxzK8Krc28CEEZILbmBPbtxWXqmhQWeY45WaUjlMdPyrCuIblTsaEhTnAA6e1bJRnqjgmqtLRnfS+KFkkEWmpu3n/WEfMeP4QfSsm6ma5uI5rh3uHx8xduvPYdBXJx3NzZSFoy8b7So45APXrVq01S4h44kA655AH1rVQszjnNS33N5Yw+RtAUdBjkfjT12JkSRCQYIGSevrVe1vkuFGBtdhkAnrVnaXb3PNWc8o9URxZjKGJijqeCvFa1vr15FkvFBOV43MMfyrNEfPGPzqQRHGO3pVWuYvQ018SXTyBRZ2oB75atSw1K31CNd8qQ3GSDETyfpXMouMYz68VI8EbqpGdwOcjjFHKib6HXmEY+6zduRxUb6ez8hWPtiubM10/wDrLudh6GQ4p4kuT/y3kIHq5pcrI5kdLBbeU20qfpWxaW0Z5PGK5PS9UNpcATs7wnqM5I+ldbZSxTgPGyvEejKe9ZzTRcWnsbVvFGFG0danaINwBzUVogC1eQAdqybNkjKuNMdyWC5+lOm05BZKuzkVrZ5pkiblxRdj5TnJdLURZ6HNZslrt3c4HrXUyQk8dq5L4hXf9k+E7mZAFllIhVh2z1/QU0zNxPOvFviNJbow2+CinG71Pr9a5GW7eXow98DoKUT+e7hfmPXJ78etXhozSfZm3FYpv4Rw3+c8CtLpLUqMLmck/mH5mxGmSACcYNSxmaKeRoiMr2butdZqHhSGz1a0sMKGltzO/cKOwPocg1VXTFu7AXCJsf1x94Zxn6+1HOivZsxUuophtcBHHYdM/wBK7rwb4g8+FdPu2/eRnbGxP3gOgrza+CxuVUc/xYqS2uJ4GHlyEHAIIPcUbmclY912ZPHT2pxjPpXH6Rr+ofY4JSxkTH3W6V01lrltefK4MMv91jwaTTRnctBT2p23irKRBumKGjxQmOxU8vtiozH82BVvaM4NDBAOBVXFYoNFg9KTZ7D8qtMoNN8ulcVixqvhpo1L243gDnHauTv7mazASGMCQHlj1X6e9dvbeJrK+JCyeW/oT1pdR0y21BdxwGxwQOa8de7qj6yjialJ8mIizyqcGOZyW3sx3Fl5zmkExDE4XI74rsW8OKt1vMSSoAQAehrHuvDc8cjFUYj6VarX3PSpujOWkjIFnaXcLeaFDL371QfSLf5/KZ03KQQecmtp9JnjByjD6iq8lo8fXOa2p1X3M8Vg4TV4pHPSaRcRudhVh14p9tqMlv8Au5YzszyWGDn/AAreCgcMSFA+ppk0STxlSq/Uiu6FTmPncRhnAht7y3n+SMgOe1W1QnJz0NVotOiifzNo3D8BVxORW9zzKiEVWydo6fpTgDnnr9KXbipAM88D2FM55MVBv4HBpSpXvQEHUcH1qQc07GfMMQDPIzWvp19cWq4hcBSclcAg1nirELmMjB4qWioyO00nWPtUgW4CxsehHArfVsDrmuCtrpR1A+ldBpupFWSORiUPTJ+7XPOJ0wnc6ANk0tV/Nw3PFPEmTWZqmSFc15f8cWmi0DTlTIjad9/p0GK9QVt1cd8VdFk1rwVcCHmS1IuFAGSwHUf1/Cmhs8K0jTpr957a3hknmaJSsSDOWzjn0r0Ww8GeIRDFLcadDFHZ4cQyzgvdPjrnoqg9BWXoI/s/4awXNk4tprmWRru5SPdKURsKgP1I/OubVtZkuZ71Z7pjbsPNWaY7+eRx06Dp2od5XsWtLHZS6fe2897qmsNbWl3PCVh8y4BS1j6ZwOWbk1SPifQ4NPt7Kxkkn8hNqlYsZbaQDjsOp9aqeMdH1Ge10nUi8jRXcIA3HkZ55HbPuaytI0Q/vkW4PmEKItpzvJ6gqOR65zSirrU0m7aR2INZ0fmSe1fzEZBIpjBYZ6lSezAc1z0M5Vx6HivXPDcV8LDZIsSQSMd77cmQdM88Akd8VxyeCll8S31urP8AZbWQqsYPzynrtB7DHU9qqMyJU2z0X4Xm11PwqY5oo5GgkKfMvNbt/wCErK4JeENE59DxXOfCANHJrVvGm23jlUKpOdrY5GfavRXXNHNqYOPRnFJaa1o8qpEVvEbsQRtH1rZTzHRTKnluRyM5xWpIOpxVKUFuQOKfNcnlsUTnefakz82Km4Vn+XJI4J7Ugi3fdB+gqrisQ4wc0Z9qmCYODTtgouFjzGW8S2IXezyE8EHpXQ6N4nntkUSP5scnBVjkrXJbBtEjZ8zJ6UpmWIrucZz0PU15rou1j7ydelXup7Hq+nahBdY5Gc4ya6OO3jdAdoP4V49pepmC4UhuAegNep6Fq0V5bqN43Y6VkoJSSZ42YYZ01z09UaUllBMmGiUj6Vgax4UhnQyW6gP6V1AIprkY611zw8LXR5dHE1aUrxZ4zqmnSWcpV1I571RA2tiu/wDHkVuIkkLqJO6g84rgCRn5eQaVCTTse5VaxGHVW1mPTnBqRaaV2diO/XtT15r1Iao+WxDsxcZNSAdqVRgHB5NKFOKs4XMCBs4zmnotKq05ugwcfSgnmF2/5xUqrzTEqTOOn51LGmSxtgjnFRz+IHs5RFGq7jIRkjOFA5NB9axNTluI9YkxbLLGyggl8DaRyPzFTYuMrHoOja7JeQeXOBv3BVcdenGa6COXPU15j4cuLljc+fCIkDKUwxIHXgH24rr9N1WQ3CxXD7o34DnGQf8ACsZw10OiM+506txxSnBBDDIIwQarxylTg1YWTNYm6ZxVnodtpmp3saRZiEvmC338ENgkqDwrZH49Kp6j4dtZpna3glZnBVROQFQngk884B4H58Cuk8T2zrF9piGw4AYgdOeM1mStHLahLkgxSLtdSeCD1B9qyk2mddKziTeINQ0KPTLeG71SzjTYFUiXjP8ACQR0I9qy7DTIVh85LlHWQDJjULuHuR6+oxXCX9x4TsdWkSK/lkhj+QQwQF0z7E9QK6PSvFGn6jEsFmzMFXaDjaAPcdqtrQaaWhr3+r7Y2gMaAKNqAYHT2HQVjXrWcto17qMcgW2LXRaMEZbH3d3TnAGD68VBcXCxXzDCuF6kdq53xoXGjW7xzym3numRk3EDAUY46epoirsJSsrnq3w10/7H4OguCnlyX7tdOM5PzHj9K6sr7VleG3VPD2nxq2QtumPptFapkNaPc42QTLxWdMvBNaUuTVOZARQhGc2T34pASmCpPB7HFLjMzIf7u4U7y8CquTYYOTz1p2KAhwWyODjFHNMLHkTapHM7iRRGQeMDt6Vmv+/cySHGOAO9WLixO0sm1WJ6AcVEImTggH3FVGEbaHVLFze5bs544kDE425JJrd0/XJLcpJE5XOMc1y7/My4HA/nUU8jmQuzdMYwaynhlM7KWayhHlkro9VtvHtwkYDbSae/jy5cHbsBryq31R1kVHb5B14rViv7WRgqygN6GsvqbfU1+vYN68iuauuXsus3AkeZ1kHRgePyrH+2XFi4+3QGSI8CaLn8xV4Y68ketSL+GK0hhVHYmpmzlHkW3YLeSO4i823lSSPGSVPT6jtU6cckgDOM1lS6Uol+0WUrWk4Ocx/d/EVYj1RLWHbq8TJITj7RCu5T9V/qPyrqi3Hc8Svar70H8jYChdvOT3p3f2qvFKskQlhkiuIj/HGcgfX0ra0jQbzVAJFVobXvPIvB/wB0d61ukrnEqcpO1iiFyOuKNoPFdFf6Ba2i7k1a3QDqZYS+4+mVI/QVhTzQQXk1pOypdou8LGcxyJ/eU9cD0PIrNVot2NJYWolcjVQOtPRc/epAVJGSMHpU0QywIPIPB9KpsySaG7emaz9TVTPEWBwYyv61qOcscnJPeqGolfOgULuYAnBqbmiWoaddw2sJSd2G4gqFQnI71sxyJJCrxMGRuVYd6564hYLA8kcimJixKnJI7jFaejybtPQ4YfM2AeuM1LKZ1uj3xuYzC7fvYhwT3WtVHK9a5G1u47Odbma5W3ROTgbmcegXvWhD4s025DG2E8hxnBTB9uO341hOyZ007tEHjbVXS2ihgJIRhK+D1I6CsW3aHXtMU7hLaucFQOc/3SaZq1559wfMfO8cZ6fSuLu7+fw5qcs1m/kx3BDYP3A49fTIqFHmZ0RlyGxL4ZurW8dbDw5atGzYDuWK/XGa1GtJ9K08LdrCJZOFRBgL+Arnbr4qaiYggg2P1LA1gXXia/1e5DTzMA3Bw2TinyS6mjqpnS31xEWFtbSBpXI8x852j396r67Jb2+maQ11am5t0vC0kIfb5gC9M1HFZqNNMq9c5OKreK7pYtH09F+8s5dh/wABxRFe8iZSbiz1vQPGWkaxFBFayLbT7QotHIDDA6DsfwroDPg8An1r5/0ZoL1wp2MVO9Q1d9Z6jqlnbK9lqBWDhWju4/P8k9ufvbfTk4rreEk1eDueYsbGLcamh6FLMM4z0qu75U1gaNrd5dl0vmhllUMx8lCoIXr1PNa9hdw39uZISSucYIwRXPUhKDtI6KdWNRXiUJpQmvJGTwyBcVdcEmsLXJHh1ouvVNuPqK6IDeiuBw3NSzREKj1p+0UrLtBPpUfmL60XA8iBzz1PpTGiyaeOKeK6UZORD9lVh1+b0qo9kWQkgZB/OtMY645oAGOlUjKTOee0lSQMI2HrxUMsZH3lIbtmurGGHNQy2kU/31Jx+FUjFs563vZ4CCJG47dq1YPEMZADxEHHJHrSy6GpmDRNtTHRqqXOiTRKGT94D/d7VQcxvW13DcqGhcN6gdRVkKsh2S8oevGePpXG7J7YYwUYHIYDB/OtKy12SE4uFLg8bu4oMmne6Nm28KSahqqnQrw6fcMCSzn5OPX61a0jwj4k8QSiXXLiXR4YnIkuC/zS9gFTOB354HPSktL8TJutbjy2YY35xisPXNWvLOdre11ppUPUxxFPwrnqqSdkenhpRlC8nqd1pfhWzn1b7Na61qE0Nlb+W7sV2wlj9wDHJOMk1yHi3w7qXhfUrK/luo7mxllYRTxqVKH0ZegyPwPNP8N/ECPRNKksbiFnDvukkC7ncY6DPT611Og/EzSJrN7K+gEMUMLsZHO4MxHK49STxWXK07nRdSjuc7pni77APss8aPGhyrFA2VPbPtV+78TR7jNB5LwkAkIMEfWvPxMUZmYHAHGeoohu/vZO0k49j+FO1tjBtSVmekWmsWN4rYkMci9UcZ/EY6ioHuoYbz7bcQXFzb5CIkPQn3PUfSuLNyVjV7dyJkxhgOnt7itLTNRlvSyCUpLjn0P1oc7oz9mou50upX9kRFdRyzQwRsS8bxksBjnjvVVfHOmg2tnZRSx2zMVa7kYeaf8AgI6DnpVSZruCIm0lJVifOtpFDA/TPv2rIn0+21ZhPDH5N8ONij5JgOv+647DofrRzaagoJvQ7Jrq/sZS728VzaN964jz5ig9yPbPaqram9jrS/2gI5YbpB5Vyg/IZ7jHaquja+93YRwwsn2yEBMuOT2Ab6jjPY1YktYNX0ieBQyKwJQE8wSjqB6Zx0rF6HQkmWfEc1vaWHnyyKsOzBPzZ3Z+UE4OAfX8K5G7MGp2pRjndnZuI2se2GHB/n7VqaDqjXsclnqDbpYT5ZJ7jtWhceFdNuIWW3H2V9hKyxdiORuXow9jQnbQdjym5jnsbh4XOGU9KvaYYb5/JKbLvrEy8ByP4SPU9j64qxqts1jeNa6xC6vHwk0XzK4PQjPUfjVVbSyZgIb+NHz8pKsBntkkcfnWykTY7SynS50XC5DqMMvrWH4mUzwsqjPkqpYCklvZ7KaO6nD4kyJkQZCyDr/30MN+Jq3YQXHiFZoLGJ0e4b99PMNqRp3x3J9AKShroDn7t2c3YyRo6q8jRMOjDoa67SdXv7GUSEi6gIw65yCvcGt3xFoJt/Bs1npNnG5Owu8sYDuqjqg7H9eteW2+oXVo+Y5XGOMGuuM3T3OCVNV03E9k0u6MN7E8BLwSSqE+YNgNjIOPStPwtKtxqYKghPnHA69etef+CPEEk1zfz3mEisbZrwsB94rgKp+rEV1nwylla+WORs5ieUg9s44/WssVNTaki8JTdFOMjX12Pdqk4xnB4rd0k+dpkXcrlTWLqXmSXU5PJyWJFXfDkrrLJC3RlDqCK53sdKeppXuILKaRuMIcfWuZ/tBvVq6XXWEelykkDPAyM8muO8xv7w/IU0hs4oOPXnvT1cHoc1UjOY1O4NnuBUq/KPWulbHJJ2di0oGOT+lPAHY5FV8gYIGKd5jkYUj6Ggl6loJgZzSqBgqD3zUCysO+R6VIJgRyM/jVIzaJsZApQOMZA+hpqyqBwuKjLlz6YqkQyQwhuHAYfSqs+j20wO0FGP8AdNWkJPBdV9s04llACEbc5zTJuYcunXWm4mjmU7ehAxV61ubu5DQzxlHI4YAA49qviRm4PI+lTKoUccCk1cuFRx1OL1SWGwYxNbM03XeTkGss3b3DlTiOMjhdwAz6n1rs9e0oahbFk++ntXBXNs9vIQwPBrKWh3UpqaNFrhEfyySWb5QVOR7fWrb2wMZV1x0INZFvIUKgMoJGMnqMVtyTb7ZCdu7ZyR39qxk7GqiVJWaEdNy0QyvG7SRuyl+uPSo7e5MkzNJErquAVkJx9TjmqkszQuhGM47VN7lJaHSQ6g8ocO+HjwVP94U2LVDJKbhMeYjDeAMBvfFZSSKRwcHaDnPSo7aYDVSjNtSQbWP170hctmdC04sPEqXi4C3SfOp4BycPn9GGO5ralvjpuuxOrZg1GI59PMXgn8sZ9641rpriyYNIB5IcjJ747fkK1bi4N3pkRDgvbXCyJj+669fzFJjH6uBpeux3MTZjmIziuus9U3WwK7Vb1PPauN1djdTRuxGBg4AxViwnIxGykkDnBpblbHQ3kUGpFkmjSXzOPn7fQdhXA6v4bksZ3+ynemfuHqPp612a6isZGQVIOcHk0lzPZ3cRMrYLDK7RkimroTZw+latPZT7GmlAceX1wV+ma6ux1PyXBt9Z8rcNy/abMEH/AIEh/pWBq+msC42jzUOeO49RWt4S1log1k+m298s75WCSMN+9A5255+YY49Qa2pyszmrK8bo7Ox1vxBMgjjbQtQUj7q3AUkfRgDXnHiTTb658VTW50VbG6lwy20JyvT7+c4APUnOBXXvJogkkbVPDsumJGhd5lkeML6bVP3iTwAK4jWPEb3oe00yD7Dp7HlAd0k/oZXPLfT7o7Ctqmxlhk7t9PmWvMh0/TX0yzmWYysHu7lDlZGX7qJ6opJOf4jz0Art/Al4NMvYLmYgo+YmGMEZ6Y/KvK4w8cg3ElSMiu68PRvcC1nU/ubefc5JP904H61y1XbQ7acbtnol+/mzyOp2A9icHHpT9DnaPU054PynPNPvfs9wsc6qAWjUtj1pNHj8rWYxjg54/Cl0JsXvFMyLbx24J3FtxGOgrmNldD4qj2zwyZJ3J68DBrnt9CEeb2mUjOST6ZFW1eo2Vl+8KFOeldS2OWfxFkPnqDSg5OagGcZyacrEdKZBaRgeMD60p61AkhB5qYOrDk0hD1YjmhXLZpmFHzLlvUd6kDegAzVJkNC7sc59sYqTzcAA8+nFRdKUH5xiqRiyyPnQruxg8e9TkhYAe/pVcOfmwMA8E4p4lygTjjv3pkXLCMCAGzx6VQ1LQ7TUssoWOTHXHWrMbhmPNTIAT1x9aUoqS1Lp1JRd0cTqPhS5Rl+zRGQD+7zWdJZajp7o1zC8a5zhv8K9N3kYxx9Kjv7aO6tRHMAy5A59K5nSa6noRxd7XR5fJecusan5j1NV5W3uPpXa6p4EmAE+nKsqn+AnDCseXwTrWXk+ybUHTLjJ+lQvQ6eePcw3mK4C9e9TQyAX6M4+6Bn8qsTeHNWgiEsljKI+u4YP54qkhPnvIf4eTQxpp7FuZxi72jIMjf5/WtfS5vNt0ibAV4dv4q3Fc6JP9GIzy2c/nWzpTfu4QeAAefSkwLt5EC/mLkMcAAfTvUVndMLnITD7Tk+oqWUnz3ZmG0jH09Kz5LpbW4SZl3hRyo6/nUobNhrl5I9qMjuRnbg5/OqDNI6M5+VwcEjimtrcO6KSJjEwJGCp4H1qcT/ZIleaIFZFDK5HBqkS0VPtkpwjsNoOVz1FVw7Wt6xjbBLBlb0wcj8qdIULEsQCfbpUN5tWFdpO9RyexHtVIzfY0/EWs32vWELXdxNMIpCGaRs4YjgfofzNYSxTBQMrgdM1fiRLiGbcVRSnmAn19PxOaqrNJF/AGWuhK+rIXurlRXd5EcB69N8DWTXugyfOVLSsBjtwMH9K86uws0SyIPmB5X2rs/COpNZwWsaLPl+6EbR65rmxETooS6npL4EIXoQBTrCcLqEDEBcHk+tVWkZid2OmeKrG4eB1YgFgcgGhR0M5T1Or8RWyXFgJzwYzwc9Qetct5cPrVu81+5urQowi2swyAnT6Vm/aj/dFCiLmPPvvDuaQcdKGBUkUgORW0JaGdSOpKDkYNKOvtUa80u7B61VzJolJAFOVhjpmq5fNORiKpMhxLKPz6VOpBXnvVRZCe/SrCOH64BpNkNDgvOB+frUqrt+9SJBvcASAAnqeBUsVsDEXaYKCTsDAjfj0Pek6kYvUFSlJXig3cYHSnofXpTfJYHqfpTwO3f24q7mTj3QoK7sjdn9KlZ1jQu7hQBkkmkWI4Gen1ohydQsW8gTBJwzRs2AwHr9OvviiUrK4Qp88kh0V9bSyiNLiMuMfKWAq0AJRipvEn2rVNMe4FrZWs0cge1MT7pJ1JxjGBgY559KzdGvWu4v3mN6naSOma541XLc7a2GVNXia0M2Ymy2TnHSk5PXkenYUyJP9Yo7NmnAY5JP0FadTlZWggtrZ4xPJKhnfao3kAn6VxHjDwzLpl5JLbRn7I/zLgdD3Fdnqw/d2soB/dSqevvWtqVpHe2E0cvOAWX61E0b0Z8rPEkhc44rWs8xhF6Enk1MYFm1aZI0GxMk/TFMxtl46DpWTO6+po/LPBh+SPSsq7jACccYq9HJhSD3qKRBImSOnrSKM+zEbS+TIuVY1d/spgAI53WMnIU/MBVFx5MquOMGtpJDNZ5j+9jnNJsaA+Grd4lKy5Pq54zVC9t4zbNEDiSE4x7U+DUpLeXa/zxn+FulVpptx39M8cdxVRTM5tDdGm2zpGcbZA0L5HZv/AK9IqGN2GNwU7SPSq9uxhuCB3II/A5FWLmVYdTlZvuljuHrmumnKxhNXloLLGhhZsfMBWr4UuWGrtatyiJtGPXgf41mvteAMucEjHvV3wuDDes4HzFsc/WoxBVFtJnrBZfvg9KqXIDL0Jz6VHBOZJfKJ2+tW3TA7celSkRJ6kSZNiQcYDcDFQ8VsWWlTXtnOI2j3YDhcnNQ/8I7ff3aLhZvU8wcEc5zmoxkfSiOR3UYOfYjpSvlerwj/AHiQahSsdLhcXJ9MinAE8bSKjLxDALM2eTscUJLZlmBMzY6c1XOR7Mk2kHJ/nSb1DYLAfjQs9ipyYLh+Om4AURSIXyV8mM/dUdfzpqRDgPSQA+v0UmpxINwCo7E/7NMQqwxluvrVgKhGVwCPfk1VzFxJrSFrudIjMtuDzukG4YHUYHU4zWpcwQvpE4uro3TIpa3HlGMR9+h6fQVyGqa3JayiK1KKg+845Le30+lPt9exJF83lwqSRETnyz6nPUVlON3c66D5YWZo6frVokUhuXfJkIQKpYnHYCtxPIlVZFwNwGAev5V54khg1GS6QOFd2KH+IA/1rWsdYfzAkMxQr/eOcfnVp2RjUpKTuda7xxvtD7j3AU8VS1G5ihiM8pKFOVION3tj+tUU1mNA/wBoctg/Mw4ANV/EDGWwgeAMzSMFBcggg1bd0ZwpWkmW2u5NRt1MaLDbPbHaoYkgHIwxPfvVzQIIX1B47WX5VQlmVCwwvbP9az5rqabSorErChGA8saYYqOgHb1q9HNNY6WtvaM4hdcOsZAyfVj3qIw7nXWnZWsdFEInd/KfIP58VHMhTkng9PeuU0y+m8w+aHEYYqjnP15rfa7haMNPKBnAULklj6AVo0ee0mTajA82mmOJN0jEFfzFayAvasWXJKms2FxuAG4Af3hitITRQWE0s2SioSTnqKl7Cjuefmx+ypeXsuFM37uFO5GeW/wrOeDbGrHuetWJ75tRuyD/AKpSdoHYVNOg+zke1YyVj0Iu5mkgADuOtRs5HQGlmODVWVyD8uQaSLEucNEQBz61NplyBAyt1xVfdlagV/LlO3gHrRYLk90u1x7VDncuKlnbKhvWoEPBFaRRjNkUmVkHPPrV7U4N95uXBSWNZFI6cj/Gs+Vst9K1lkNxZIm3Jh5Uj+6ex/H+dawWpE3azKNjKQxhk5wSwrV0ST94hBG7zAee/NZdzEEljkTKjODVzQbiK2vFe4YBFyeR37VFRFxd9UegmTfI0ydCxHHAq+LrZa72DYHLHHArK06dbzT98cbqC2ACME++Kq6jdTxQvbhgIz1GOfxohdozqWTZe07xbNZX1zJBCrbwAgbIx9SD+lX/APhPdW/552/5H/GuISVvNAzxnnnFWd8fr/49VcqM1UdjBEc24+WQQP7wNI6lhulUBh3Unn86fMziVFU5C89aHB2Z6kjtXMtT0myEyvHEoVCQxPGRmovtJU7dkgPcA1Ngm3+VF3Z4JPNdT9jEWiW8tou2RF3ykKME/XrQ3YEuY5VJJT/y7sT6PJgD8KvQyF1UArvByQOg9qgkP2mQuH3EcsVOcmpvtBaNVkdTIO4AziqRlNFtC6t82AT78VUv9QVYjHGd3PzOOPyqG9u1CfK2dvUmqUFpNeSJ5gMcWc5I5NVcjkW7Ksj+bPyTjOBmruwHLkgACotWVUukCAKFHaoYbhjwcH2an0NIWLMj5gII2kkc1peHbHSpbuSXWZ5lRDsjggO12OMlt3QAdMd8+1Y0s/2iRQwxt6ADg1BKds7EHknNJa6FS01OivtFa6v2GmuBZ5+R5Gzj2x1JFWbuPy4orCElzCnyyMeS+cms/wAOXUhkliVNyKm8sf4K1NMRW1UX10AltAxCqx46ck/nWi0OWd73JLWKafaxTC4+Y56H6d6tWDqXZSFVWJIJbOSOOKz7O8juTdpaSbEEvysR95amWXEnzzPIVxgtgAew9Kq5tVjzU7nQ2thCYpXmjU228OoY8EjufTkVj63qqXN0qRbQ0bhtynI/CtvW4dmm2ltbzxzrNGrP8wXyxwSOP61DFbWYzmzgdm6OUBI/GhO6OKcXB6k93PsgmePPzL2IHb3qxpjfadCmhlYMyxt0cN274rP1P/jykGAxPQbc4+gpfDzm2gn83KRuhwCvLds1LJirq5zWnqjRNhSSOSBwcU+4feMJ29aooxinYA5IJBq4848l8ouWGMkZxWdRWOug7oozr3zVKQ4HTg9DVppD0HNV3AJzUI1ZVY7VJqCc4HBqe4+7j1qm64GKtIm5bjffB9ajVtrkVHBJtyvY06Zi23pwMcDFaWIa1GOcv+NaOnt/pMaM5VJfkYj3HH61mk9KuQkgIR1A/lVw3IqLQtNFucq3fqPQiqVlK8Uu+MKWAP3jxVxrgNPlujdT71U0oF75VMe/r8nrxRVsKlezub+l6/dR3MSySJGNww8Wdy/Q102p22nzgy2d1Pcu43NJMm3B5yMfhXHQiSe6UQxvAewZQAK6i0h36dMk853oC6hfutxzWcWKbMORWRwecelJ5x9KeS8mCc7QOBngUmytLmdjMl+9SCiiuVHoPciX7rfWunP/ACKMv/XM/wA6KKUtkXDqcvpf+rb6Gkb/AI/5voP5UUVXQSK6/wDHzD/v1vt/rfwFFFDMpbGHq3/H1SWvQfWiiq6F0txYf+PmSqkv+uNFFCLqGpon3Zvwrfl/5Azf7slFFHU5pGJ4e/1z/wC8P5VtT/8AHlJ/u0UVoa/YLeh/f/4D/U1tQ/dT6UUVRxyNPTf+PpPqKf4y/wCQyv8A17Ciis5blQ+E8yj/AOPqT61Zb/j1NFFKp0Lomev+sH1qDtRRULc0kV5vv1Xk60UVqjNEaf6ypn+6KKKoct0Rd6uwdV+lFFOIpjJfux/WrOif8hhf94/yoopT2FHYu2P/ACEZvr/Wug0//j1k/wCuJooqY7kS2M+P7p+lFFFWSf/Z" /></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
My Requirement is to send data coming from oracle tables as an excel sheet attachment through mail to the customers. I am able to get the attachment but whatever I write as the body of mail, it goes inside the excel sheet.
Code:
CREATE OR REPLACE PROCEDURE trackekr(cursor1 IN OUT SYS_REFCURSOR)
AS
v_connection UTL_SMTP.connection;
v_smtp VARCHAR2(255):='mail.bbc.com';
v_clob CLOB := EMPTY_CLOB();
v_len INTEGER;
v_index INTEGER;
c_mime_boundary CONSTANT VARCHAR2(256) := 'the boundary can be almost anything';
headerLines CLOB := EMPTY_CLOB();
BEGIN
OPEN cursor1 FOR
SELECT COUNTRY_ID, START_DATE
FROM Table WHERE OBJECT_NAME = 'XYZ';
DBMS_LOB.CreateTemporary( v_clob, true );
headerLines := 'COUNTRY_ID,START_DATE'|| UTL_TCP.crlf; --// create CSV header line
DBMS_LOB.WriteAppend( v_clob, length(headerLines), headerLines ); --// write it to CLOB
--// start loop to add data lines to CSV
FOR cursor1 in
( SELECT COUNTRY_ID, START_DATE
FROM Table WHERE OBJECT_NAME = 'XYZ')
LOOP
v_clob :=
v_clob
|| cursor1.COUNTRY_ID
|| ','
|| cursor1.START_DATE
|| UTL_TCP.crlf;
END LOOP;
-- UTL
v_connection := UTL_SMTP.open_connection(v_smtp, 25);
UTL_SMTP.helo(v_connection, v_smtp);
UTL_SMTP.mail(v_connection, 'abc.singh#yahoo.in');
UTL_SMTP.rcpt(v_connection, 'abc.singh#wbc.com');
UTL_SMTP.open_data(v_connection);
UTL_SMTP.write_data(v_connection, 'From: ' || 'abc.singh#yahoo.in' || UTL_TCP.crlf);
UTL_SMTP.write_data(v_connection, 'To: ' || 'abc.singh#wbc.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);
if DBMS_LOB.IsOpen( v_clob ) = 1 then
DBMS_LOB.FreeTemporary( v_clob );
end if;
UTL_SMTP.close_data(v_connection);
UTL_SMTP.quit(v_connection);
END;
In a multi-part MIME message, body is a "part" by itself and needs it's own boundary.
In your original code, you find these lines:
UTL_SMTP.write_data(
v_connection,
'This is a multi-part message in MIME format.' || UTL_TCP.crlf
);
Just after those lines, you add this bit of code:
-- Body >>>
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);
UTL_SMTP.write_data(v_connection, UTL_TCP.crlf);
UTL_SMTP.write_data(v_connection, 'Hello, this is the body.'||UTL_TCP.crlf);
UTL_SMTP.write_data(v_connection, UTL_TCP.crlf);
-- <<< Body
Don't remove anything from your original code.
That way the body is within it's own boundary part, just like the csv file, but without a Content-Disposition: attachment header.
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;