i make a form i want when i click on button it send email i get a code for email from internet
CREATE OR REPLACE FUNCTION FSC.SEND_MAIL
(pIssuer IN VARCHAR2,
pReceiver IN VARCHAR2,
pSender IN VARCHAR2,
pSubject IN VARCHAR2,
pMessage IN VARCHAR2) RETURN VARCHAR2 IS
c utl_smtp.connection;
respuesta utl_smtp.reply;
pServer VARCHAR2(50) := '192.168.0.6';
BEGIN
-- Open the connection to the mail server
c := utl_smtp.open_connection(pServer);
respuesta := utl_smtp.helo(c, pServer);
-- Start the Issuer mail.
respuesta := utl_smtp.mail(c, pSender);
-- Starts Receiver
respuesta := utl_smtp.rcpt(c, pReceiver);
respuesta := utl_smtp.open_data(c);
-- Enter the email header
utl_smtp.write_data(c, 'From: ' || pIssuer || utl_tcp.CRLF);
utl_smtp.write_data(c, 'To: ' || pReceiver || utl_tcp.CRLF);
-- Enter the Subject
utl_smtp.write_data(c, 'Subject: ' || pSubject || utl_tcp.CRLF);
-- Write the message text.
utl_smtp.write_data(c, utl_tcp.CRLF || pMessage);
utl_smtp.write_data(c, utl_tcp.CRLF || '.');
respuesta := utl_smtp.close_data(c);
-- Close connection
respuesta := utl_smtp.quit(c);
RETURN '0';
EXCEPTION
WHEN utl_smtp.transient_error OR utl_smtp.permanent_error THEN
utl_smtp.quit(c);
RETURN sqlerrm;
--raise_application_error(-20000,
-- 'The sending of the email has failed by returning the following error: ' || sqlerrm);
WHEN OTHERS THEN
RETURN sqlerrm;
END;
/
i make this function in sql it and it was successfully run but when i execute then no email send to my desire address
declare
begin
dbms_output.put_line(SEND_MAIL('usmanafb#ctm.com.pk','usmanafb#ctm.com.pk','usmanafb#ctm.com.pk','Testing','email message'));
end;
i use my local exchange for eamil sending and the ip address of that server is 192.168.0.6
the second issue in this code when i make same function in Oracle 10 g forms then it give me this error
utl_tcp.CRLF is can not directly acces remote package
I use this general procedure to send out mails. It also supports attachment (plain text only) and mails are not limited to 32767 characters.
If you don't need attachments at all, it should be no problem for you to remove it.
PRIORITY_HIGH CONSTANT INTEGER := 1;
PRIORITY_NORMAL CONSTANT INTEGER := 3;
PRIORITY_LOW CONSTANT INTEGER := 5;
PROCEDURE SendMail(
Subject IN VARCHAR2,
Message IN OUT CLOB,
ToMail IN VARCHAR2,
FromMail IN VARCHAR2, FromName IN VARCHAR2,
Attachment IN OUT CLOB, FileName IN VARCHAR2,
Priority IN INTEGER DEFAULT PRIORITY_NORMAL) IS
MIME_BOUNDARY CONSTANT VARCHAR2(50) := '====Multipart.Boundary.689464861147414354====';
MIME_MIXED CONSTANT VARCHAR2(50) := 'multipart/mixed;';
MIME_TEXT CONSTANT VARCHAR2(50) := 'text/plain;';
MIME_HTML CONSTANT VARCHAR2(50) := 'text/html;';
MAIL_HOST CONSTANT VARCHAR2(50) := '192.168.0.6'; -- try also 'mailhost'
con UTL_SMTP.connection;
ret UTL_SMTP.reply;
Charset VARCHAR2(20);
Footer VARCHAR2(1000);
ClobLen PLS_INTEGER;
amount BINARY_INTEGER := 8192;
buffer VARCHAR2(16384);
offset PLS_INTEGER := 1;
isHTML BOOLEAN := REGEXP_LIKE(DBMS_LOB.SUBSTR(Message, 1000, 1), '<(html)|(body)', 'i');
BEGIN
SELECT UTL_I18N.MAP_CHARSET(VALUE)
INTO Charset
FROM V$NLS_PARAMETERS
WHERE PARAMETER = 'NLS_CHARACTERSET';
-- setup mail header
con := UTL_SMTP.OPEN_CONNECTION(MAIL_HOST, 25);
ret := UTL_SMTP.helo(con, SYS_CONTEXT('USERENV', 'DB_DOMAIN')); -- assuming your database is in the same domain as your mail server
ret := UTL_SMTP.Mail(con, FromMail);
ret := UTL_SMTP.rcpt(con, ToMail);
-- simply call "UTL_SMTP.rcpt(con, ...);" again in order to add further recipient
ret := UTL_SMTP.open_data(con);
IF FromName IS NOT NULL THEN
UTL_SMTP.write_data(con, 'From: "'||FromName||'" <'||FromMail||'>'||Utl_Tcp.CRLF);
ELSE
UTL_SMTP.write_data(con, 'From: <'||FromMail||'>'||Utl_Tcp.CRLF);
END IF;
UTL_SMTP.write_data(con, 'To: <'||ToMail||'>'||Utl_Tcp.CRLF);
-- UTL_SMTP.write_data(con, 'Cc: <'||CcMail||'>'||Utl_Tcp.CRLF);
UTL_SMTP.write_data(con, 'Subject: '||Subject||Utl_Tcp.CRLF);
UTL_SMTP.write_data(con, 'X-Priority: '||Priority||Utl_Tcp.CRLF);
IF Attachment IS NOT NULL AND FileName IS NOT NULL THEN
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, 'This is a multipart message in MIME format.' || Utl_Tcp.CRLF);
UTL_SMTP.write_data(con, '--'||MIME_BOUNDARY || Utl_Tcp.CRLF);
END IF;
Footer := 'Message from '||SYS_CONTEXT('USERENV', 'DB_NAME')||' sent at '||TO_CHAR(SYSDATE,'yyyy-mm-dd hh24:mi:ss');
IF isHTML THEN
UTL_SMTP.write_data(con, 'Content-type: '||MIME_HTML||' charset='||Charset || Utl_Tcp.CRLF);
Message := REPLACE(message, '</body>', '<p>'||Footer||'</p></body>');
ELSE
UTL_SMTP.write_data(con, 'Content-type: '||MIME_TEXT||' charset='||Charset || Utl_Tcp.CRLF);
END IF;
-- Mail Body
UTL_SMTP.write_data(con, Utl_Tcp.CRLF);
ClobLen := DBMS_LOB.GETLENGTH(Message);
LOOP
EXIT WHEN offset > ClobLen;
DBMS_LOB.READ(Message, 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);
IF NOT isHTML THEN
UTL_SMTP.write_data(con, Utl_Tcp.CRLF || Utl_Tcp.CRLF);
UTL_SMTP.write_data(con, Footer);
UTL_SMTP.write_data(con, Utl_Tcp.CRLF);
END IF;
IF Attachment IS NOT NULL AND FileName IS NOT NULL THEN
-- 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="'||Filename||'"'|| Utl_Tcp.CRLF);
UTL_SMTP.write_data(con, 'Content-Disposition: attachment; filename="'||Filename||'"'|| Utl_Tcp.CRLF);
UTL_SMTP.write_data(con, Utl_Tcp.CRLF);
offset := 1;
ClobLen := DBMS_LOB.GETLENGTH(Attachment);
LOOP
EXIT WHEN offset > ClobLen;
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);
END IF;
-- finish mail
ret := UTL_SMTP.close_data(con);
ret := UTL_SMTP.quit(con);
EXCEPTION
WHEN UTL_SMTP.TRANSIENT_ERROR OR UTL_SMTP.PERMANENT_ERROR THEN
UTL_SMTP.quit(con);
RAISE;
END SendMail;
Just a note, do not miss the UTL_SMTP.write_data(con, UTL_TCP.CRLF) lines. They are looking redundant, however most of them are required! Also courtesy message like "This is a multipart message in MIME format." is needed for proper display of your mail in case of attachments.
If you still face problems make a dbms_output.put_line(ret.code||': '||ret.text); after each function call on UTL_SMTP.
Here the same procedure but reduced to your needs:
FUNCTION SendMail(
Subject IN VARCHAR2,
Message IN VARCHAR2,
FromMail IN VARCHAR2, FromName IN VARCHAR2,
ToMail IN VARCHAR2) RETURN VARCHAR2 IS
MIME_TEXT CONSTANT VARCHAR2(50) := 'text/plain;';
MIME_HTML CONSTANT VARCHAR2(50) := 'text/html;';
MAIL_HOST CONSTANT VARCHAR2(50) := '192.168.0.6'; -- try also 'mailhost'
con UTL_SMTP.connection;
ret UTL_SMTP.reply;
Charset VARCHAR2(20);
isHTML BOOLEAN := REGEXP_LIKE(DBMS_LOB.SUBSTR(Message, 1000, 1), '<(html)|(body)', 'i');
BEGIN
SELECT UTL_I18N.MAP_CHARSET(VALUE)
INTO Charset
FROM V$NLS_PARAMETERS
WHERE PARAMETER = 'NLS_CHARACTERSET';
-- setup mail header
con := UTL_SMTP.OPEN_CONNECTION(MAIL_HOST, 25);
ret := UTL_SMTP.helo(con, SYS_CONTEXT('USERENV', 'DB_DOMAIN')); -- assuming your database is in the same domain as your mail server
ret := UTL_SMTP.Mail(con, FromMail);
ret := UTL_SMTP.rcpt(con, ToMail);
ret := UTL_SMTP.open_data(con);
UTL_SMTP.write_data(con, 'From: "'||FromName||'" <'||FromMail||'>'||Utl_Tcp.CRLF);
UTL_SMTP.write_data(con, 'To: <'||ToMail||'>'||Utl_Tcp.CRLF);
UTL_SMTP.write_data(con, 'Subject: '||Subject||Utl_Tcp.CRLF);
UTL_SMTP.write_data(con, 'X-Priority: 3'||Utl_Tcp.CRLF);
IF isHTML THEN
UTL_SMTP.write_data(con, 'Content-type: '||MIME_HTML||' charset='||Charset || Utl_Tcp.CRLF);
ELSE
UTL_SMTP.write_data(con, 'Content-type: '||MIME_TEXT||' charset='||Charset || Utl_Tcp.CRLF);
END IF;
-- 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);
-- finish mail
ret := UTL_SMTP.close_data(con);
ret := UTL_SMTP.quit(con);
RETURN '0';
EXCEPTION
WHEN UTL_SMTP.TRANSIENT_ERROR OR UTL_SMTP.PERMANENT_ERROR THEN
UTL_SMTP.quit(con);
RETURN SQLERRM;
END SendMail;
Related
I would like to send one compressed blob data as file attachment(file.zip) to my mail id. Below I have written the code which will compress the blob data i am looking for.
Can this blob data be sent as email attachment from oracle.
declare
var1 blob;
var2 blob;
cursor datacur is
select empdata from emptable;
begin
dbms_lob.createtemporary(var1,true,dbms_lob.call);
dbms_lob.open(var1,dbms_lob.lob_readwrite);
for curvar in datacur
loop
dbms_lob.writeappend(var1,utl_raw.length(utl_raw.cast_to_raw(curvar.empdata)),ut l_raw.cast_to_raw(curvar.empdata));
end loop;
dbms_lob.createtemporary(var2,true,dbms_lob.call);
dbms_lob.open(var2,dbms_lob.lob_readwrite);
utl_compress.lz_compress(var1,var2,6);
dbms_lob.close(var1);
dbms_lob.freetemporary(var1);
dbms_lob.freetemporary(var2);
exception
when others then
dbms_output.put_line('error '||sqlcode||sqlerrm);
end;
Try this one (not tested):
PRIORITY_HIGH CONSTANT INTEGER := 1;
PRIORITY_NORMAL CONSTANT INTEGER := 3;
PRIORITY_LOW CONSTANT INTEGER := 5;
PROCEDURE SendMail(
Subject IN VARCHAR2,
Message IN CLOB,
ToMail IN VARCHAR2,
FromMail IN VARCHAR2, FromName IN VARCHAR2,
Attachment IN BLOB, FileName IN VARCHAR2,
Priority IN INTEGER DEFAULT PRIORITY_NORMAL) IS
MIME_BOUNDARY CONSTANT VARCHAR2(50) := '====Multipart.Boundary.689464861147414354====';
MIME_MIXED CONSTANT VARCHAR2(50) := 'multipart/mixed;';
MIME_TEXT CONSTANT VARCHAR2(50) := 'text/plain;';
MIME_HTML CONSTANT VARCHAR2(50) := 'text/html;';
MAIL_HOST CONSTANT VARCHAR2(50) := 'mailhost';
con UTL_SMTP.connection;
ret UTL_SMTP.reply;
Charset VARCHAR2(20);
Footer VARCHAR2(1000);
LobLen PLS_INTEGER;
amount BINARY_INTEGER := 4800;
buffer VARCHAR2(19600);
buffer_raw RAW(4800);
offset PLS_INTEGER := 1;
isHTML BOOLEAN := REGEXP_LIKE(DBMS_LOB.SUBSTR(Message, 1000, 1), '<(html)|(body)', 'i');
BEGIN
SELECT UTL_I18N.MAP_CHARSET(VALUE)
INTO Charset
FROM V$NLS_PARAMETERS
WHERE PARAMETER = 'NLS_CHARACTERSET';
-- setup mail header
con := UTL_SMTP.OPEN_CONNECTION(MAIL_HOST, 25);
ret := UTL_SMTP.helo(con, SYS_CONTEXT('USERENV', 'DB_DOMAIN')); -- assuming your database is in the same domain as your mail server
ret := UTL_SMTP.Mail(con, FromMail);
ret := UTL_SMTP.rcpt(con, ToMail);
-- simply call "UTL_SMTP.rcpt(con, ...);" again in order to add further recipient
ret := UTL_SMTP.open_data(con);
IF FromName IS NOT NULL THEN
UTL_SMTP.write_data(con, 'From: "'||FromName||'" <'||FromMail||'>'||Utl_Tcp.CRLF);
ELSE
UTL_SMTP.write_data(con, 'From: <'||FromMail||'>'||Utl_Tcp.CRLF);
END IF;
UTL_SMTP.write_data(con, 'To: <'||ToMail||'>'||Utl_Tcp.CRLF);
-- UTL_SMTP.write_data(con, 'Cc: <'||CcMail||'>'||Utl_Tcp.CRLF);
UTL_SMTP.write_data(con, 'Subject: '||Subject||Utl_Tcp.CRLF);
UTL_SMTP.write_data(con, 'X-Priority: '||Priority||Utl_Tcp.CRLF);
IF Attachment IS NOT NULL AND FileName IS NOT NULL THEN
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, 'This is a multipart message in MIME format.' || Utl_Tcp.CRLF);
UTL_SMTP.write_data(con, '--'||MIME_BOUNDARY || Utl_Tcp.CRLF);
END IF;
Footer := 'Message from '||SYS_CONTEXT('USERENV', 'DB_NAME')||' sent at '||TO_CHAR(SYSDATE,'yyyy-mm-dd hh24:mi:ss');
IF isHTML THEN
UTL_SMTP.write_data(con, 'Content-type: '||MIME_HTML||' charset='||Charset || Utl_Tcp.CRLF);
Message := REPLACE(message, '</body>', '<p>'||Footer||'</p></body>');
ELSE
UTL_SMTP.write_data(con, 'Content-type: '||MIME_TEXT||' charset='||Charset || Utl_Tcp.CRLF);
END IF;
-- Mail Body
UTL_SMTP.write_data(con, Utl_Tcp.CRLF);
LobLen := DBMS_LOB.GETLENGTH(Message);
LOOP
EXIT WHEN offset > ClobLen;
DBMS_LOB.READ(Message, 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);
IF NOT isHTML THEN
UTL_SMTP.write_data(con, Utl_Tcp.CRLF || Utl_Tcp.CRLF);
UTL_SMTP.write_data(con, Footer);
UTL_SMTP.write_data(con, Utl_Tcp.CRLF);
END IF;
IF Attachment IS NOT NULL AND FileName IS NOT NULL THEN
-- 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="'||Filename||'"'|| Utl_Tcp.CRLF);
UTL_SMTP.write_data(con, 'Content-Transfer-Encoding: base64' || Utl_Tcp.CRLF);
UTL_SMTP.write_data(con, 'Content-Disposition: attachment; filename="'||Filename||'"'|| Utl_Tcp.CRLF);
UTL_SMTP.write_data(con, Utl_Tcp.CRLF);
offset := 1;
LobLen := DBMS_LOB.GETLENGTH(Attachment);
LOOP
EXIT WHEN offset > LobLen;
DBMS_LOB.READ(Attachment, amount, offset, buffer_raw);
UTL_SMTP.write_raw_data(con, utl_encode.base64_encode(buffer_raw));
offset := offset + amount;
END LOOP;
UTL_SMTP.write_data(con, Utl_Tcp.CRLF);
UTL_SMTP.write_data(con, '--'||MIME_BOUNDARY||'--' || Utl_Tcp.CRLF);
END IF;
-- finish mail
ret := UTL_SMTP.close_data(con);
ret := UTL_SMTP.quit(con);
EXCEPTION
WHEN UTL_SMTP.TRANSIENT_ERROR OR UTL_SMTP.PERMANENT_ERROR THEN
UTL_SMTP.quit(con);
RAISE;
END SendMail;
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;
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
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.