Utl_encode.text_encode - QUOTED_PRINTABLE
Hi.
I´m using utl_encode.text_encode to format e-mails that I need to send in my program.
QUOTED_PRINTABLE := 2;
wresult := utl_encode.text_encode(nvl(wline, ' '), 'WE8ISO8859P1', QUOTED_PRINTABLE);The problem is that when last char of the line is a dot (.), text_encode, is removing it.
Example:
Text to Encode:
<p>Para entrar no sistema, acesse o site: <a href="http://satir-app.intra.tilibra.com.br:7780/pls/adpi/satidpi.abertura" target="_blank">satir-app.intra.tilibra.com.br</a><br />Text Encoded by utl_encode.text_encode:
<p>Para entrar no sistema, acesse o site: <a href=3D"http://satir-app.intra=
tilibra.com.br:7780/pls/adpi/satidpi.abertura" target=3D"_blank">satir-app=
intra.tilibra.com.br</a><br />Note that the url http://satir-app.intra.tilibra.com.br:7780/pls/adpi/satidpi.abertura becames http://satir-appintra.tilibra.com.br:7780/pls/adpi/satidpi.abertura without a dot between intra and tilibra
and the text of url satir-app.intra.tilibra.com.br becames satir-appintra.tilibra.com.br without a dot between app and intra
There is a way to solve this?
Edited by: mcardia on 11/03/2011 06:43
Sorry to bother...
I solve it myself.
The problem was not with the dot at end of line, but with the dot at begin of line.
Mail servers ignores dots at begin of line, so when the e-mail was sent, they look like I wrote before.
To solve, I did this:
QUOTED_PRINTABLE := 2;
wresult := utl_encode.text_encode(nvl(wline, ' '), 'WE8ISO8859P1', QUOTED_PRINTABLE);
wresult := regexp_replace(wresult , '^\.', '..', 1, 0, 'im');Replacing lines that begins with a dot with two dots is the solution.
Similar Messages
-
How to use stored package in form.
hi
i created the following package but now i want to use the following code in form
how could i use?.
create or replace package body mahi
is
-- Write a MIME header
procedure write_mime_header (
p_conn in out nocopy utl_smtp.connection
, p_name in varchar2
, p_value in varchar2
is
begin
utl_smtp.write_data ( p_conn
, p_name || ': ' || p_value || utl_tcp.crlf
end;
procedure mail (
p_sender in varchar2
, p_recipient in varchar2
, p_subject in varchar2
, p_message in varchar2
is
v_nls_charset VARCHAR2(50);
/*LOB operation related varriables */
v_src_loc BFILE := BFILENAME('BACKUP', 'Logon.jpg');
l_buffer RAW(54);
l_amount BINARY_INTEGER := 54;
l_pos INTEGER := 1;
l_blob BLOB := EMPTY_BLOB;
l_blob_len INTEGER;
v_amount INTEGER;
/*UTL_SMTP related varriavles. */
v_connection_handle UTL_SMTP.CONNECTION;
v_from_email_address VARCHAR2(30) := [email protected]';
v_to_email_address VARCHAR2(30) := '[email protected]';
I have used stunnel to send mail using smtp.gmail.com
To get stunnel see http://stunnel.org/.
The ORIGINAL idea is here :
http://monkeyonoracle.blogspot.com/2009/11/plsql-and-gmail-or-utlsmtp-with-ssl.html
v_smtp_host VARCHAR2(30) := 'localhost.localdomain';
v_subject VARCHAR2(30) := 'Your Test Mail';
l_message VARCHAR2(200) := 'This is test mail using UTL_SMTP';
/* This send_header procedure is written in the documentation */
PROCEDURE send_header(pi_name IN VARCHAR2, pi_header IN VARCHAR2) AS
BEGIN
UTL_SMTP.WRITE_DATA(v_connection_handle,
pi_name || ': ' || pi_header || UTL_TCP.CRLF);
END;
BEGIN
SELECT value
INTO v_nls_charset
FROM nls_database_parameters
WHERE parameter = 'NLS_CHARACTERSET';
/*Preparing the LOB from file for attachment. */
DBMS_LOB.OPEN(v_src_loc, DBMS_LOB.LOB_READONLY); --Read the file
DBMS_LOB.CREATETEMPORARY(l_blob, TRUE); --Create temporary LOB to store the file.
v_amount := DBMS_LOB.GETLENGTH(v_src_loc); --Amount to store.
DBMS_LOB.LOADFROMFILE(l_blob, v_src_loc, v_amount); -- Loading from file into temporary LOB
l_blob_len := DBMS_LOB.getlength(l_blob);
/*UTL_SMTP related coding. */
v_connection_handle := UTL_SMTP.OPEN_CONNECTION(host => v_smtp_host,
port => 1925);
UTL_SMTP.EHLO(v_connection_handle, 'gmail.com');
UTL_SMTP.COMMAND(v_connection_handle, 'auth login');
UTL_SMTP.COMMAND(v_connection_handle,
UTL_ENCODE.TEXT_ENCODE('[email protected]',
v_nls_charset,
1));
UTL_SMTP.COMMAND(v_connection_handle,
UTL_ENCODE.TEXT_ENCODE('xxxxx', v_nls_charset, 1));
--UTL_SMTP.MAIL(v_connection_handle, v_from_email_address);
--UTL_SMTP.RCPT(v_connection_handle, v_to_email_address);
UTL_SMTP.COMMAND(v_connection_handle,
'MAIL FROM: <'>');
UTL_SMTP.COMMAND(v_connection_handle,
'RCPT TO: <'>');
UTL_SMTP.OPEN_DATA(v_connection_handle);
send_header('From', '"Sender" <'>');
send_header('To', '"Recipient" <'>');
send_header('Subject', v_subject);
--MIME header.
UTL_SMTP.WRITE_DATA(v_connection_handle,
'MIME-Version: 1.0' || UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(v_connection_handle,
'Content-Type: multipart/mixed; ' || UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(v_connection_handle,
' boundary= "' || 'BACKUP.SECBOUND' || '"' ||
UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(v_connection_handle, UTL_TCP.CRLF);
-- Mail Body
UTL_SMTP.WRITE_DATA(v_connection_handle,
'--' || 'BACKUP.SECBOUND' || UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(v_connection_handle,
'Content-Type: text/plain;' || UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(v_connection_handle,
' charset=US-ASCII' || UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(v_connection_handle, UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(v_connection_handle, l_message || UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(v_connection_handle, UTL_TCP.CRLF);
-- Mail Attachment
UTL_SMTP.WRITE_DATA(v_connection_handle,
'--' || 'BACKUP.SECBOUND' || UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(v_connection_handle,
'Content-Type: application/octet-stream' ||
UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(v_connection_handle,
'Content-Disposition: attachment; ' || UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(v_connection_handle,
' filename="' || 'Logon.jpg' || '"' || --My filename
UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(v_connection_handle,
'Content-Transfer-Encoding: base64' || UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(v_connection_handle, UTL_TCP.CRLF);
/* Writing the BLOL in chunks */
WHILE l_pos < l_blob_len LOOP
DBMS_LOB.READ(l_blob, l_amount, l_pos, l_buffer);
UTL_SMTP.write_raw_data(v_connection_handle,
UTL_ENCODE.BASE64_ENCODE(l_buffer));
UTL_SMTP.WRITE_DATA(v_connection_handle, UTL_TCP.CRLF);
l_buffer := NULL;
l_pos := l_pos + l_amount;
END LOOP;
UTL_SMTP.WRITE_DATA(v_connection_handle, UTL_TCP.CRLF);
-- Close Email
UTL_SMTP.WRITE_DATA(v_connection_handle,
'--' || 'BACKUP.SECBOUND' || '--' || UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(v_connection_handle,
UTL_TCP.CRLF || '.' || UTL_TCP.CRLF);
UTL_SMTP.CLOSE_DATA(v_connection_handle);
UTL_SMTP.QUIT(v_connection_handle);
DBMS_LOB.FREETEMPORARY(l_blob);
DBMS_LOB.FILECLOSE(v_src_loc);
EXCEPTION
WHEN OTHERS THEN
UTL_SMTP.QUIT(v_connection_handle);
DBMS_LOB.FREETEMPORARY(l_blob);
DBMS_LOB.FILECLOSE(v_src_loc);
RAISE;
END;
end;
sarah helped me to create the above package but i am not able to use in form
i sent email to her but no reply.hi
mehwish............just do for attachment.......
u can also use something like this...
Execute send_mail;and also.
try something like this..
example:
begin
mahi.mail('email address','subject','message','attachment');
end;Edited by: Sarah on Apr 18, 2011 10:25 AM -
Getting junk letters instead of photo in an email.
hi all
i am trying to send an email via gmail.com i am able to send an email but when i try to
send attachment so i am getting strange texts instead of photo
its not displaying photo but there is different format text is displaying in my box.
here is the result.
also getting this error but i am able to send email.
ERROR at line 1:
ORA-20000: Failed to send mail due to the
following error: ORA-29277: invalid SMTP operation
ORA-06512: at "MAIL.MAHI", line 159
ORA-06512: at line 2===============================================
--BACKUP.SECBOUNDContent-
Type: application/octet-streamContent-Disposition:
attachment; filename="g.gif"Content-Transfer-Encoding: base64
Qk2O5QgAAAAAADYAAAAoAAAAwgIAABMBAAABABgAAAAA
AFjlCAAAAAAAAAAAAAAAAAAAAAAAhNWuhNWuhNWuhNWu
hNWuhNWuhNWuhNWuhNWuhNWuhNWuhNWuhNWuhNWuh
NWuhNWuhNWuhNWuhNWuhNWuhNWuhNWuhNWuhNWuhNW
uhNWuhNWuhNWuhNWuhNWuhNWuhNWuhNWuhNWuhNWuhN
WuhNWuhNWuhNWuhNWuhNWuhNWuhNWuhNWuhNWuhNWuh
NWuhNWuhNWuhNWuhNWuhNWuhNWuhNWuhNWuhNWuhNWu
hNWuhNWuhNWuhNWuhNWuhNWuhNWuhN
WuhNWuhNWuhNWuhNWuhNWuhNWuhNWuhNWuhNWuhNWuh
NWuhNWuhNWuhNWuhNWuhNWuhNWuhNWuhNWuhNWuhNW
uhNWuhNWuhNWuhNWuhNWuhNWuhNWuhNWuhNWuhNWuhN
WuhNWuhNWuhNWuhNWuhNWuhNWuhNWuhNWuhNWuhNWuhNand here the link which is i followed to use with my codes....
Re: Sending UTL_SMTP mail with single jpg attachment issue
create or replace package body Mahi
is
-- Write a MIME header
procedure write_mime_header (
p_conn in out nocopy utl_smtp.connection
, p_name in varchar2
, p_value in varchar2
is
begin
utl_smtp.write_data ( p_conn
, p_name || ': ' || p_value || utl_tcp.crlf
end;
procedure mail (
p_sender in varchar2
, p_recipient in varchar2
, p_subject in varchar2
, p_message in varchar2
is
l_conn utl_smtp.connection;
nls_charset varchar2(255);
v_src_loc BFILE := BFILENAME('BACKUP', 'Logon.jpg');
--v_src_loc BLOB;
l_buffer RAW(54);
l_amount BINARY_INTEGER := 54;
l_pos INTEGER := 1;
l_blob BLOB := EMPTY_BLOB;
l_blob_len INTEGER;
v_amount INTEGER;
v_fname VARCHAR2(50);
CURSOR img_cur IS SELECT photo_name,photo
FROM temp_photo;
--crlf varchar2(2) := chr(10)||chr(13);
PROCEDURE send_header(pi_name IN VARCHAR2, pi_header IN VARCHAR2) AS
BEGIN
UTL_SMTP.WRITE_DATA(l_conn,
pi_name || ': ' || pi_header || UTL_TCP.CRLF);
END;
begin
-- get characterset
select value
into nls_charset
from nls_database_parameters
where parameter = 'NLS_CHARACTERSET';
select
photo into v_src_loc from
temp_photo
where id=1;
DBMS_LOB.OPEN(v_src_loc, DBMS_LOB.LOB_READONLY); --Read the file
DBMS_LOB.CREATETEMPORARY(l_blob, TRUE); --Create temporary LOB to store the file.
v_amount := DBMS_LOB.GETLENGTH(v_src_loc); --Amount to store.
DBMS_LOB.LOADFROMFILE(l_blob, v_src_loc, v_amount); -- Loading from file into temporary LOB
--DBMS_LOB.COPY(l_blob, v_src_loc, v_amount);
l_blob_len := DBMS_LOB.getlength(l_blob);
-- establish connection and autheticate
l_conn := utl_smtp.open_connection (g_smtp_host, g_smtp_port);
utl_smtp.ehlo(l_conn, g_smtp_domain);
utl_smtp.command(l_conn, 'auth login');
utl_smtp.command(l_conn,utl_encode.text_encode('[email protected]', nls_charset, 1));
utl_smtp.command(l_conn, utl_encode.text_encode('xxxxx', nls_charset, 1));
-- set from/recipient
utl_smtp.command(l_conn, 'MAIL FROM: <'||p_sender||'>');
utl_smtp.command(l_conn, 'RCPT TO: <'||p_recipient||'>');
-- write mime headers
utl_smtp.open_data (l_conn);
write_mime_header (l_conn, 'From', p_sender);
write_mime_header (l_conn, 'To', p_recipient);
write_mime_header (l_conn, 'Subject', p_subject);
write_mime_header (l_conn, 'Content-Type', 'text/plain; charset=us-ascii');
write_mime_header (l_conn, 'X-Mailer', g_mailer_id);
utl_smtp.write_data (l_conn, UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(l_conn,
'MIME-Version: 1.0' || UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(l_conn,
'Content-Type: multipart/mixed; ' || UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(l_conn,
' boundary= "' || 'BACKUP.SECBOUND' || '"' ||
UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(l_conn, UTL_TCP.CRLF);
-- write message body
utl_smtp.write_data (l_conn, p_message);
OPEN img_cur;
LOOP
FETCH img_cur INTO v_fname,l_blob;
end loop;
close img_cur;
UTL_SMTP.WRITE_DATA(l_conn,
'--' || 'BACKUP.SECBOUND' || UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(l_conn,
'Content-Type: text/plain;' || UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(l_conn,
' charset=US-ASCII' || UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(l_conn, UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(l_conn, p_message || UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(l_conn, UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(l_conn,
'--' || 'BACKUP.SECBOUND' || UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(l_conn,
'Content-Type: application/octet-stream' ||
UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(l_conn,
'Content-Disposition: attachment; ' || UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(l_conn,
' filename="' || 'gpg.jpg' || '"' || --My filename
UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(l_conn,
'Content-Transfer-Encoding: base64' || UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(l_conn, UTL_TCP.CRLF);
/* Writing the BLOL in chunks */
WHILE l_pos < l_blob_len LOOP
DBMS_LOB.READ(l_blob, l_amount, l_pos, l_buffer);
UTL_SMTP.write_raw_data(l_conn,
UTL_ENCODE.BASE64_ENCODE(l_buffer));
UTL_SMTP.WRITE_DATA(l_conn, UTL_TCP.CRLF);
l_buffer := NULL;
l_pos := l_pos + l_amount;
END LOOP;
UTL_SMTP.WRITE_DATA(l_conn, UTL_TCP.CRLF);
-- Close Email
UTL_SMTP.WRITE_DATA(l_conn,
'--' || 'BACKUP.SECBOUND' || '--' || UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(l_conn,
UTL_TCP.CRLF || '.' || UTL_TCP.CRLF);
UTL_SMTP.CLOSE_DATA(l_conn);
utl_smtp.close_data (l_conn);
UTL_SMTP.QUIT(l_conn);
DBMS_LOB.FREETEMPORARY(l_blob);
DBMS_LOB.FREETEMPORARY(l_blob);
DBMS_LOB.FILECLOSE(v_src_loc);
-- end connection
utl_smtp.quit (l_conn);
exception
when others
then
begin
utl_smtp.quit(l_conn);
exception
when others then
null;
end;
raise_application_error(-20000,'Failed to send mail due to the
following error: ' || sqlerrm);
DBMS_LOB.FREETEMPORARY(l_blob);
DBMS_LOB.FREETEMPORARY(l_blob);
DBMS_LOB.FILECLOSE(v_src_loc);
raise;
end;
end;
commit;Note:- i am using Stunnel,Oracle Database 11g R2 and OS is Linux...
I installed Linux on virtualBox.
please suggest me why i am getting strange text instead of photo?
if my code is wrong plz correct for me..
thanks in advance...
Mehwish
Student.
Edited by: Mehwish on Apr 15, 2011 10:57 PMYour codes are very nice and easy to use but i am unlucky and i am not able to send attachment
before i was not able to send even junk text of photo but after using u r code
i am able to send that and i am near to solve my problem because of your nice guide and codes...
create directory backup as '/u01/dump';
grant read,write on directory backup to mail,scott;
and goes this instead of picture.
Hi Meh --BACKUP.SECBOUNDContent-Type: application/octet-streamContent-Disposition:
attachment; filename="gpg.jpg"Content-Transfer-Encoding: base64 /9j/4AAQ
SkZJRgABAgAAZABkAAD/7AARRHVja3kAAQAEAAAAPgAA/+
4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAQEBgQEBgkGBQYJCgcGBgcKCwkJCg
kJCw8LDAwMDAsPDA0ODg4NDBERExMRERoZGRkaHR0dHR0dHR0dHQEGBwcMCw
wWDw8WGRQQFBkdHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dH
R0dHR0dHR0dHR0dHR0d/8AAEQgA+wG0AwERAAIRAQMRAf/EAKQAAAICAwEBAQ
AAAAAAAAAAAAECAAMFBgcECAkBAQEAAwEBAQAAAAAAAAAAAAABAgMEBQYHE
AABAwIEAwQGCAMFBgYDAAABAAIDEQQhMRIFQRMGUWEiB3GBoTJCFJGxwVJiI
xUIkjMk0XKCokPh8cJT
and i tried to use this code now.
create or replace package body mahi
is
-- Write a MIME header
procedure write_mime_header (
p_conn in out nocopy utl_smtp.connection
, p_name in varchar2
, p_value in varchar2
is
begin
utl_smtp.write_data ( p_conn
, p_name || ': ' || p_value || utl_tcp.crlf
end;
procedure mail (
p_sender in varchar2
, p_recipient in varchar2
, p_subject in varchar2
, p_message in varchar2
is
l_conn utl_smtp.connection;
nls_charset varchar2(255);
v_src_loc BFILE := BFILENAME('BACKUP', 'Logon.jpg');
--v_src_loc BLOB;
l_buffer RAW(54);
l_amount BINARY_INTEGER := 54;
l_pos INTEGER := 1;
l_blob BLOB := EMPTY_BLOB;
l_blob_len INTEGER;
v_amount INTEGER;
v_fname VARCHAR2(50);
--crlf varchar2(2) := chr(10)||chr(13);
PROCEDURE send_header(pi_name IN VARCHAR2, pi_header IN VARCHAR2) AS
BEGIN
UTL_SMTP.WRITE_DATA(l_conn,
pi_name || ': ' || pi_header || UTL_TCP.CRLF);
END;
begin
-- get characterset
select value
into nls_charset
from nls_database_parameters
where parameter = 'NLS_CHARACTERSET';
select
photo into v_src_loc from
temp_photo
where id=1;
DBMS_LOB.OPEN(v_src_loc, DBMS_LOB.LOB_READONLY); --Read the file
DBMS_LOB.CREATETEMPORARY(l_blob, TRUE); --Create temporary LOB to store the file.
v_amount := DBMS_LOB.GETLENGTH(v_src_loc); --Amount to store.
DBMS_LOB.LOADFROMFILE(l_blob, v_src_loc, v_amount); -- Loading from file into temporary LOB
--DBMS_LOB.COPY(l_blob, v_src_loc, v_amount);
l_blob_len := DBMS_LOB.getlength(l_blob);
-- establish connection and autheticate
l_conn := utl_smtp.open_connection (g_smtp_host, g_smtp_port);
utl_smtp.ehlo(l_conn, g_smtp_domain);
utl_smtp.command(l_conn, 'auth login');
utl_smtp.command(l_conn,utl_encode.text_encode('[email protected]', nls_charset, 1));
utl_smtp.command(l_conn, utl_encode.text_encode('xxxxx', nls_charset, 1));
-- set from/recipient
utl_smtp.command(l_conn, 'MAIL FROM: <'||p_sender||'>');
utl_smtp.command(l_conn, 'RCPT TO: <'||p_recipient||'>');
-- write mime headers
utl_smtp.open_data (l_conn);
write_mime_header (l_conn, 'From', p_sender);
write_mime_header (l_conn, 'To', p_recipient);
write_mime_header (l_conn, 'Subject', p_subject);
write_mime_header (l_conn, 'Content-Type', 'text/plain; charset=us-ascii');
write_mime_header (l_conn, 'X-Mailer', g_mailer_id);
utl_smtp.write_data (l_conn, UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(l_conn,
'MIME-Version: 1.0' || UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(l_conn,
'Content-Type: multipart/mixed; ' || UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(l_conn,
' boundary= "' || 'BACKUP.SECBOUND' || '"' ||
UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(l_conn, UTL_TCP.CRLF);
-- write message body
utl_smtp.write_data (l_conn, p_message);
UTL_SMTP.WRITE_DATA(l_conn,
'--' || 'BACKUP.SECBOUND' || UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(l_conn,
'Content-Type: text/plain;' || UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(l_conn,
' charset=US-ASCII' || UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(l_conn, UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(l_conn, p_message || UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(l_conn, UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(l_conn,
'--' || 'BACKUP.SECBOUND' || UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(l_conn,
'Content-Type: application/octet-stream' ||
UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(l_conn,
'Content-Disposition: attachment; ' || UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(l_conn,
' filename="' || 'gpg.jpg' || '"' || --My filename
UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(l_conn,
'Content-Transfer-Encoding: base64' || UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(l_conn, UTL_TCP.CRLF);
/* Writing the BLOL in chunks */
WHILE l_pos < l_blob_len LOOP
DBMS_LOB.READ(l_blob, l_amount, l_pos, l_buffer);
UTL_SMTP.write_raw_data(l_conn,
UTL_ENCODE.BASE64_ENCODE(l_buffer));
UTL_SMTP.WRITE_DATA(l_conn, UTL_TCP.CRLF);
l_buffer := NULL;
l_pos := l_pos + l_amount;
END LOOP;
UTL_SMTP.WRITE_DATA(l_conn, UTL_TCP.CRLF);
-- Close Email
UTL_SMTP.WRITE_DATA(l_conn,
'--' || 'BACKUP.SECBOUND' || '--' || UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(l_conn,
UTL_TCP.CRLF || '.' || UTL_TCP.CRLF);
UTL_SMTP.CLOSE_DATA(l_conn);
utl_smtp.close_data (l_conn);
UTL_SMTP.QUIT(l_conn);
DBMS_LOB.FREETEMPORARY(l_blob);
DBMS_LOB.FREETEMPORARY(l_blob);
DBMS_LOB.FILECLOSE(v_src_loc);
-- end connection
utl_smtp.quit (l_conn);
exception
when others
then
begin
utl_smtp.quit(l_conn);
exception
when others then
null;
end;
raise_application_error(-20000,'Failed to send mail due to the
following error: ' || sqlerrm);
DBMS_LOB.FREETEMPORARY(l_blob);
DBMS_LOB.FREETEMPORARY(l_blob);
DBMS_LOB.FILECLOSE(v_src_loc);
raise;
end;
end;
Note:- i m using stunnel and sending email via gmail and my OS is linux and oracle database 11g R2.
i posted already in my previous post.
is tthere any format problem?
and also i am getting this error but i am able to send email which is getting properly in inbox.
ERROR at line 1:
ORA-20000: Failed to send mail due to the
following error: ORA-29277: invalid SMTP operation
ORA-06512: at "MAIL.Mahi", line 151
ORA-06512: at line 2 -
Excel attachment by utl_smtp
I am using Oracle 11g db , os: windows xp 32 bit.
I am trying to send email with excel attachment .I have installed stunnel.
telnet localhost 1925 is working.
create or replace
PROCEDURE send_mail_not
IS
v_mailconn UTL_SMTP.connection;
v_err VARCHAR2 (1000);
v_message VARCHAR2 (3000);
crlf VARCHAR2 (2) := CHR (13) || CHR (10);
v_attachment VARCHAR2 (200);
p_from_mail_id VARCHAR2 (200);
p_to_mail_id VARCHAR2 (200);
p_subject VARCHAR2 (200);
nls_charset varchar2(255);
BEGIN
select value
into nls_charset
from nls_database_parameters
where parameter = 'NLS_CHARACTERSET';
p_from_mail_id := '[email protected]';
p_to_mail_id := '[email protected]';
p_subject := 'error msg';
v_attachment := 'EXCEL ATTACHMENT';
v_mailconn := UTL_SMTP.open_connection ('localhost', 1925);
UTL_SMTP.helo (v_mailconn, 'localhost');
UTL_SMTP.mail (v_mailconn, '[email protected]');
utl_smtp.command(V_mailconn, 'auth login');
utl_smtp.command(v_mailconn,utl_encode.text_encode('[email protected]', nls_charset, 1));
utl_smtp.command(v_mailconn, utl_encode.text_encode('******', nls_charset, 1));
UTL_SMTP.rcpt (v_mailconn, '[email protected]');
v_message := 'dfdfjkdflkdmf';
DBMS_OUTPUT.put_line ('Inside email procedure');
v_message :=
'Date: '
|| TO_CHAR (SYSDATE, 'dd Mon yy hh24:mi:ss')
|| crlf
|| 'From: '
|| p_from_mail_id
|| crlf
|| 'Subject: '
|| p_subject
|| crlf
|| 'To: '
|| p_to_mail_id
|| crlf
|| 'Mime-version: 1.0'
|| UTL_TCP.crlf
|| -- use Mime mail standard
'Content-type: multipart/mixed;'
|| UTL_TCP.crlf
|| 'boundary="-----SECBOUND"'
|| UTL_TCP.crlf
|| '-------SECBOUND'
|| UTL_TCP.crlf
|| 'Content-Type: text/html;'
|| UTL_TCP.crlf
|| 'Content-Transfer_Encoding: 8bit'
|| UTL_TCP.crlf
|| UTL_TCP.crlf
|| v_message
|| UTL_TCP.crlf
|| -- message body
UTL_TCP.crlf
|| UTL_TCP.crlf
|| '-------SECBOUND'
|| UTL_TCP.crlf
|| 'Content-Type: text/plain;'
|| UTL_TCP.crlf
|| ' name="excel.log"'
|| UTL_TCP.crlf
|| -- file name that will hold the attached text
'Content-Transfer_Encoding: 8bit'
|| UTL_TCP.crlf
|| 'Content-Disposition: attachment;'
|| UTL_TCP.crlf
|| ' filename="sampleexcel.xls"'
|| UTL_TCP.crlf
|| UTL_TCP.crlf
|| v_attachment
|| UTL_TCP.crlf
|| -- attachment
UTL_TCP.crlf
|| '-------SECBOUND--' -- end mime mail
UTL_SMTP.write_data (v_mailconn, v_message);
UTL_SMTP.close_data (v_mailconn);
UTL_SMTP.quit (v_mailconn);
DBMS_OUTPUT.put_line ('v_message');
EXCEPTION
WHEN OTHERS
THEN
v_err := SQLERRM;
DBMS_OUTPUT.PUT_LINE(V_ERR);
END send_mail_not;
when I am calling the subprogram it showing me error:
ORA-29279: SMTP permanent error: 530 5.5.1 http://support.google.com/mail/bin/answer.py?answer=14257 pa1sm62366791pac.17 - gsmtp
plz helpSee the code examples that are posted on OTN recently at
http://otn.oracle.com/sample_code/tech/pl_sql/htdocs/Utl_Smtp_Sam
ple.html. -
What is the default encoding file format for oracle database.
Hello,
I wanted to create all files in ANSI format irrespective of database characterset. is there any way to confirm?
please help me out.Hello,
AS per my knowledge, UTL_FILE expects that files opened by UTL_FILE.FOPEN in text mode are encoded in the database character set And files opened by UTL_FILE.FOPEN_NCHAR in text mode are encoded in the UTF8 character set. However there is not any parameter to set default encoding format for file. It works as mentioned above.
Encoding mode is depend on database character set. If you want to change it while reading/writing file then you can use utl_encode.text_encode/ utl_encode.text_decode/ UTL_RAW.CONVERT function.
When data encoded in one character set is read and Globalization Support is told (such as by means of NLS_LANG) that it is encoded in another character set, the result is indeterminate. If NLS_LANG is set, it should therefore be the same as the database character set..
I wanted to create file using UTL_FILE. and whatever files gets create that should be in ANSI format.
Database version : 11.2.0.1
Edited by: Sachin.Ichake on Oct 3, 2012 11:12 PM -
Using UTL_ENCODE in on-logon
i have this call in the forms on-logon trigger and it does not seem to work my applet fails to open and i get a frm-92101
pswd_decoded := UTL_ENCODE.TEXT_DECODE(P_O_PASSWORD,'WE8ISO8859P1',1);
can we use UTL_ENCODE in forms or is there another way to decode 64 bit strings...
This call works in pl/sql developper
and on forms client base run but not on /forms/frmservlet?i solved it using Text_io to write and read the pass
and host command HOST('/usr/bin/openssl enc -d -base64 -in tmpin.txt -out tmpout.txt, NO_SCREEN)
since what i wanted to do is get a users pass before logon from a php session and since i wasnt connected to a any BD i had to use server functions -
Using utl_encode.base64_encode within decode function
Hi, I want to use utl_encode.base64_encode within decode function. However, the result is not as expected.
select 'a', decode('a', '1', 'EQUAL to 1',
--'NOT EQUAL to 1'
utl_encode.base64_encode('a')
) result
from dual
A RESULT
a 43673D3D
43673D3D is not a base64 encoded value of a
What is wrong with the sql?
ThanksSQL> select 'a'
2 , utl_encode.base64_encode(utl_raw.cast_to_raw('a')) raw_result
3 , utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw('a'))) string_result
4 from dual;
' RAW_RESULT STRING_RESULT
a 59513D3D YQ==
1 row selected.Keep in mind that utl_encode.base64_encode returns a RAW and needs RAW input.
You'll probably need UTL_RAW to get your desired result.
http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14258/u_encode.htm#CACECFHF -
Webutil.Pll requires packaged code Webutil_Db.
Webutil_Db requires Utl_Encode.Base64_Decode.
Utl_Encode.Base64_Decode is not avail on Oracle8.1.7.2.0.
There is a workaround, because I found it, tested it worked, and then promptly lost it again !!!
Any ideas please ???Only a couple of functions in webutil.pll make use of this package, so if you don't use those functions, you don't need the webutil_db package. This means you don't have to install the package.
Do not forget to alter the webutil.pll put some exceptions where it calls the webutil_db packages.
It's dirrrty, but it works for me ;) -
How to export UTL_ENCODE package body in Oracle9i?
I want to export UTL_ENCODE package and import it into Oracle8.1.6. Because its package body is wrapped, I can't copy and paste the code. Is there any other way to export the package? thanks for your replying.
Wrapped source compiles just as plain text does. However, it is not backwards compatible. So if the UTL_ENCODE was wrapped with the 9.0.1 wrap binary then the 8.1.6 database won't understand the wrapped source. You can go forward though.
Even if you had plain text source - it isn't generally a good idea to move Oracle Builtins to a backward version.
Two workarounds:
1) roll your own - as it isn't a tremendously complicated package.
2) If your 8.1.6 database shares a network with a 9i database, use a database link to get at the functionality you need.
Michael O'Neill
Publisher of the PigiWiki
clever-idea.com -
Utl_encode.base64_encode
I must pass raw type to base 64, with this code I get error, can you help me to obtain the fine value?
declare
entrada raw (32000) := '÷8 ²÷÷?/ï?+vNoUJóé¹$';
devuelve raw(32000);
begin
devuelve := utl_encode.base64_encode(entrada);
dbms_output.put_line('devuelve '||devuelve);
end;
thanks
amparodeclare
entrada raw (32000) :=
utl_raw.cast_to_raw('÷8 ²÷÷?/ï?+vNoUJóé¹$'); -
UTL_ENCODE.BASE64_ENCODE for null
hi all
how work with UTL_ENCODE.BASE64_ENCODE and null values ?
SQL> select * from scott.emp;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
7369 SMITH CLERK 7902 17.12.1980 800,00 20
7499 ALLEN SALESMAN 7698 20.02.1981 1600,00 300,00 30
7521 WARD SALESMAN 7698 22.02.1981 1250,00 500,00 30
7566 JONES MANAGER 7839 02.04.1981 2975,00 20
7654 MARTIN SALESMAN 7698 28.09.1981 1250,00 1400,00 30
7698 BLAKE MANAGER 7839 01.05.1981 2850,00 30
7782 CLARK MANAGER 7839 09.06.1981 2450,00 10
7788 SCOTT ANALYST 7566 09.12.1982 3000,00 20
7839 KING PRESIDENT 17.11.1981 5000,00 10
7844 TURNER SALESMAN 7698 08.09.1981 1500,00 0,00 30
7876 ADAMS CLERK 7788 12.01.1983 1100,00 20
7900 JAMES CLERK 7698 03.12.1981 950,00 30
7902 FORD ANALYST 7566 03.12.1981 3000,00 20
7934 MILLER CLERK 7782 23.01.1982 1300,00 10
14 rows selected
SQL> -- look at mgr is not null
SQL> select utl_encode.base64_encode(utl_raw.cast_to_raw(mgr)) from scott.emp where mgr is not null;
UTL_ENCODE.BASE64_ENCODE(UTL_R
4E7A6B774D673D3D
4E7A59354F413D3D
4E7A59354F413D3D
4E7A677A4F513D3D
4E7A59354F413D3D
4E7A677A4F513D3D
4E7A677A4F513D3D
4E7A55324E673D3D
4E7A59354F413D3D
4E7A63344F413D3D
4E7A59354F413D3D
4E7A55324E673D3D
4E7A63344D673D3D
13 rows selected
SQL> select utl_encode.base64_encode(utl_raw.cast_to_raw(mgr)) from scott.emp where mgr is null;
select utl_encode.base64_encode(utl_raw.cast_to_raw(mgr)) from scott.emp where mgr is null
ORA-29261: bad argument
ORA-06512: at "SYS.UTL_ENCODE", line 8
ORA-06512: at "SYS.UTL_ENCODE", line 243
SQL> select utl_raw.cast_to_raw(null) from dual;
UTL_RAW.CAST_TO_RAW(NULL)
SQL> select utl_encode.base64_encode(utl_raw.cast_to_raw(null)) from dual;
select utl_encode.base64_encode(utl_raw.cast_to_raw(null)) from dual
ORA-29261: bad argument
ORA-06512: at "SYS.UTL_ENCODE", line 8
ORA-06512: at "SYS.UTL_ENCODE", line 243
SQL> select * from v$version where rownum=1;
BANNER
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
SQL> say i have table emp and i want to encode each row/column
query
select utl_encode.base64_encode(utl_raw.cast_to_raw(ename)), utl_encode.base64_encode(utl_raw.cast_to_raw(empno)) from scott.empwill be work
but
select utl_encode.base64_encode(utl_raw.cast_to_raw(ename)), utl_encode.base64_encode(utl_raw.cast_to_raw(mgr)) from scott.empno
i saw http://docs.oracle.com/cd/E11882_01/appdev.112/e25788/u_encode.htm#ARPLS70869
but :(
so which ways exists for work with null values in this case?why result of "select utl_encode.base64_encode(null) from dual" is not null but it's error?Sorry can't give an answer, but I think there are more mysteries (at least for me) which ask for an answer:
SQL> select * from v$version where rownum = 1
BANNER
Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - Production
1 row selected.
SQL> select utl_encode.base64_encode (utl_raw.cast_to_raw (10)) DEPTNO from dual
union all
select utl_encode.base64_encode (utl_raw.cast_to_raw (deptno)) DEPTNO from dept where deptno = 10
DEPTNO
4D544D54413D
4D54413D
2 rows selected.why we get different results?
SQL> select utl_encode.base64_encode (utl_raw.cast_to_raw (10)) deptno from dept
DEPTNO
4D544D544D544D544D54413D
4D544D544D544D54413D
4D544D544D54413D
4D544D54413D
4D54413D
5 rows selected.Why is part of the result always appended to the previous row? -
Problem with DBMS_LOB.SUBSTR
Hi,
i want to encode a BLOB into BASE64_ENCODE.
Here my PL/SQL function:
FUNCTION encodeBlob2Base64(pBlobIn IN BLOB)
RETURN BLOB
IS
vAmount PLS_INTEGER := 20000;
vBase64Blob BLOB;
vBlobIn BLOB;
vOffset PLS_INTEGER := 1;
BEGIN
vBlobIn := pBlobIn;
dbms_lob.createtemporary(lob_loc => vBase64Blob, CACHE => FALSE);
LOOP
dbms_lob.append(dest_lob => vBase64Blob,
src_lob => utl_encode.base64_encode(r =>
dbms_lob.substr(lob_loc => vBlobIn, amount => vAmount, offset => vOffset)));
vOffset := vOffset + vAmount;
END LOOP;
dbms_lob.freetemporary(lob_loc => vBase64Blob);
RETURN vBase64Blob;
EXCEPTION
WHEN OTHERS THEN
RAISE;
END encodeBlob2Base64;
When i now use my function i get the ORA-29261: bad argument in the statement DBMS_LOB.SUBSTR(lob_loc ...)
Has somebody an idea, what's wrong?
Many thanks in advance.
Regards,
MartinThe reason is that utl_encode returns a raw whereas dbms_lob.append expects either a blob or a clob.
SQL> desc utl_encode;
FUNCTION BASE64_DECODE RETURNS RAW
Argument Name Type In/Out Default?
R RAW IN
FUNCTION BASE64_ENCODE RETURNS RAW
Argument Name Type In/Out Default?
R RAW IN
FUNCTION MIMEHEADER_DECODE RETURNS VARCHAR2
Argument Name Type In/Out Default?
BUF VARCHAR2 IN
FUNCTION MIMEHEADER_ENCODE RETURNS VARCHAR2
Argument Name Type In/Out Default?
BUF VARCHAR2 IN
ENCODE_CHARSET VARCHAR2 IN DEFAULT
ENCODING BINARY_INTEGER IN DEFAULT
FUNCTION QUOTED_PRINTABLE_DECODE RETURNS RAW
Argument Name Type In/Out Default?
R RAW IN
FUNCTION QUOTED_PRINTABLE_ENCODE RETURNS RAW
Argument Name Type In/Out Default?
R RAW IN
FUNCTION TEXT_DECODE RETURNS VARCHAR2
Argument Name Type In/Out Default?
BUF VARCHAR2 IN
ENCODE_CHARSET VARCHAR2 IN DEFAULT
ENCODING BINARY_INTEGER IN DEFAULT
FUNCTION TEXT_ENCODE RETURNS VARCHAR2
Argument Name Type In/Out Default?
BUF VARCHAR2 IN
ENCODE_CHARSET VARCHAR2 IN DEFAULT
ENCODING BINARY_INTEGER IN DEFAULT
FUNCTION UUDECODE RETURNS RAW
Argument Name Type In/Out Default?
R RAW IN
FUNCTION UUENCODE RETURNS RAW
Argument Name Type In/Out Default?
R RAW IN
TYPE BINARY_INTEGER IN DEFAULT
FILENAME VARCHAR2 IN DEFAULT
PERMISSION VARCHAR2 IN DEFAULT
SQL> spool off -
Capture Web Cam image in APEX and Upload into the Database
Overview
By using a flash object, you should be able to interface with a usb web cam connected to the client machine. Their are a couple of open source ones that I know about, but the one I chose to go with is by Taboca Labs and is called CamCanvas. This is released under the MIT license, and it is at version 0.2, so not very mature - but in saying that it seems to do the trick. The next part is to upload a snapshot into the database - in this particular implementation, it is achieved by taking a snapshot, and putting that data into the canvas object. This is a new HTML5 element, so I am not certain what the IE support would be like. Once you have the image into the canvas, you can then use the provided function convertToDataURL() to convert the image into a Base64 encoded string, which you can then use to convert into to a BLOB. There is however one problem with the Base64 string - APEX has a limitation of 32k for and item value, so can't be submitted by normal means, and a workaround (AJAX) has to be implemented.
Part 1. Capturing the Image from the Flash Object into the Canvas element
Set up the Page
Required Files
Download the tarball of the webcam library from: https://github.com/taboca/CamCanvas-API-/tarball/master
Upload the necessary components to your application. (The flash swf file can be got from one of the samples in the Samples folder. In the root of the tarball, there is actually a swf file, but this seems to be a different file than of what is in the samples - so I just stick with the one from the samples)
Page Body
Create a HTML region, and add the following:
<div class="container">
<object id="iembedflash" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"
codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,0,0" width="320" height="240">
<param name="movie" value="#APP_IMAGES#camcanvas.swf" />
<param name="quality" value="high" />
<param name="allowScriptAccess" value="always" />
<embed allowScriptAccess="always" id="embedflash" src="#APP_IMAGES#camcanvas.swf" quality="high" width="320" height="240"
type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" mayscript="true" />
</object>
</div>
<p><a href="javascript:captureToCanvas()">Capture</a></p>
<canvas style="border:1px solid yellow" id="canvas" width="320" height="240"></canvas>That will create the webcam container, and an empty canvas element for the captured image to go into.
Also, have a hidden unprotected page item to store the Base64 code into - I called mine P2_IMAGE_BASE64
HTML Header and Body Attribute
Add the Page HTML Body Attribute as:
onload="init(320,240)"
JavaScript
Add the following in the Function and Global Variable Declarations for the page (mostly taken out of the samples provided)
//Camera relations functions
var gCtx = null;
var gCanvas = null;
var imageData = null;
var ii=0;
var jj=0;
var c=0;
function init(ww,hh){
gCanvas = document.getElementById("canvas");
var w = ww;
var h = hh;
gCanvas.style.width = w + "px";
gCanvas.style.height = h + "px";
gCanvas.width = w;
gCanvas.height = h;
gCtx = gCanvas.getContext("2d");
gCtx.clearRect(0, 0, w, h);
imageData = gCtx.getImageData( 0,0,320,240);
function passLine(stringPixels) {
//a = (intVal >> 24) & 0xff;
var coll = stringPixels.split("-");
for(var i=0;i<320;i++) {
var intVal = parseInt(coll);
r = (intVal >> 16) & 0xff;
g = (intVal >> 8) & 0xff;
b = (intVal ) & 0xff;
imageData.data[c+0]=r;
imageData.data[c+1]=g;
imageData.data[c+2]=b;
imageData.data[c+3]=255;
c+=4;
if(c>=320*240*4) {
c=0;
gCtx.putImageData(imageData, 0,0);
function captureToCanvas() {
flash = document.getElementById("embedflash");
flash.ccCapture();
var canvEle = document.getElementById('canvas');
$s('P2_IMAGE_BASE64', canvEle.toDataURL());//Assumes hidden item name is P2_IMAGE_BASE64
clob_Submit();//this is a part of part (AJAX submit value to a collection) two
}In the footer region of the page (which is just a loading image to show whilst the data is being submitted to the collection [hidden by default]) :<img src="#IMAGE_PREFIX#processing3.gif" id="AjaxLoading"
style="display:none;position:absolute;left:45%;top:45%;padding:10px;border:2px solid black;background:#FFF;" />If you give it a quick test, you should be able to see the webcam feed and capture it into the canvas element by clicking the capture link, in between the two elements - it might through a JS error since the clob_Submit() function does not exist yet.
*Part 2. Upload the image into the Database*
As mentioned in the overview, the main limitation is that APEX can't submit values larger than 32k, which I hope the APEX development team will be fixing this limitation in a future release, the workaround isn't really good from a maintainability perspective.
In the sample applications, there is one that demonstrates saving values to the database that are over 32k, which uses an AJAX technique: see http://www.oracle.com/technetwork/developer-tools/apex/application-express/packaged-apps-090453.html#LARGE.
*Required Files*
From the sample application, there is a script you need to upload, and reference in your page. So you can either install the sample application I linked to, or grab the script from the demonstration I have provided - its called apex_save_large.js.
*Create a New Page*
Create a page to Post the large value to (I created mine as 1000), and create the following process, with the condition that Request = SAVE. (All this is in the sample application for saving large values).declare
l_code clob := empty_clob;
begin
dbms_lob.createtemporary( l_code, false, dbms_lob.SESSION );
for i in 1..wwv_flow.g_f01.count loop
dbms_lob.writeappend(l_code,length(wwv_flow.g_f01(i)),wwv_flow.g_f01(i));
end loop;
apex_collection.create_or_truncate_collection(p_collection_name => wc_pkg_globals.g_base64_collection);
apex_collection.add_member(p_collection_name => wc_pkg_globals.g_base64_collection,p_clob001 => l_code);
htmldb_application.g_unrecoverable_error := TRUE;
end;I also created a package for storing the collection name, which is referred to in the process, for the collection name:create or replace
package
wc_pkg_globals
as
g_base64_collection constant varchar2(40) := 'BASE64_IMAGE';
end wc_pkg_globals;That is all that needs to be done for page 1000. You don't use this for anything else, *so go back to edit the camera page*.
*Modify the Function and Global Variable Declarations* (to be able to submit large values.)
The below again assumes the item that you want to submit has an item name of 'P2_IMAGE_BASE64', the condition of the process on the POST page is request = SAVE, and the post page is page 1000. This has been taken srtaight from the sample application for saving large values.//32K Limit workaround functions
function clob_Submit(){
$x_Show('AjaxLoading')
$a_PostClob('P2_IMAGE_BASE64','SAVE','1000',clob_SubmitReturn);
function clob_SubmitReturn(){
if(p.readyState == 4){
$x_Hide('AjaxLoading');
$x('P2_IMAGE_BASE64').value = '';
}else{return false;}
function doSubmit(r){
$x('P2_IMAGE_BASE64').value = ''
flowSelectAll();
document.wwv_flow.p_request.value = r;
document.wwv_flow.submit();
}Also, reference the script that the above code makes use of, in the page header<script type="text/javascript" src="#WORKSPACE_IMAGES#apex_save_large.js"></script>Assuming the script is located in workspace images, and not associated to a specific app. Other wise reference #APP_IMAGES#
*Set up the table to store the images*CREATE TABLE "WC_SNAPSHOT"
"WC_SNAPSHOT_ID" NUMBER NOT NULL ENABLE,
"BINARY" BLOB,
CONSTRAINT "WC_SNAPSHOT_PK" PRIMARY KEY ("WC_SNAPSHOT_ID")
create sequence seq_wc_snapshot start with 1 increment by 1;
CREATE OR REPLACE TRIGGER "BI_WC_SNAPSHOT" BEFORE
INSERT ON WC_SNAPSHOT FOR EACH ROW BEGIN
SELECT seq_wc_snapshot.nextval INTO :NEW.wc_snapshot_id FROM dual;
END;
Then finally, create a page process to save the image:declare
v_image_input CLOB;
v_image_output BLOB;
v_buffer NUMBER := 64;
v_start_index NUMBER := 1;
v_raw_temp raw(64);
begin
--discard the bit of the string we dont need
select substr(clob001, instr(clob001, ',')+1, length(clob001)) into v_image_input
from apex_collections
where collection_name = wc_pkg_globals.g_base64_collection;
dbms_lob.createtemporary(v_image_output, true);
for i in 1..ceil(dbms_lob.getlength(v_image_input)/v_buffer) loop
v_raw_temp := utl_encode.base64_decode(utl_raw.cast_to_raw(dbms_lob.substr(v_image_input, v_buffer, v_start_index)));
dbms_lob.writeappend(v_image_output, utl_raw.length(v_raw_temp),v_raw_temp);
v_start_index := v_start_index + v_buffer;
end loop;
insert into WC_SNAPSHOT (binary) values (v_image_output); commit;
end;Create a save button - add some sort of validation to make sure the hidden item has a value (i.e. image has been captured). Make the above conditional for request = button name so it only runs when you click Save (you probably want to disable this button until the data has been completely submitted to the collection - I haven't done this in the demonstration).
Voila, you should have now be able to capture the image from a webcam. Take a look at the samples from the CamCanvas API for extra effects if you wanted to do something special.
And of course, all the above assumed you want a resolution of 320 x 240 for the image.
Disclaimer: At time of writing, this worked with a logitech something or rather webcam, and is completely untested on IE.
Check out a demo: http://apex.oracle.com/pls/apex/f?p=trents_demos:webcam_i (my image is a bit blocky, but i think its just my webcam. I've seen others that are much more crisp using this) Also, just be sure to wait for the progress bar to dissappear before clicking Save.
Feedback welcomed.Hmm, maybe for some reason you aren't getting the base64 version of the saved image? Is the collection getting the full base64 string? Seems like its not getting any if its no data found.
The javascript console is your friend.
Also, in the example i used an extra page, from what one of the examples on apex packages apps had. But since then, I found this post by Carl: http://carlback.blogspot.com/2008/04/new-stuff-4-over-head-with-clob.html - I would use this technique for submitting the clob, over what I have done - as its less hacky. Just sayin. -
HOW TO SEND A HEBREW EMAIL WITH ATTACHMENT USING DEMO_MAIL
Hello All,
This is Not a question , just attaching something I've implemented and might be interesting for few of us,
This package I'm attaching allows to send Hebrew Language email + attaching files to it.
This package is based on demo_mail package (combined here but you can search at google for more example information if needed).
My Package is supplied as is , for any specific information regarding it , please contact me directly at : [email protected] or POST here.
* Please also note , that this package allow file to be attach via URL (meaning you will have to define a link to this file, if you would like to implement a link to a local file , e.g : c:\temp\myfile , you will have to customize the package your self with database directories option etc ...)
First I will attach an example of how to use it :
==================================
begin
demo_mail_heb.send_html_mail_attach(p_sender => '[email protected]',
p_recipients => '[email protected]',
p_subject => 'שלום וברכה עולם',
p_data => '<hr><b>בוקר טוב</b><hr>',
p_file_name => 'but_choose_file.gif',
p_file_mime_type => 'application/pdf',
p_file_URL => 'http://10.172.246.160:7777/i/but_choose_file.gif');
end;
Second Here is the Package (please note you will have to modify few settings in order to enable it , such as mail server address ..etc)
======================================================================================
CREATE OR REPLACE PACKAGE demo_mail_heb IS
----------------------- Customizable Section -----------------------
-- Customize the SMTP host, port and your domain name below.
smtp_host VARCHAR2(256) := 'mail.oracle.com';
smtp_port PLS_INTEGER := 25;
smtp_domain VARCHAR2(256) := 'oracle.com';
-- Customize the signature that will appear in the email's MIME header.
-- Useful for versioning.
MAILER_ID CONSTANT VARCHAR2(256) := 'Mailer by Oracle UTL_SMTP';
--------------------- End Customizable Section ---------------------
-- A unique string that demarcates boundaries of parts in a multi-part email
-- The string should not appear inside the body of any part of the email.
-- Customize this if needed or generate this randomly dynamically.
BOUNDARY CONSTANT VARCHAR2(256) := '-----7D81B75CCC90D2974F7A1CBD';
FIRST_BOUNDARY CONSTANT VARCHAR2(256) := '--' || BOUNDARY || utl_tcp.CRLF;
LAST_BOUNDARY CONSTANT VARCHAR2(256) := '--' || BOUNDARY || '--' ||
utl_tcp.CRLF;
-- A MIME type that denotes multi-part email (MIME) messages.
MULTIPART_MIME_TYPE CONSTANT VARCHAR2(256) := 'multipart/mixed; boundary="'||
BOUNDARY || '"';
MAX_BASE64_LINE_WIDTH CONSTANT PLS_INTEGER := 76 / 4 * 3;
-- Sent clear Html Email
procedure send_html_mail (p_sender in varchar2 default null,
p_recipients in varchar2 default null,
p_subject in varchar2 default null,
p_data in varchar2 default null,
p_mime_type in varchar2 default 'text/html; charset=windows-1255');
-- Sent Html Email with Attachment
procedure send_html_mail_attach (p_sender in varchar2 default null,
p_recipients in varchar2 default null,
p_subject in varchar2 default null,
p_data in varchar2 default '<b>áå÷ø èåá òåìí - áãé÷ä</b',
p_mime_type in varchar2 default demo_mail_heb.MULTIPART_MIME_TYPE,
p_file_name in varchar2 default 'but_choose_file.gif',
p_file_mime_type in varchar2 default 'application/pdf',
p_file_URL in varchar2 default 'http://10.172.246.160:7777/i/but_choose_file.gif');
-- A simple email API for sending email in plain text in a single call.
-- The format of an email address is one of these:
-- someone@some-domain
-- "Someone at some domain" <someone@some-domain>
-- Someone at some domain <someone@some-domain>
-- The recipients is a list of email addresses separated by
-- either a "," or a ";"
PROCEDURE mail(sender IN VARCHAR2,
recipients IN VARCHAR2,
subject IN VARCHAR2,
message IN VARCHAR2);
-- Extended email API to send email in HTML or plain text with no size limit.
-- First, begin the email by begin_mail(). Then, call write_text() repeatedly
-- to send email in ASCII piece-by-piece. Or, call write_mb_text() to send
-- email in non-ASCII or multi-byte character set. End the email with
-- end_mail().
FUNCTION begin_mail(sender IN VARCHAR2,
recipients IN VARCHAR2,
subject IN VARCHAR2,
mime_type IN VARCHAR2 DEFAULT 'text/plain',
priority IN PLS_INTEGER DEFAULT NULL)
RETURN utl_smtp.connection;
-- Write email body in ASCII
PROCEDURE write_text(conn IN OUT NOCOPY utl_smtp.connection,
message IN VARCHAR2);
-- Write email body in non-ASCII (including multi-byte). The email body
-- will be sent in the database character set.
PROCEDURE write_mb_text(conn IN OUT NOCOPY utl_smtp.connection,
message IN VARCHAR2);
-- Write email body in binary
PROCEDURE write_raw(conn IN OUT NOCOPY utl_smtp.connection,
message IN RAW);
-- APIs to send email with attachments. Attachments are sent by sending
-- emails in "multipart/mixed" MIME format. Specify that MIME format when
-- beginning an email with begin_mail().
-- Send a single text attachment.
PROCEDURE attach_text(conn IN OUT NOCOPY utl_smtp.connection,
data IN VARCHAR2,
mime_type IN VARCHAR2 DEFAULT 'text/plain',
inline IN BOOLEAN DEFAULT TRUE,
filename IN VARCHAR2 DEFAULT NULL,
last IN BOOLEAN DEFAULT FALSE);
-- Send a binary attachment. The attachment will be encoded in Base-64
-- encoding format.
PROCEDURE attach_base64(conn IN OUT NOCOPY utl_smtp.connection,
data IN RAW,
mime_type IN VARCHAR2 DEFAULT 'application/octet',
inline IN BOOLEAN DEFAULT TRUE,
filename IN VARCHAR2 DEFAULT NULL,
last IN BOOLEAN DEFAULT FALSE);
-- Send an attachment with no size limit. First, begin the attachment
-- with begin_attachment(). Then, call write_text repeatedly to send
-- the attachment piece-by-piece. If the attachment is text-based but
-- in non-ASCII or multi-byte character set, use write_mb_text() instead.
-- To send binary attachment, the binary content should first be
-- encoded in Base-64 encoding format using the demo package for 8i,
-- or the native one in 9i. End the attachment with end_attachment.
PROCEDURE begin_attachment(conn IN OUT NOCOPY utl_smtp.connection,
mime_type IN VARCHAR2 DEFAULT 'text/plain',
inline IN BOOLEAN DEFAULT TRUE,
filename IN VARCHAR2 DEFAULT NULL,
transfer_enc IN VARCHAR2 DEFAULT NULL);
-- End the attachment.
PROCEDURE end_attachment(conn IN OUT NOCOPY utl_smtp.connection,
last IN BOOLEAN DEFAULT FALSE);
-- End the email.
PROCEDURE end_mail(conn IN OUT NOCOPY utl_smtp.connection);
-- Extended email API to send multiple emails in a session for better
-- performance. First, begin an email session with begin_session.
-- Then, begin each email with a session by calling begin_mail_in_session
-- instead of begin_mail. End the email with end_mail_in_session instead
-- of end_mail. End the email session by end_session.
FUNCTION begin_session RETURN utl_smtp.connection;
-- Begin an email in a session.
PROCEDURE begin_mail_in_session(conn IN OUT NOCOPY utl_smtp.connection,
sender IN VARCHAR2,
recipients IN VARCHAR2,
subject IN VARCHAR2,
-- mime_type IN VARCHAR2 DEFAULT 'text/plain; charset=windows-1255',
mime_type IN VARCHAR2 DEFAULT 'text/plain',
priority IN PLS_INTEGER DEFAULT NULL);
-- End an email in a session.
PROCEDURE end_mail_in_session(conn IN OUT NOCOPY utl_smtp.connection);
-- End an email session.
PROCEDURE end_session(conn IN OUT NOCOPY utl_smtp.connection);
END;
CREATE OR REPLACE PACKAGE BODY demo_mail_heb IS
-- Sent clear Html Email
procedure send_html_mail (p_sender in varchar2 default null,
p_recipients in varchar2 default null,
p_subject in varchar2 default null,
p_data in varchar2 default null,
p_mime_type in varchar2 default 'text/html; charset=windows-1255')
Is
conn utl_smtp.connection;
BEGIN
conn := demo_mail_heb.begin_mail(
sender => p_sender,
recipients => p_recipients,
subject => p_subject,
mime_type => p_mime_type);
demo_mail_heb.write_text(
conn => conn,
message => p_data);
demo_mail_heb.end_mail( conn => conn );
END;
-- Sent Html Email with Attachment
procedure send_html_mail_attach (p_sender in varchar2 default null,
p_recipients in varchar2 default null,
p_subject in varchar2 default null,
p_data in varchar2 default '<b>áå÷ø èåá òåìí - áãé÷ä</b',
p_mime_type in varchar2 default demo_mail_heb.MULTIPART_MIME_TYPE,
p_file_name in varchar2 default 'but_choose_file.gif',
p_file_mime_type in varchar2 default 'application/pdf',
p_file_URL in varchar2 default 'http://10.172.246.160:7777/i/but_choose_file.gif')
is
conn utl_smtp.connection;
req utl_http.req;
resp utl_http.resp;
data RAW(200);
begin
conn := demo_mail_heb.begin_mail(
sender => p_sender,
recipients => p_recipients,
subject => p_subject,
mime_type => p_mime_type);
demo_mail_heb.attach_text(
conn => conn,
data => p_data,
mime_type => 'text/html');
demo_mail_heb.begin_attachment(
conn => conn,
mime_type => p_file_mime_type,
inline => TRUE,
filename => p_file_name,
transfer_enc => 'base64');
-- In writing Base-64 encoded text following the MIME format below,
-- the MIME format requires that a long piece of data must be splitted
-- into multiple lines and each line of encoded data cannot exceed
-- 80 characters, including the new-line characters. Also, when
-- splitting the original data into pieces, the length of each chunk
-- of data before encoding must be a multiple of 3, except for the
-- last chunk. The constant demo_mail_heb.MAX_BASE64_LINE_WIDTH
-- (76 / 4 * 3 = 57) is the maximum length (in bytes) of each chunk
-- of data before encoding.
Utl_Http.set_proxy('www-proxy.us.oracle.com', 'oracle.com');
req := utl_http.begin_request(p_file_URL);
resp := utl_http.get_response(req);
BEGIN
LOOP
utl_http.read_raw(resp, data, demo_mail_heb.MAX_BASE64_LINE_WIDTH);
demo_mail_heb.write_raw(
conn => conn,
message => utl_encode.base64_encode(data));
END LOOP;
EXCEPTION
WHEN utl_http.end_of_body THEN
utl_http.end_response(resp);
END;
demo_mail_heb.end_attachment( conn => conn );
demo_mail_heb.end_mail( conn => conn );
end;
-- Return the next email address in the list of email addresses, separated
-- by either a "," or a ";". The format of mailbox may be in one of these:
-- someone@some-domain
-- "Someone at some domain" <someone@some-domain>
-- Someone at some domain <someone@some-domain>
FUNCTION get_address(addr_list IN OUT VARCHAR2) RETURN VARCHAR2 IS
addr VARCHAR2(256);
i pls_integer;
FUNCTION lookup_unquoted_char(str IN VARCHAR2,
chrs IN VARCHAR2) RETURN pls_integer AS
c VARCHAR2(5);
i pls_integer;
len pls_integer;
inside_quote BOOLEAN;
BEGIN
inside_quote := false;
i := 1;
len := length(str);
WHILE (i <= len) LOOP
c := substr(str, i, 1);
IF (inside_quote) THEN
IF (c = '"') THEN
inside_quote := false;
ELSIF (c = '\') THEN
i := i + 1; -- Skip the quote character
END IF;
GOTO next_char;
END IF;
IF (c = '"') THEN
inside_quote := true;
GOTO next_char;
END IF;
IF (instr(chrs, c) >= 1) THEN
RETURN i;
END IF;
<<next_char>>
i := i + 1;
END LOOP;
RETURN 0;
END;
BEGIN
addr_list := ltrim(addr_list);
i := lookup_unquoted_char(addr_list, ',;');
IF (i >= 1) THEN
addr := substr(addr_list, 1, i - 1);
addr_list := substr(addr_list, i + 1);
ELSE
addr := addr_list;
addr_list := '';
END IF;
i := lookup_unquoted_char(addr, '<');
IF (i >= 1) THEN
addr := substr(addr, i + 1);
i := instr(addr, '>');
IF (i >= 1) THEN
addr := substr(addr, 1, i - 1);
END IF;
END IF;
RETURN addr;
END;
-- Write a MIME header
PROCEDURE write_mime_header(conn IN OUT NOCOPY utl_smtp.connection,
name IN VARCHAR2,
value IN VARCHAR2) IS
BEGIN
-- utl_smtp.write_data(conn, name || ': ' || value || utl_tcp.CRLF);
utl_smtp.write_raw_data(conn, UTL_RAW.CAST_TO_RAW(name || ': ' ||value || utl_tcp.CRLF));
END;
-- Mark a message-part boundary. Set <last> to TRUE for the last boundary.
PROCEDURE write_boundary(conn IN OUT NOCOPY utl_smtp.connection,
last IN BOOLEAN DEFAULT FALSE) AS
BEGIN
IF (last) THEN
utl_smtp.write_data(conn, LAST_BOUNDARY);
ELSE
utl_smtp.write_data(conn, FIRST_BOUNDARY);
END IF;
END;
PROCEDURE mail(sender IN VARCHAR2,
recipients IN VARCHAR2,
subject IN VARCHAR2,
message IN VARCHAR2) IS
conn utl_smtp.connection;
BEGIN
conn := begin_mail(sender, recipients, subject);
write_text(conn, message);
end_mail(conn);
END;
FUNCTION begin_mail(sender IN VARCHAR2,
recipients IN VARCHAR2,
subject IN VARCHAR2,
mime_type IN VARCHAR2 DEFAULT 'text/plain',
priority IN PLS_INTEGER DEFAULT NULL)
RETURN utl_smtp.connection IS
conn utl_smtp.connection;
BEGIN
conn := begin_session;
begin_mail_in_session(conn, sender, recipients, subject, mime_type,
priority);
RETURN conn;
END;
PROCEDURE write_text(conn IN OUT NOCOPY utl_smtp.connection,
message IN VARCHAR2) IS
BEGIN
utl_smtp.write_raw_data(conn, utl_raw.cast_to_raw(CONVERT(message,'IW8ISO8859P8')));
END;
PROCEDURE write_mb_text(conn IN OUT NOCOPY utl_smtp.connection,
message IN VARCHAR2) IS
BEGIN
utl_smtp.write_raw_data(conn, utl_raw.cast_to_raw(message));
END;
PROCEDURE write_raw(conn IN OUT NOCOPY utl_smtp.connection,
message IN RAW) IS
BEGIN
utl_smtp.write_raw_data(conn, message);
END;
PROCEDURE attach_text(conn IN OUT NOCOPY utl_smtp.connection,
data IN VARCHAR2,
mime_type IN VARCHAR2 DEFAULT 'text/plain',
inline IN BOOLEAN DEFAULT TRUE,
filename IN VARCHAR2 DEFAULT NULL,
last IN BOOLEAN DEFAULT FALSE) IS
BEGIN
begin_attachment(conn, mime_type, inline, filename);
write_text(conn, data);
end_attachment(conn, last);
END;
PROCEDURE attach_base64(conn IN OUT NOCOPY utl_smtp.connection,
data IN RAW,
mime_type IN VARCHAR2 DEFAULT 'application/octet',
inline IN BOOLEAN DEFAULT TRUE,
filename IN VARCHAR2 DEFAULT NULL,
last IN BOOLEAN DEFAULT FALSE) IS
i PLS_INTEGER;
len PLS_INTEGER;
BEGIN
begin_attachment(conn, mime_type, inline, filename, 'base64');
-- Split the Base64-encoded attachment into multiple lines
i := 1;
len := utl_raw.length(data);
WHILE (i < len) LOOP
IF (i + MAX_BASE64_LINE_WIDTH < len) THEN
utl_smtp.write_raw_data(conn,
utl_encode.base64_encode(utl_raw.substr(data, i,
MAX_BASE64_LINE_WIDTH)));
ELSE
utl_smtp.write_raw_data(conn,
utl_encode.base64_encode(utl_raw.substr(data, i)));
END IF;
utl_smtp.write_data(conn, utl_tcp.CRLF);
i := i + MAX_BASE64_LINE_WIDTH;
END LOOP;
end_attachment(conn, last);
END;
PROCEDURE begin_attachment(conn IN OUT NOCOPY utl_smtp.connection,
mime_type IN VARCHAR2 DEFAULT 'text/plain',
inline IN BOOLEAN DEFAULT TRUE,
filename IN VARCHAR2 DEFAULT NULL,
transfer_enc IN VARCHAR2 DEFAULT NULL) IS
BEGIN
write_boundary(conn);
write_mime_header(conn, 'Content-Type', mime_type);
IF (filename IS NOT NULL) THEN
IF (inline) THEN
write_mime_header(conn, 'Content-Disposition',
'inline; filename="'||filename||'"');
ELSE
write_mime_header(conn, 'Content-Disposition',
'attachment; filename="'||filename||'"');
END IF;
END IF;
IF (transfer_enc IS NOT NULL) THEN
write_mime_header(conn, 'Content-Transfer-Encoding', transfer_enc);
END IF;
utl_smtp.write_data(conn, utl_tcp.CRLF);
END;
PROCEDURE end_attachment(conn IN OUT NOCOPY utl_smtp.connection,
last IN BOOLEAN DEFAULT FALSE) IS
BEGIN
utl_smtp.write_data(conn, utl_tcp.CRLF);
IF (last) THEN
write_boundary(conn, last);
END IF;
END;
PROCEDURE end_mail(conn IN OUT NOCOPY utl_smtp.connection) IS
BEGIN
end_mail_in_session(conn);
end_session(conn);
END;
FUNCTION begin_session RETURN utl_smtp.connection IS
conn utl_smtp.connection;
BEGIN
-- open SMTP connection
conn := utl_smtp.open_connection(smtp_host, smtp_port);
utl_smtp.helo(conn, smtp_domain);
RETURN conn;
END;
PROCEDURE begin_mail_in_session(conn IN OUT NOCOPY utl_smtp.connection,
sender IN VARCHAR2,
recipients IN VARCHAR2,
subject IN VARCHAR2,
mime_type IN VARCHAR2 DEFAULT 'text/plain',
-- mime_type IN VARCHAR2 DEFAULT 'text/plain; charset=windows-1255',
priority IN PLS_INTEGER DEFAULT NULL) IS
my_recipients VARCHAR2(32767) := recipients;
my_sender VARCHAR2(32767) := sender;
BEGIN
-- Specify sender's address (our server allows bogus address
-- as long as it is a full email address ([email protected]).
utl_smtp.mail(conn, get_address(my_sender));
-- Specify recipient(s) of the email.
WHILE (my_recipients IS NOT NULL) LOOP
utl_smtp.rcpt(conn, get_address(my_recipients));
END LOOP;
-- Start body of email
utl_smtp.open_data(conn);
-- Set "From" MIME header
write_mime_header(conn, 'From', sender);
-- Set "To" MIME header
write_mime_header(conn, 'To', recipients);
-- Set "Subject" MIME header
write_mime_header(conn, 'Subject', subject);
-- Set "Content-Type" MIME header
write_mime_header(conn, 'Content-Type', mime_type);
-- Set "X-Mailer" MIME header
write_mime_header(conn, 'X-Mailer', MAILER_ID);
-- Set priority:
-- High Normal Low
-- 1 2 3 4 5
IF (priority IS NOT NULL) THEN
write_mime_header(conn, 'X-Priority', priority);
END IF;
-- Send an empty line to denotes end of MIME headers and
-- beginning of message body.
utl_smtp.write_data(conn, utl_tcp.CRLF);
IF (mime_type LIKE 'multipart/mixed%') THEN
write_text(conn, 'This is a multi-part message in MIME format.' ||
utl_tcp.crlf);
END IF;
END;
PROCEDURE end_mail_in_session(conn IN OUT NOCOPY utl_smtp.connection) IS
BEGIN
utl_smtp.close_data(conn);
END;
PROCEDURE end_session(conn IN OUT NOCOPY utl_smtp.connection) IS
BEGIN
utl_smtp.quit(conn);
END;
END;Hello All,
Small modification - use this package and not the above
HERE IS A WORKING CODE FOR SENDING HEBREW MESSAGES (INCLUDING SUBJECT IN UTF-8 APPEAR IN ALL EMAIL CLIENTS I HAVE CHECKED) + ATTACHMENTS
Code attached below is supplied as is with no support. anyhow if help is needed , please contact me via [email protected]
============================================================================
CREATE OR REPLACE PACKAGE demo_mail_heb IS
----------------------- Customizable Section -----------------------
-- Customize the SMTP host, port and your domain name below.
smtp_host VARCHAR2(256) := pst_ajax.getParameter('EMAIL_SMTP_HOST');
smtp_port PLS_INTEGER := pst_ajax.getParameter('EMAIL_SMTP_PORT');
smtp_domain VARCHAR2(256) := pst_ajax.getParameter('EMAIL_SMTP_DOMAIN');
-- Customize the signature that will appear in the email's MIME header.
-- Useful for versioning.
MAILER_ID CONSTANT VARCHAR2(256) := 'Mailer by Oracle UTL_SMTP';
--------------------- End Customizable Section ---------------------
-- A unique string that demarcates boundaries of parts in a multi-part email
-- The string should not appear inside the body of any part of the email.
-- Customize this if needed or generate this randomly dynamically.
BOUNDARY CONSTANT VARCHAR2(256) := '-----7D81B75CCC90D2974F7A1CBD';
FIRST_BOUNDARY CONSTANT VARCHAR2(256) := '--' || BOUNDARY || utl_tcp.CRLF;
LAST_BOUNDARY CONSTANT VARCHAR2(256) := '--' || BOUNDARY || '--' ||
utl_tcp.CRLF;
-- A MIME type that denotes multi-part email (MIME) messages.
MULTIPART_MIME_TYPE CONSTANT VARCHAR2(256) := 'multipart/mixed; boundary="'||
BOUNDARY || '"';
MAX_BASE64_LINE_WIDTH CONSTANT PLS_INTEGER := 76 / 4 * 3;
-- Sent clear Html Email
procedure send_html_mail (p_sender in varchar2 default null,
p_recipients in varchar2 default null,
p_subject in varchar2 default null,
p_data in varchar2 default null,
p_mime_type in varchar2 default 'text/html; charset=windows-1255');
-- Sent Html Email with Attachment
procedure send_html_mail_attach (p_sender in varchar2 default null,
p_recipients in varchar2 default null,
p_subject in varchar2 default null,
p_data in varchar2 default '<b>áå÷ø èåá òåìí - áãé÷ä</b',
p_mime_type in varchar2 default 'text/html; charset=windows-1255',
p_file_name in varchar2 default 'but_choose_file.gif',
p_file_mime_type in varchar2 default 'application/pdf',
p_file_URL in varchar2 default 'http://10.172.246.160:7777/i/but_choose_file.gif');
-- A simple email API for sending email in plain text in a single call.
-- The format of an email address is one of these:
-- someone@some-domain
-- "Someone at some domain" <someone@some-domain>
-- Someone at some domain <someone@some-domain>
-- The recipients is a list of email addresses separated by
-- either a "," or a ";"
PROCEDURE mail(sender IN VARCHAR2,
recipients IN VARCHAR2,
subject IN VARCHAR2,
message IN VARCHAR2);
-- Extended email API to send email in HTML or plain text with no size limit.
-- First, begin the email by begin_mail(). Then, call write_text() repeatedly
-- to send email in ASCII piece-by-piece. Or, call write_mb_text() to send
-- email in non-ASCII or multi-byte character set. End the email with
-- end_mail().
FUNCTION begin_mail(sender IN VARCHAR2,
recipients IN VARCHAR2,
subject IN VARCHAR2,
mime_type IN VARCHAR2 DEFAULT 'text/plain',
priority IN PLS_INTEGER DEFAULT NULL)
RETURN utl_smtp.connection;
-- Write email body in ASCII
PROCEDURE write_text(conn IN OUT NOCOPY utl_smtp.connection,
message IN VARCHAR2);
-- Write email body in non-ASCII (including multi-byte). The email body
-- will be sent in the database character set.
PROCEDURE write_mb_text(conn IN OUT NOCOPY utl_smtp.connection,
message IN VARCHAR2);
-- Write email body in binary
PROCEDURE write_raw(conn IN OUT NOCOPY utl_smtp.connection,
message IN RAW);
-- APIs to send email with attachments. Attachments are sent by sending
-- emails in "multipart/mixed" MIME format. Specify that MIME format when
-- beginning an email with begin_mail().
-- Send a single text attachment.
PROCEDURE attach_text(conn IN OUT NOCOPY utl_smtp.connection,
data IN VARCHAR2,
mime_type IN VARCHAR2 DEFAULT 'text/plain',
inline IN BOOLEAN DEFAULT TRUE,
filename IN VARCHAR2 DEFAULT NULL,
last IN BOOLEAN DEFAULT FALSE);
-- Send a binary attachment. The attachment will be encoded in Base-64
-- encoding format.
PROCEDURE attach_base64(conn IN OUT NOCOPY utl_smtp.connection,
data IN RAW,
mime_type IN VARCHAR2 DEFAULT 'application/octet',
inline IN BOOLEAN DEFAULT TRUE,
filename IN VARCHAR2 DEFAULT NULL,
last IN BOOLEAN DEFAULT FALSE);
-- Send an attachment with no size limit. First, begin the attachment
-- with begin_attachment(). Then, call write_text repeatedly to send
-- the attachment piece-by-piece. If the attachment is text-based but
-- in non-ASCII or multi-byte character set, use write_mb_text() instead.
-- To send binary attachment, the binary content should first be
-- encoded in Base-64 encoding format using the demo package for 8i,
-- or the native one in 9i. End the attachment with end_attachment.
PROCEDURE begin_attachment(conn IN OUT NOCOPY utl_smtp.connection,
mime_type IN VARCHAR2 DEFAULT 'text/plain',
inline IN BOOLEAN DEFAULT TRUE,
filename IN VARCHAR2 DEFAULT NULL,
transfer_enc IN VARCHAR2 DEFAULT NULL);
-- End the attachment.
PROCEDURE end_attachment(conn IN OUT NOCOPY utl_smtp.connection,
last IN BOOLEAN DEFAULT FALSE);
-- End the email.
PROCEDURE end_mail(conn IN OUT NOCOPY utl_smtp.connection);
-- Extended email API to send multiple emails in a session for better
-- performance. First, begin an email session with begin_session.
-- Then, begin each email with a session by calling begin_mail_in_session
-- instead of begin_mail. End the email with end_mail_in_session instead
-- of end_mail. End the email session by end_session.
FUNCTION begin_session RETURN utl_smtp.connection;
-- Handling the Email Subject Line
function mimeheader_encode(
p_str varchar2
, p_charset varchar2 := 'UTF-8') return varchar2;
-- Begin an email in a session.
PROCEDURE begin_mail_in_session(conn IN OUT NOCOPY utl_smtp.connection,
sender IN VARCHAR2,
recipients IN VARCHAR2,
subject IN VARCHAR2,
-- mime_type IN VARCHAR2 DEFAULT 'text/plain; charset=windows-1255',
mime_type IN VARCHAR2 DEFAULT 'text/plain',
priority IN PLS_INTEGER DEFAULT NULL);
-- End an email in a session.
PROCEDURE end_mail_in_session(conn IN OUT NOCOPY utl_smtp.connection);
-- End an email session.
PROCEDURE end_session(conn IN OUT NOCOPY utl_smtp.connection);
END;
CREATE OR REPLACE PACKAGE BODY demo_mail_heb IS
-- Sent clear Html Email
procedure send_html_mail (p_sender in varchar2 default null,
p_recipients in varchar2 default null,
p_subject in varchar2 default null,
p_data in varchar2 default null,
p_mime_type in varchar2 default 'text/html; charset=windows-1255')
Is
conn utl_smtp.connection;
BEGIN
conn := demo_mail_heb.begin_mail(
sender => p_sender,
recipients => p_recipients,
subject => p_subject,
mime_type => 'text/html; charset=UTF-8');--p_mime_type);
demo_mail_heb.write_text(
conn => conn,
message => p_data);
demo_mail_heb.end_mail( conn => conn );
END;
-- Sent Html Email with Attachment
procedure send_html_mail_attach (p_sender in varchar2 default null,
p_recipients in varchar2 default null,
p_subject in varchar2 default null,
p_data in varchar2 default '<b>áå÷ø èåá òåìí - áãé÷ä</b',
p_mime_type in varchar2 default 'text/html; charset=windows-1255',
p_file_name in varchar2 default 'but_choose_file.gif',
p_file_mime_type in varchar2 default 'application/pdf',
p_file_URL in varchar2 default 'http://10.172.246.160:7777/i/but_choose_file.gif')
is
conn utl_smtp.connection;
req utl_http.req;
resp utl_http.resp;
data RAW(200);
v_mime_type varchar2(32767):=demo_mail.MULTIPART_MIME_TYPE;
begin
conn := demo_mail_heb.begin_mail(
sender => p_sender,
recipients => p_recipients,
subject => p_subject,
mime_type => v_mime_type);
demo_mail_heb.attach_text(
conn => conn,
data => p_data,
mime_type => 'text/html');
demo_mail_heb.begin_attachment(
conn => conn,
mime_type => p_file_mime_type,
inline => TRUE,
filename => p_file_name,
transfer_enc => 'base64');
-- In writing Base-64 encoded text following the MIME format below,
-- the MIME format requires that a long piece of data must be splitted
-- into multiple lines and each line of encoded data cannot exceed
-- 80 characters, including the new-line characters. Also, when
-- splitting the original data into pieces, the length of each chunk
-- of data before encoding must be a multiple of 3, except for the
-- last chunk. The constant demo_mail_heb.MAX_BASE64_LINE_WIDTH
-- (76 / 4 * 3 = 57) is the maximum length (in bytes) of each chunk
-- of data before encoding.
req := utl_http.begin_request(p_file_URL);
resp := utl_http.get_response(req);
BEGIN
LOOP
utl_http.read_raw(resp, data, demo_mail_heb.MAX_BASE64_LINE_WIDTH);
demo_mail_heb.write_raw(
conn => conn,
message => utl_encode.base64_encode(data));
END LOOP;
EXCEPTION
WHEN utl_http.end_of_body THEN
utl_http.end_response(resp);
END;
demo_mail_heb.end_attachment( conn => conn );
demo_mail_heb.end_mail( conn => conn );
end;
-- Return the next email address in the list of email addresses, separated
-- by either a "," or a ";". The format of mailbox may be in one of these:
-- someone@some-domain
-- "Someone at some domain" <someone@some-domain>
-- Someone at some domain <someone@some-domain>
FUNCTION get_address(addr_list IN OUT VARCHAR2) RETURN VARCHAR2 IS
addr VARCHAR2(256);
i pls_integer;
FUNCTION lookup_unquoted_char(str IN VARCHAR2,
chrs IN VARCHAR2) RETURN pls_integer AS
c VARCHAR2(5);
i pls_integer;
len pls_integer;
inside_quote BOOLEAN;
BEGIN
inside_quote := false;
i := 1;
len := length(str);
WHILE (i <= len) LOOP
c := substr(str, i, 1);
IF (inside_quote) THEN
IF (c = '"') THEN
inside_quote := false;
ELSIF (c = '\') THEN
i := i + 1; -- Skip the quote character
END IF;
GOTO next_char;
END IF;
IF (c = '"') THEN
inside_quote := true;
GOTO next_char;
END IF;
IF (instr(chrs, c) >= 1) THEN
RETURN i;
END IF;
<<next_char>>
i := i + 1;
END LOOP;
RETURN 0;
END;
BEGIN
addr_list := ltrim(addr_list);
i := lookup_unquoted_char(addr_list, ',;');
IF (i >= 1) THEN
addr := substr(addr_list, 1, i - 1);
addr_list := substr(addr_list, i + 1);
ELSE
addr := addr_list;
addr_list := '';
END IF;
i := lookup_unquoted_char(addr, '<');
IF (i >= 1) THEN
addr := substr(addr, i + 1);
i := instr(addr, '>');
IF (i >= 1) THEN
addr := substr(addr, 1, i - 1);
END IF;
END IF;
RETURN addr;
END;
-- Write a MIME header
PROCEDURE write_mime_header(conn IN OUT NOCOPY utl_smtp.connection,
name IN VARCHAR2,
value IN VARCHAR2) IS
BEGIN
-- utl_smtp.write_data(conn, name || ': ' || value || utl_tcp.CRLF);
utl_smtp.write_raw_data(conn, UTL_RAW.CAST_TO_RAW(name || ': ' ||value || utl_tcp.CRLF));
END;
-- Mark a message-part boundary. Set <last> to TRUE for the last boundary.
PROCEDURE write_boundary(conn IN OUT NOCOPY utl_smtp.connection,
last IN BOOLEAN DEFAULT FALSE) AS
BEGIN
IF (last) THEN
utl_smtp.write_data(conn, LAST_BOUNDARY);
ELSE
utl_smtp.write_data(conn, FIRST_BOUNDARY);
END IF;
END;
PROCEDURE mail(sender IN VARCHAR2,
recipients IN VARCHAR2,
subject IN VARCHAR2,
message IN VARCHAR2) IS
conn utl_smtp.connection;
BEGIN
conn := begin_mail(sender, recipients, subject);
write_text(conn, message);
end_mail(conn);
END;
FUNCTION begin_mail(sender IN VARCHAR2,
recipients IN VARCHAR2,
subject IN VARCHAR2,
mime_type IN VARCHAR2 DEFAULT 'text/plain',
priority IN PLS_INTEGER DEFAULT NULL)
RETURN utl_smtp.connection IS
conn utl_smtp.connection;
BEGIN
conn := begin_session;
begin_mail_in_session(conn, sender, recipients, subject, mime_type,
priority);
RETURN conn;
END;
PROCEDURE write_text(conn IN OUT NOCOPY utl_smtp.connection,
message IN VARCHAR2) IS
BEGIN
utl_smtp.write_raw_data(conn, utl_raw.cast_to_raw(CONVERT(message,'IW8ISO8859P8')));
-- utl_smtp.write_raw_data(conn, utl_raw.cast_to_raw(message));
END;
PROCEDURE write_mb_text(conn IN OUT NOCOPY utl_smtp.connection,
message IN VARCHAR2) IS
BEGIN
utl_smtp.write_raw_data(conn, utl_raw.cast_to_raw(message));
END;
PROCEDURE write_raw(conn IN OUT NOCOPY utl_smtp.connection,
message IN RAW) IS
BEGIN
utl_smtp.write_raw_data(conn, message);
END;
PROCEDURE attach_text(conn IN OUT NOCOPY utl_smtp.connection,
data IN VARCHAR2,
mime_type IN VARCHAR2 DEFAULT 'text/plain',
inline IN BOOLEAN DEFAULT TRUE,
filename IN VARCHAR2 DEFAULT NULL,
last IN BOOLEAN DEFAULT FALSE) IS
BEGIN
begin_attachment(conn, mime_type, inline, filename);
write_text(conn, data);
end_attachment(conn, last);
END;
PROCEDURE attach_base64(conn IN OUT NOCOPY utl_smtp.connection,
data IN RAW,
mime_type IN VARCHAR2 DEFAULT 'application/octet',
inline IN BOOLEAN DEFAULT TRUE,
filename IN VARCHAR2 DEFAULT NULL,
last IN BOOLEAN DEFAULT FALSE) IS
i PLS_INTEGER;
len PLS_INTEGER;
BEGIN
begin_attachment(conn, mime_type, inline, filename, 'base64');
-- Split the Base64-encoded attachment into multiple lines
i := 1;
len := utl_raw.length(data);
WHILE (i < len) LOOP
IF (i + MAX_BASE64_LINE_WIDTH < len) THEN
utl_smtp.write_raw_data(conn,
utl_encode.base64_encode(utl_raw.substr(data, i,
MAX_BASE64_LINE_WIDTH)));
ELSE
utl_smtp.write_raw_data(conn,
utl_encode.base64_encode(utl_raw.substr(data, i)));
END IF;
utl_smtp.write_data(conn, utl_tcp.CRLF);
i := i + MAX_BASE64_LINE_WIDTH;
END LOOP;
end_attachment(conn, last);
END;
PROCEDURE begin_attachment(conn IN OUT NOCOPY utl_smtp.connection,
mime_type IN VARCHAR2 DEFAULT 'text/plain',
inline IN BOOLEAN DEFAULT TRUE,
filename IN VARCHAR2 DEFAULT NULL,
transfer_enc IN VARCHAR2 DEFAULT NULL) IS
BEGIN
write_boundary(conn);
write_mime_header(conn, 'Content-Type', mime_type);
IF (filename IS NOT NULL) THEN
IF (inline) THEN
write_mime_header(conn, 'Content-Disposition',
'inline; filename="'||filename||'"');
ELSE
write_mime_header(conn, 'Content-Disposition',
'attachment; filename="'||filename||'"');
END IF;
END IF;
IF (transfer_enc IS NOT NULL) THEN
write_mime_header(conn, 'Content-Transfer-Encoding', transfer_enc);
END IF;
utl_smtp.write_data(conn, utl_tcp.CRLF);
END;
PROCEDURE end_attachment(conn IN OUT NOCOPY utl_smtp.connection,
last IN BOOLEAN DEFAULT FALSE) IS
BEGIN
utl_smtp.write_data(conn, utl_tcp.CRLF);
IF (last) THEN
write_boundary(conn, last);
END IF;
END;
PROCEDURE end_mail(conn IN OUT NOCOPY utl_smtp.connection) IS
BEGIN
end_mail_in_session(conn);
end_session(conn);
END;
FUNCTION begin_session RETURN utl_smtp.connection IS
conn utl_smtp.connection;
BEGIN
-- open SMTP connection
conn := utl_smtp.open_connection(smtp_host, smtp_port);
utl_smtp.helo(conn, smtp_domain);
RETURN conn;
END;
-- Handling the Email Subject Line
function mimeheader_encode(
p_str varchar2
, p_charset varchar2 := 'UTF-8') return varchar2 is
l_str varchar2(2000);
begin
l_str:=utl_raw.cast_to_varchar2(utl_encode.quoted_printable_encode(utl_raw.cast_to_raw(p_str)));
l_str:=replace(l_str,'='||chr(13)||chr(10),''); --unfold the data
l_str:=replace(l_str,'?','=3f'); --quote question marks
l_str:=replace(l_str,' ','=20'); --quote spaces
l_str:='=?'||p_charset||'?Q?'||l_str||'?='; -- add prefix and suffix
return l_str;
end;
PROCEDURE begin_mail_in_session(conn IN OUT NOCOPY utl_smtp.connection,
sender IN VARCHAR2,
recipients IN VARCHAR2,
subject IN VARCHAR2,
mime_type IN VARCHAR2 DEFAULT 'text/plain',
-- mime_type IN VARCHAR2 DEFAULT 'text/plain; charset=windows-1255',
priority IN PLS_INTEGER DEFAULT NULL) IS
my_recipients VARCHAR2(32767) := recipients;
my_sender VARCHAR2(32767) := sender;
BEGIN
-- Specify sender's address (our server allows bogus address
-- as long as it is a full email address ([email protected]).
utl_smtp.mail(conn, get_address(my_sender));
-- Specify recipient(s) of the email.
WHILE (my_recipients IS NOT NULL) LOOP
utl_smtp.rcpt(conn, get_address(my_recipients));
END LOOP;
-- Start body of email
utl_smtp.open_data(conn);
-- Set "From" MIME header
write_mime_header(conn, 'From', sender);
-- Set "To" MIME header
write_mime_header(conn, 'To', recipients);
-- Set "Content-Type" MIME header
write_mime_header(conn, 'Content-Type', mime_type);
-- write_mime_header(conn, 'Content-Type', 'text/html; charset=UTF-8');
-- Set "Subject" MIME header
-- write_mime_header(conn, 'Subject', subject);
-- write_mime_header(conn, 'Subject', CONVERT(subject,'IW8ISO8859P8'));
write_mime_header(conn, 'Subject',mimeheader_encode(p_str => subject,p_charset => 'UTF-8'));
-- write_mime_header(conn, 'Subject',CONVERT(subject,'IW8MSWIN1255'));
-- Set "X-Mailer" MIME header
write_mime_header(conn, 'X-Mailer', MAILER_ID);
-- Set priority:
-- High Normal Low
-- 1 2 3 4 5
IF (priority IS NOT NULL) THEN
write_mime_header(conn, 'X-Priority', priority);
END IF;
-- Send an empty line to denotes end of MIME headers and
-- beginning of message body.
utl_smtp.write_data(conn, utl_tcp.CRLF);
IF (mime_type LIKE 'multipart/mixed%') THEN
write_text(conn, 'This is a multi-part message in MIME format.' ||
utl_tcp.crlf);
END IF;
END;
PROCEDURE end_mail_in_session(conn IN OUT NOCOPY utl_smtp.connection) IS
BEGIN
utl_smtp.close_data(conn);
END;
PROCEDURE end_session(conn IN OUT NOCOPY utl_smtp.connection) IS
BEGIN
utl_smtp.quit(conn);
END;
END; -
PL/SQL Mail Utility :: Binary/Ascii/Cc/Bcc/FileDump
I was working on my mail package and decided it was overtly complicated and
stripped it down to its bare bones. Here is what I came up with. Built on a previous
foundation of anothers work, I expanded the functionality considerably. You will find all
the features I think that you will need regarding a mail routine. There is also a nice
filedump routine included which makes very easy to create flat file dumps that you can
then attach to your emails. There are a few pre-reqs in using this though :
- 9iR2+
- DBA_Directories defined as opposed to utl_file paths
- Java Virtual Machine. Document can be found in Note :105472.1 Setup, Configuration,
and Use of the Java Virtual Machine on metalink.
As always, I welcome feedback and suggestions for improvement.
Barry C
http://www.myoracleportal.com
CREATE OR REPLACE PACKAGE mail_tools
AS
-- SENDMAIL supports variable message length with/without attachments
-- QUERY_SERVER allows you to check the status of a mail server to see if it is running
-- DUMP_FLATFILE allows you to dump flat file data from query submitted
-- Query Server to verify that the server is up and running.
-- Connects, Noop Command is executed, Disconnect.
-- GET_MAIL_ADDRESS is utilized in the SENDMAIL procedure
-- Table 100-3 SMTP Reply Codes
-- Reply Code
-- Meaning
-- 211 System status, or system help reply
-- 214 Help message [Information on how to use the receiver or the meaning of a particular non-standard command; this reply is useful only to the human user]
-- 220 <domain> Service ready
-- 221 <domain> Service closing transmission channel
-- 250 Requested mail action okay, completed
-- 251 User not local; will forward to <forward-path>
-- 252 OK, pending messages for node <node> started. Cannot VRFY user (e.g., info is not local), but will take message for this user and attempt delivery.
-- 253 OK, <messages> pending messages for node <node> started
-- 354 Start mail input; end with <CRLF>.<CRLF>
-- 355 Octet-offset is the transaction offset
-- 421 <domain> Service not available, closing transmission channel (This may be a reply to any command if the service knows it must shut down.)
-- 450 Requested mail action not taken: mailbox unavailable [for example, mailbox busy]
-- 451 Requested action aborted: local error in processing
-- 452 Requested action not taken: insufficient system storage
-- 453 You have no mail.
-- 454 TLS not available due to temporary reason. Encryption required for requested authentication mechanism.
-- 458 Unable to queue messages for node <node>
-- 459 Node <node> not allowed: reason
-- 500 Syntax error, command unrecognized (This may include errors such as command line too long.)
-- 501 Syntax error in parameters or arguments
-- 502 Command not implemented
-- 503 Bad sequence of commands
-- 504 Command parameter not implemented
-- 521 <Machine> does not accept mail.
-- 530 Must issue a STARTTLS command first. Encryption required for requested authentication mechanism.
-- 534 Authentication mechanism is too weak.
-- 538 Encryption required for requested authentication mechanism.
-- 550 Requested action not taken: mailbox unavailable [for , mailbox not found, no access]
-- 551 User not local; please try <forward-path>
-- 552 Requested mail action aborted: exceeded storage allocation
-- 553 Requested action not taken: mailbox name not allowed [for example, mailbox syntax incorrect]
-- 554 Transaction failed
This version allows for a customized seperator value. Using this function will allow you to
perform fixed width flat files by defining '' for no seperator and then RPAD/LPAD your columns as necessary.
Or use whatever seperator you wish to use, pipe, space, zeros, etc.
-- Example : This will generate a flat file which tabbed seperated
-- DECLARE
-- l_rows NUMBER;
-- l_sql VARCHAR2(32000);
-- BEGIN
-- l_sql := '
-- SELECT rpad(hou.NAME,70) udn_desc
-- , rpad(pcak.segment1,6) coid
-- , rpad(pcak.segment2,4) udn
-- FROM hr_all_organization_units hou, hr.pay_cost_allocation_keyflex pcak
-- WHERE TRUNC (SYSDATE) BETWEEN hou.date_from
-- AND NVL (hou.date_to, ''31-DEC-4712'')
-- AND pcak.cost_allocation_keyflex_id = hou.cost_allocation_keyflex_id
-- GROUP BY pcak.segment1, pcak.segment2, hou.NAME
-- ORDER BY 1, 2, 3
-- l_rows :=
-- dump_flatfile
-- (p_query =>
-- , p_dir => 'INTF000_TABLES'
-- , p_filename => 'test.csv'
-- , p_separator => ' ' -- <= tabbed 5 spaces between each column
-- , p_max_linesize => 32000
-- , p_mode => 'w' -- (w)rite mode or (a)ppend mode
-- END;
FUNCTION dump_flatfile (
p_query IN VARCHAR2
, p_dir IN VARCHAR2
, p_filename IN VARCHAR2
, p_separator IN VARCHAR2
, p_headers IN BOOLEAN DEFAULT FALSE
, p_trailing_separator IN BOOLEAN DEFAULT FALSE
, p_max_linesize IN NUMBER DEFAULT 32000
, p_mode IN VARCHAR2 DEFAULT 'w' )
RETURN NUMBER;
FUNCTION get_mail_address (
addr_list IN OUT VARCHAR2 )
RETURN VARCHAR2;
FUNCTION smtp_command (
command IN VARCHAR2
, ok IN VARCHAR2 DEFAULT '250'
, code OUT VARCHAR2
, DEBUG NUMBER DEFAULT 0 )
RETURN BOOLEAN;
FUNCTION query_server (
smtp_server VARCHAR2
, smtp_server_port PLS_INTEGER DEFAULT 25
, DEBUG NUMBER DEFAULT 0 )
RETURN BOOLEAN;
This procedure uses the UTL_TCP package to send an email message.
Up to three file names may be specified as attachments.
Written: Dave Wotton, 14/6/01 (Cambridge UK)
This script comes with no warranty or support. You are free to
modify it as you wish, but please retain an acknowledgement of
my original authorship.
Amended: Dave Wotton, 10/7/01
Now uses the utl_smtp.write_data() method to send the message,
eliminating the 32Kb message size constraint imposed by the
utl_smtp.data() procedure.
Amended: Dave Wotton, 20/7/01
Increased the v_line variable, which holds the file attachment
lines from 400 to 1000 bytes. This is the maximum supported
by RFC2821, The Simple Mail Transfer Protocol specification.
Amended: Dave Wotton, 24/7/01
Now inserts a blank line before each MIME boundary line. Some
mail-clients require this.
Amended: Dave Wotton, 4/10/01
Introduced a 'debug' parameter. Defaults to 0. If set to
non-zero then errors in opening files for attaching are
reported using dbms_output.put_line.
Include code to hand MS Windows style pathnames.
Amended: Barry Chase, 4/29/03
Added Priority to procedure and also X-Mailer ID.
Removed restrictions for email size limitation as well.
Emails are now formatted text messages, meaning you can
write your message in html format.
And finally, changed from using UTL_SMTP to UTL_TCP instead.
Amended: Barry Chase 11/10/2003
Added session timeout of 4 minutes to prevent hanging server connections
Amended: Barry Chase 12/04/2003
Added Date String so that it represents timezone of originating server
p_datestring
Amended: Barry Chase 03/01/2004
Added functionality to support binary attachments and remote attachments.
Its about 98% complete. Not work perfectly yet. Still trying to figure out
encoding to base64 or mime. Have a good start on it though.
04/12/2004
BCHASE :: Binary Support is fully functional now.
09/01/2005
BCHASE :: Modified attachment directories to use DBA_DIRECTORIES instead
of UTL_DIR in the Oracle initialization file.
02/22/2006
BCHASE :: Added variable length message email support (CLOB)
04/21/2006
BCHASE :: Expanded functionality to include Cc and Bcc
Also removed redundant calls from package. The single
mail_files command will handle flat files and binary files such as zip/pdf/etc.
SMTP Server and SMTP Server Port are parameters on the sendmail procedure now
as well.
Refer to http://home.clara.net/dwotton/dba/oracle_smtp.htm for more
details on the original source code.
For information on the enhanced mail_tools package as provided by Barry
Chase, refer to http://www.myoracleportal.com
/* Retrieves local binary file from database server.
* using DBMS_LOB commands and stores into BLOB
* return BLOB
FUNCTION get_local_binary_data (
p_dir IN VARCHAR2
, p_file IN VARCHAR2 )
RETURN BLOB;
/* Supports binary attachments and message of variable length. Uses CLOB.*/
-- DECLARE
-- t_blob BLOB;
-- BEGIN
-- Use the get_local_binary_data to collect your BLOB from the filesystem
-- or just load from a table where your BLOB is stored at, then just pass
-- as t_blob on the binaryfile parameter below. Remember to provide an
-- appropriate filename. Optionally, you can leave filename NULL and pass
-- the binaryfile parameter as EMPTY_BLOB() to send an email without an
-- attachment.
-- t_blob :=
-- mail_tools.get_local_binary_data
-- ( p_dir => 'INTF0047_TABLES'
--, p_file => 'test_file1.csv' );
-- mail_tools.sendmail
-- ( smtp_server => 'your.smtp.server'
-- , smtp_server_port => 25
-- , from_name => 'Email Address of Sender'
-- , to_name => 'list of TO email addresses separated by commas (,)'
-- , cc_name => 'list of CC email addresses separated by commas (,)'
-- , bcc_name => 'list of BCC email addresses separated by commas (,)'
-- , subject => 'Some brief Subject'
-- , MESSAGE => 'Your message goes here. Can include HTML code.'
-- , priority => '1-5 1 being the highest priority and 3 normal priority'
-- , filename => 'your.filename.txt or leave NULL'
-- , binaryfile => 'your blob is passed here otherwise leave as EMPTY_BLOB()
-- , DEBUG => 'Default is DBMS output otherwise pass a 1 to disable );
-- END;
PROCEDURE sendmail (
smtp_server VARCHAR2
, smtp_server_port PLS_INTEGER DEFAULT 25
, from_name VARCHAR2
, to_name VARCHAR2
, cc_name VARCHAR2 DEFAULT NULL
, bcc_name VARCHAR2 DEFAULT NULL
, subject VARCHAR2
, MESSAGE CLOB
, priority PLS_INTEGER DEFAULT NULL
, filename VARCHAR2 DEFAULT NULL
, binaryfile BLOB DEFAULT EMPTY_BLOB ( )
, DEBUG NUMBER DEFAULT 0 );
v_parm_value VARCHAR2 ( 4000 );
lbok BOOLEAN;
v_smtp_server VARCHAR2 ( 50 );
v_smtp_server_port NUMBER := 25;
crlf VARCHAR2 ( 10 ) := utl_tcp.crlf;
conn utl_tcp.connection;
p_debug_marker PLS_INTEGER := 0;
rc INTEGER;
p_from_name VARCHAR2 ( 100 );
p_to_name VARCHAR2 ( 4000 );
p_cc_name VARCHAR2 ( 4000 );
p_bcc_name VARCHAR2 ( 4000 );
p_subject VARCHAR2 ( 150 );
tx_timeout PLS_INTEGER := 240;
-- 240 Seconds (4 minutes);
p_datestring VARCHAR2 ( 100 )
:= 'Date: '
|| TO_CHAR ( SYSDATE, 'MM/DD/RR HH:MI AM' )
|| ' '
|| DBTIMEZONE
|| ' '
|| '(GMT'
|| DBTIMEZONE
|| ')';
-- Customize the signature that will appear in the email's MIME header.
-- Useful for versioning.
mailer_id CONSTANT VARCHAR2 ( 256 ) := 'Mailer by Oracle UTL_TCP';
max_base64_line_width CONSTANT PLS_INTEGER := 76 / 4 * 3;
END;
CREATE OR REPLACE PACKAGE BODY mail_tools
IS
PROCEDURE print_output (
p_message IN VARCHAR2 )
IS
BEGIN
dbms_output.put_line ( SUBSTR ( p_message
, 1
, 250 ));
IF LENGTH ( p_message ) > 250
THEN
dbms_output.put_line ( SUBSTR ( p_message
, 251
, 500 ));
END IF;
IF LENGTH ( p_message ) > 500
THEN
dbms_output.put_line ( SUBSTR ( p_message
, 501
, 750 ));
END IF;
IF LENGTH ( p_message ) > 750
THEN
dbms_output.put_line ( SUBSTR ( p_message
, 751
, 1000 ));
END IF;
EXCEPTION
WHEN OTHERS
THEN
NULL; -- Ignore errors... protect buffer overflow's etc.
END print_output;
FUNCTION dump_flatfile (
p_query IN VARCHAR2
, p_dir IN VARCHAR2
, p_filename IN VARCHAR2
, p_separator IN VARCHAR2
, p_headers IN BOOLEAN DEFAULT FALSE
, p_trailing_separator IN BOOLEAN DEFAULT FALSE
, p_max_linesize IN NUMBER DEFAULT 32000
, p_mode IN VARCHAR2 DEFAULT 'w' )
RETURN NUMBER
IS
l_output utl_file.file_type;
l_thecursor INTEGER DEFAULT dbms_sql.open_cursor;
l_columnvalue VARCHAR2 ( 4000 );
l_status INTEGER;
l_colcnt NUMBER DEFAULT 0;
l_cnt NUMBER DEFAULT 0;
l_separator VARCHAR2 ( 10 ) DEFAULT '';
l_line LONG;
l_desctbl dbms_sql.desc_tab;
v_sqlerrm VARCHAR2 ( 32000 );
l_mode CHAR ( 1 ) := 'w';
BEGIN
IF p_mode NOT IN ( 'w', 'a' )
THEN
l_mode := 'w';
ELSE
l_mode := p_mode;
END IF;
l_output := utl_file.fopen ( p_dir
, p_filename
, l_mode
, p_max_linesize );
dbms_sql.parse ( l_thecursor
, p_query
, dbms_sql.native );
dbms_sql.describe_columns ( l_thecursor
, l_colcnt
, l_desctbl );
FOR i IN 1 .. l_colcnt
LOOP
dbms_sql.define_column ( l_thecursor
, i
, l_columnvalue
, 4000 );
IF ( l_desctbl ( i ).col_type = 2 ) /* number type */
THEN
l_desctbl ( i ).col_max_len := l_desctbl ( i ).col_precision + 2;
ELSIF ( l_desctbl ( i ).col_type = 12 ) /* date type */
THEN
/* length of my date format */
l_desctbl ( i ).col_max_len := 20;
ELSIF ( l_desctbl ( i ).col_type = 8 ) /* LONG type */
THEN
l_desctbl ( i ).col_max_len := 2000;
END IF;
IF p_headers
THEN
utl_file.put ( l_output, l_separator || l_desctbl ( i ).col_name );
l_separator := p_separator;
END IF;
END LOOP;
IF p_trailing_separator
THEN
utl_file.put ( l_output, l_separator );
END IF;
IF p_headers
THEN
utl_file.new_line ( l_output );
END IF;
l_status := dbms_sql.EXECUTE ( l_thecursor );
LOOP
EXIT WHEN ( dbms_sql.fetch_rows ( l_thecursor ) <= 0 );
l_line := NULL;
l_separator := '';
FOR i IN 1 .. l_colcnt
LOOP
dbms_sql.COLUMN_VALUE ( l_thecursor
, i
, l_columnvalue );
IF NVL ( INSTR ( l_columnvalue, ',' ), 0 ) = 0
THEN
NULL;
ELSE
l_columnvalue := '"' || l_columnvalue || '"';
END IF;
utl_file.put ( l_output, l_separator || l_columnvalue );
l_separator := p_separator;
END LOOP;
IF p_trailing_separator
THEN
utl_file.put ( l_output, l_separator );
END IF;
utl_file.new_line ( l_output );
l_cnt := l_cnt + 1;
END LOOP;
dbms_sql.close_cursor ( l_thecursor );
utl_file.fclose ( l_output );
RETURN l_cnt;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
dbms_output.put_line ( 'NO_DATA_FOUND' );
utl_file.fclose ( l_output );
RETURN l_cnt;
WHEN utl_file.invalid_path
THEN
dbms_output.put_line ( 'UTL_FILE.INVALID_PATH' );
utl_file.fclose ( l_output );
RETURN l_cnt;
WHEN utl_file.read_error
THEN
dbms_output.put_line ( 'UTL_FILE.READ_ERROR' );
utl_file.fclose ( l_output );
RETURN l_cnt;
WHEN utl_file.write_error
THEN
dbms_output.put_line ( 'UTL_FILE.WRITE_ERROR' );
utl_file.fclose ( l_output );
RETURN l_cnt;
WHEN utl_file.invalid_mode
THEN
dbms_output.put_line ( 'UTL_FILE.INVALID_MODE' );
utl_file.fclose ( l_output );
RETURN l_cnt;
WHEN utl_file.invalid_filehandle
THEN
dbms_output.put_line ( 'UTL_FILE.INVALID_FILEHANDLE' );
utl_file.fclose ( l_output );
RETURN l_cnt;
WHEN utl_file.invalid_operation
THEN
dbms_output.put_line ( 'UTL_FILE.INVALID_OPERATION' );
utl_file.fclose ( l_output );
RETURN l_cnt;
WHEN utl_file.internal_error
THEN
dbms_output.put_line ( 'UTL_FILE.INTERNAL_ERROR' );
utl_file.fclose ( l_output );
RETURN l_cnt;
WHEN utl_file.invalid_maxlinesize
THEN
dbms_output.put_line ( 'UTL_FILE.INVALID_MAXLINESIZE' );
utl_file.fclose ( l_output );
RETURN l_cnt;
WHEN VALUE_ERROR
THEN
dbms_output.put_line ( 'UTL_FILE.VALUE_ERROR' );
utl_file.fclose ( l_output );
RETURN l_cnt;
WHEN OTHERS
THEN
hum_do.default_exception ( 'ERROR in dump_csv : ' );
utl_file.fclose ( l_output );
RETURN l_cnt;
END dump_flatfile;
-- Return the next email address in the list of email addresses, separated
-- by either a "," or a ";". The format of mailbox may be in one of these:
-- someone@some-domain
-- "Someone at some domain" <someone@some-domain>
-- Someone at some domain <someone@some-domain>
FUNCTION get_mail_address (
addr_list IN OUT VARCHAR2 )
RETURN VARCHAR2
IS
addr VARCHAR2 ( 256 );
i PLS_INTEGER;
FUNCTION lookup_unquoted_char (
str IN VARCHAR2
, chrs IN VARCHAR2 )
RETURN PLS_INTEGER
AS
c VARCHAR2 ( 5 );
i PLS_INTEGER;
len PLS_INTEGER;
inside_quote BOOLEAN;
BEGIN
inside_quote := FALSE;
i := 1;
len := LENGTH ( str );
WHILE ( i <= len )
LOOP
c := SUBSTR ( str
, i
, 1 );
IF ( inside_quote )
THEN
IF ( c = '"' )
THEN
inside_quote := FALSE;
ELSIF ( c = '\' )
THEN
i := i + 1;
-- Skip the quote character
END IF;
GOTO next_char;
END IF;
IF ( c = '"' )
THEN
inside_quote := TRUE;
GOTO next_char;
END IF;
IF ( INSTR ( chrs, c ) >= 1 )
THEN
RETURN i;
END IF;
<<next_char>>
i := i + 1;
END LOOP;
RETURN 0;
END;
BEGIN
addr_list := LTRIM ( addr_list );
i := lookup_unquoted_char ( addr_list, ',;' );
IF ( i >= 1 )
THEN
addr := SUBSTR ( addr_list
, 1
, i - 1 );
addr_list := SUBSTR ( addr_list, i + 1 );
ELSE
addr := addr_list;
addr_list := '';
END IF;
i := lookup_unquoted_char ( addr, '<' );
IF ( i >= 1 )
THEN
addr := SUBSTR ( addr, i + 1 );
i := INSTR ( addr, '>' );
IF ( i >= 1 )
THEN
addr := SUBSTR ( addr
, 1
, i - 1 );
END IF;
END IF;
RETURN addr;
END;
FUNCTION smtp_command (
command IN VARCHAR2
, ok IN VARCHAR2 DEFAULT '250'
, code OUT VARCHAR2
, DEBUG NUMBER DEFAULT 0 )
RETURN BOOLEAN
IS
response VARCHAR2 ( 3 );
p_output_message VARCHAR2 ( 255 );
len PLS_INTEGER;
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
len := utl_tcp.write_line ( conn, command );
p_output_message := SUBSTR ( utl_tcp.get_line ( conn, TRUE )
, 1
, 255 );
response := SUBSTR ( p_output_message
, 1
, 3 );
p_output_message :=
SUBSTR ( command || ' - ' || p_output_message
, 1
, 255 );
IF DEBUG = 1
THEN -- No Output
NULL;
ELSE -- Then DBMS_OUTPUT messages
print_output ( p_output_message );
END IF;
IF ( response <> ok )
THEN
code := response;
RETURN FALSE;
ELSE
code := response;
RETURN TRUE;
END IF;
EXCEPTION
WHEN OTHERS
THEN
p_output_message := SQLCODE || ' - ' || SQLERRM;
code := p_output_message;
RETURN FALSE;
END smtp_command;
FUNCTION query_server (
smtp_server VARCHAR2
, smtp_server_port PLS_INTEGER DEFAULT 25
, DEBUG NUMBER DEFAULT 0 )
RETURN BOOLEAN
IS
p_output_message VARCHAR2 ( 255 );
PRAGMA AUTONOMOUS_TRANSACTION;
err_noop EXCEPTION; -- SMTP code 250 not received
err_server_reject EXCEPTION;
-- SMTP code 421 means rejected
BEGIN
v_smtp_server := smtp_server;
v_smtp_server_port := smtp_server_port;
-- Open the SMTP connection ...
conn :=
utl_tcp.open_connection ( remote_host => v_smtp_server
, remote_port => v_smtp_server_port
, tx_timeout => tx_timeout );
----- OPEN SMTP PORT CONNECTION
rc := utl_tcp.write_line ( conn, 'HELO ' || v_smtp_server );
-- This will return a 250 OK response if your connection is valid
-- Initial handshaking ...
----- PERFORMS HANDSHAKING WITH SMTP SERVER
p_output_message := utl_tcp.get_line ( conn, TRUE );
IF DEBUG = 1
THEN -- No Output
NULL;
ELSE -- Then DBMS_OUTPUT messages
print_output ( p_output_message );
END IF;
IF SUBSTR ( p_output_message
, 1
, 3 ) = '421'
THEN
RAISE err_server_reject;
END IF;
-- NOOP THE SERVER
rc := utl_tcp.write_line ( conn, 'NOOP' );
-- This will return a 250 OK response if your connection is valid
-- Initial handshaking ...
----- PERFORMS NOOP WITH SMTP SERVER
p_output_message := utl_tcp.get_line ( conn, TRUE );
IF DEBUG = 1
THEN -- No Output
NULL;
ELSE -- Then DBMS_OUTPUT messages
print_output ( p_output_message );
END IF;
IF SUBSTR ( p_output_message
, 1
, 3 ) <> '250'
THEN
RAISE err_noop;
END IF;
rc := utl_tcp.write_line ( conn, 'QUIT' );
----- ENDS EMAIL TRANSACTION
BEGIN
FOR i_idx IN 1 .. 100
LOOP
p_output_message := utl_tcp.get_line ( conn, TRUE );
IF DEBUG = 1
THEN -- No Output
NULL;
ELSE -- Then DBMS_OUTPUT messages
print_output ( p_output_message );
END IF;
END LOOP;
EXCEPTION
WHEN OTHERS
THEN
IF DEBUG = 1
THEN -- No Output
NULL;
ELSE -- Then DBMS_OUTPUT messages
print_output ( p_output_message );
END IF;
END;
utl_tcp.close_connection ( conn ); ----- CLOSE SMTP PORT CONNECTION
RETURN TRUE;
EXCEPTION
WHEN err_server_reject
THEN
print_output ( 'ERROR -'
|| ' Server Rejected Connection ::'
|| ' SERVER_MSG := '
|| p_output_message );
RETURN FALSE;
WHEN err_noop
THEN
print_output ( 'ERROR -'
|| ' NOOP Check Failed ::'
|| ' SERVER_MSG := '
|| p_output_message );
utl_tcp.close_connection ( conn ); ----- CLOSE SMTP PORT CONNECTION
RETURN FALSE;
END query_server;
FUNCTION get_local_binary_data (
p_dir IN VARCHAR2
, p_file IN VARCHAR2 )
RETURN BLOB
IS
l_bfile BFILE;
l_data BLOB;
l_dbdir VARCHAR2 ( 100 ) := p_dir;
BEGIN
dbms_lob.createtemporary ( lob_loc => l_data
, CACHE => TRUE
, dur => dbms_lob.CALL );
l_bfile := BFILENAME ( l_dbdir, p_file );
dbms_lob.fileopen ( l_bfile, dbms_lob.file_readonly );
dbms_lob.loadfromfile ( l_data
, l_bfile
, dbms_lob.getlength ( l_bfile ));
dbms_lob.fileclose ( l_bfile );
RETURN l_data;
EXCEPTION
WHEN OTHERS
THEN
print_output ( 'Error during GET_LOCAL_BINARY_DATA :: '
|| SQLCODE
|| ' - '
|| SQLERRM );
dbms_lob.fileclose ( l_bfile );
RAISE;
END get_local_binary_data;
PROCEDURE attach_base64 (
conn IN OUT NOCOPY utl_tcp.connection
, DATA IN BLOB )
IS
i PLS_INTEGER;
len PLS_INTEGER;
l_result PLS_INTEGER;
l_buffer RAW ( 32767 );
l_pos INTEGER := 1;
l_blob_len INTEGER;
l_amount BINARY_INTEGER := 32767;
req utl_http.req;
resp utl_http.resp;
pdata RAW ( 200 );
BEGIN
-- Split the Base64-encoded attachment into multiple lines
-- In writing Base-64 encoded text following the MIME format below,
-- the MIME format requires that a long piece of data must be splitted
-- into multiple lines and each line of encoded data cannot exceed
-- 80 characters, including the new-line characters. Also, when
-- splitting the original data into pieces, the length of each chunk
-- of data before encoding must be a multiple of 3, except for the
-- last chunk. The constant MAX_BASE64_LINE_WIDTH
-- (76 / 4 * 3 = 57) is the maximum length (in bytes) of each chunk
-- of data before encoding.
l_blob_len := dbms_lob.getlength ( DATA );
WHILE l_pos < l_blob_len
LOOP
l_amount := max_base64_line_width;
dbms_lob.READ ( DATA
, l_amount
, l_pos
, l_buffer );
rc := utl_tcp.write_raw ( conn, utl_encode.base64_encode ( l_buffer ));
utl_tcp.FLUSH ( conn );
l_pos := l_pos + max_base64_line_width;
rc := utl_tcp.write_line ( conn, crlf );
END LOOP;
END attach_base64;
PROCEDURE sendmail (
smtp_server VARCHAR2
, smtp_server_port PLS_INTEGER DEFAULT 25
, from_name VARCHAR2
, to_name VARCHAR2
, cc_name VARCHAR2 DEFAULT NULL
, bcc_name VARCHAR2 DEFAULT NULL
, subject VARCHAR2
, MESSAGE CLOB
, priority PLS_INTEGER DEFAULT NULL
, filename VARCHAR2 DEFAULT NULL
, binaryfile BLOB DEFAULT EMPTY_BLOB ( )
, DEBUG NUMBER DEFAULT 0 )
IS
pos PLS_INTEGER := 1;
bytes_o_data CONSTANT PLS_INTEGER := 32767;
offset PLS_INTEGER := bytes_o_data;
msg_length CONSTANT PLS_INTEGER
:= dbms_lob.getlength ( MESSAGE );
v_line VARCHAR2 ( 32767 );
i BINARY_INTEGER;
v_slash_pos NUMBER;
my_recipients VARCHAR2 ( 32767 );
p_recipient_count PLS_INTEGER := 0;
p_output_message VARCHAR2 ( 2000 );
PRAGMA AUTONOMOUS_TRANSACTION;
err_server_reject EXCEPTION;
-- SMTP code 421 means rejected
err_message_send EXCEPTION; -- SMTP code must be 250
err_end_of_input EXCEPTION;
-- Used to signify last line of input retrieved
l_result PLS_INTEGER;
l_buffer_b RAW ( 32767 );
l_amount BINARY_INTEGER := 32767;
l_pos INTEGER := 1;
l_blob_len INTEGER;
l_blob BLOB;
g_debug BOOLEAN := TRUE;
i_base64 PLS_INTEGER;
len_base64 PLS_INTEGER;
BEGIN
v_smtp_server := smtp_server;
v_smtp_server_port := smtp_server_port;
l_blob := binaryfile;
-- Open the SMTP connection ...
conn :=
utl_tcp.open_connection ( remote_host => v_smtp_server
, remote_port => v_smtp_server_port
, tx_timeout => tx_timeout );
----- OPEN SMTP PORT CONNECTION
rc := utl_tcp.write_line ( conn, 'HELO ' || v_smtp_server );
-- Initial handshaking ...
----- PERFORMS HANDSHAKING WITH SMTP SERVER
p_output_message := utl_tcp.get_line ( conn, TRUE );
IF DEBUG = 1
THEN -- No Output
NULL;
ELSE -- Then DBMS_OUTPUT messages
print_output ( p_output_message );
END IF;
IF SUBSTR ( p_output_message
, 1
, 3 ) = '421'
THEN
RAISE err_server_reject;
ELSE
-- DBMS_OUTPUT.put_line (UTL_TCP.get_line (conn, TRUE));
rc := utl_tcp.write_line ( conn, 'MAIL FROM: ' || from_name );
----- MBOX SENDING THE EMAIL
p_output_message := utl_tcp.get_line ( conn, TRUE );
IF DEBUG = 1
THEN -- No Output
NULL;
ELSE -- Then DBMS_OUTPUT messages
print_output ( p_output_message );
END IF;
-- DBMS_OUTPUT.put_line (UTL_TCP.get_line (conn, TRUE));
-- rc := UTL_TCP.write_line (conn, 'RCPT TO: ' || to_name);
-- Specify recipient(s) of the email.
my_recipients := to_name;
WHILE ( my_recipients IS NOT NULL )
LOOP
BEGIN
rc :=
utl_tcp.write_line ( conn
, 'RCPT TO: '
|| get_mail_address ( my_recipients ));
p_recipient_count := p_recipient_count + 1;
END;
END LOOP;
-- DBMS_OUTPUT.put_line ('RCPT TO: COUNT ' || p_recipient_count);
----- MBOX RECV THE EMAIL
p_output_message := utl_tcp.get_line ( conn, TRUE );
IF DEBUG = 1
THEN -- No Output
NULL;
ELSE -- Then DBMS_OUTPUT messages
print_output ( p_output_message );
END IF;
-- DBMS_OUTPUT.put_line (UTL_TCP.get_line (conn, TRUE));
-- rc := UTL_TCP.write_line (conn, 'RCPT TO: ' || cc_name);
-- Specify cc recipient(s) of the email.
my_recipients := cc_name;
WHILE ( my_recipients IS NOT NULL )
LOOP
BEGIN
rc :=
utl_tcp.write_line ( conn
, 'RCPT TO: '
|| get_mail_address ( my_recipients ));
p_recipient_count := p_recipient_count + 1;
END;
END LOOP;
-- DBMS_OUTPUT.put_line ('RCPT TO: COUNT ' || p_recipient_count);
----- MBOX RECV THE EMAIL
p_output_message := utl_tcp.get_line ( conn, TRUE );
IF DEBUG = 1
THEN -- No Output
NULL;
ELSE -- Then DBMS_OUTPUT messages
print_output ( p_output_message );
END IF;
-- DBMS_OUTPUT.put_line (UTL_TCP.get_line (conn, TRUE));
-- rc := UTL_TCP.write_line (conn, 'RCPT TO: ' || bcc_name);
-- Specify bcc recipient(s) of the email.
my_recipients := bcc_name;
WHILE ( my_recipients IS NOT NULL )
LOOP
BEGIN
rc :=
utl_tcp.write_line ( conn
, 'RCPT TO: '
|| get_mail_address ( my_recipients ));
p_recipient_count := p_recipient_count + 1;
END;
END LOOP;
-- DBMS_OUTPUT.put_line ('RCPT TO: COUNT ' || p_recipient_count);
----- MBOX RECV THE EMAIL
p_output_message := utl_tcp.get_line ( conn, TRUE );
IF DEBUG = 1
THEN -- No Output
NULL;
ELSE -- Then DBMS_OUTPUT messages
print_output ( p_output_message );
END IF;
-- DBMS_OUTPUT.put_line (UTL_TCP.get_line (conn, TRUE));
rc := utl_tcp.write_line ( conn, 'DATA' );
----- EMAIL MSG BODY START
p_output_message := utl_tcp.get_line ( conn, TRUE );
IF DEBUG = 1
THEN -- No Output
NULL;
ELSE -- Then DBMS_OUTPUT messages
print_output ( p_output_message );
END IF;
-- DBMS_OUTPUT.put_line (UTL_TCP.get_line (conn, TRUE));
-- build the start of the mail message ...
rc := utl_tcp.write_line ( conn, p_datestring );
rc := utl_tcp.write_line ( conn, 'From: ' || from_name );
rc := utl_tcp.write_line ( conn, 'Subject: ' || subject );
rc := utl_tcp.write_line ( conn, 'To: ' || to_name );
IF cc_name IS NOT NULL
THEN
rc := utl_tcp.write_line ( conn, 'Cc: ' || cc_name );
END IF;
IF bcc_name IS NOT NULL
THEN
rc := utl_tcp.write_line ( conn, 'Bcc: ' || bcc_name );
END IF;
rc := utl_tcp.write_line ( conn, 'Mime-Version: 1.0' );
-- Set priority:
-- High Normal Low
-- 1 2 3 4 5
IF ( priority IS NOT NULL )
THEN
rc := utl_tcp.write_line ( conn, 'X-Priority: ' || priority );
END IF;
rc := utl_tcp.write_line ( conn, 'X-Mailer: ' || mailer_id );
rc :=
utl_tcp.write_line
( conn
, 'Content-Type: multipart/mixed; boundary="=_mixed 0052287A85256E75_="' );
rc := utl_tcp.write_line ( conn, '' );
rc :=
utl_tcp.write_line
( conn
, 'This is a Mime message, which your current mail reader may not' );
rc :=
utl_tcp.write_line
( conn
, 'understand. Parts of the message will appear as text. If the remainder' );
rc :=
utl_tcp.write_line
( conn
, 'appears as random characters in the message body, instead of as' );
rc :=
utl_tcp.write_line
( conn
, 'attachments, then you''ll have to extract these parts and decode them' );
rc := utl_tcp.write_line ( conn, 'manually.' );
rc := utl_tcp.write_line ( conn, '' );
rc := utl_tcp.write_line ( conn, '--=_mixed 0052287A85256E75_=' );
rc :=
utl_tcp.write_line ( conn
, 'Content-Type: text/html; charset=8859-1' );
rc := utl_tcp.write_line ( conn, '' );
rc := utl_tcp.write_line ( conn, '<html>' );
rc := utl_tcp.write_line ( conn, '<head>' );
rc :=
utl_tcp.write_line
( conn
, '<meta http-equiv="Content-Type" content="text/html;charset=8859-1">' );
rc := utl_tcp.write_line ( conn, '<title>' );
rc := utl_tcp.write_line ( conn, subject );
rc := utl_tcp.write_line ( conn, '</title>' );
rc := utl_tcp.write_line ( conn, '</head>' );
rc := utl_tcp.write_line ( conn, '<body>' );
WHILE pos < msg_length
LOOP
rc :=
utl_tcp.write_line ( conn
, dbms_lob.SUBSTR ( MESSAGE
, offset
, pos ));
pos := pos + offset;
offset := LEAST ( bytes_o_data, msg_length - offset );
END LOOP;
rc := utl_tcp.write_line ( conn, '<BR><BR>' );
rc := utl_tcp.write_line ( conn, '</body></html>' );
rc := utl_tcp.write_line ( conn, '' );
rc := utl_tcp.write_line ( conn, crlf );
-- Append the file BLOB ...
-- If the filename has been supplied ... it will fail if the BLOB is empty
IF filename IS NOT NULL
THEN
BEGIN
-- generate the MIME boundary line ...
rc :=
utl_tcp.write_line ( conn, '--=_mixed 0052287A85256E75_=' );
rc :=
utl_tcp.write_line
( conn
, 'Content-Type: application/octet-stream; name="'
|| filename
|| '"' );
rc :=
utl_tcp.write_line
( conn
, 'Content-Disposition: attachment; filename="'
|| filename
|| '"' );
rc :=
utl_tcp.write_line ( conn
, 'Content-Transfer-Encoding: base64' );
rc := utl_tcp.write_line ( conn, '' );
rc := utl_tcp.write_line ( conn, '' );
-- and append the file contents to the end of the message ...
-- Go get the file and the loop through blob and attach data
-- and append the file contents to the end of the message ...
attach_base64 ( conn => conn
, DATA => l_blob );
EXCEPTION
WHEN OTHERS
THEN
p_output_message :=
'Error in attaching file '
|| filename
|| ' :: '
|| SQLCODE
|| ' - '
|| SQLERRM;
IF DEBUG = 1
THEN -- No Output
NULL;
ELSE -- Then DBMS_OUTPUT messages
print_output ( p_output_message );
END IF;
RAISE err_message_send;
END;
END IF;
rc := utl_tcp.write_line ( conn, '' );
-- append the final boundary line ...
rc := utl_tcp.write_line ( conn, '' );
rc := utl_tcp.write_line ( conn, '--=_mixed 0052287A85256E75_=--' );
rc := utl_tcp.write_line ( conn, '' );
-- and close the SMTP connection ...
rc := utl_tcp.write_line ( conn, '.' );
----- EMAIL MESSAGE BODY END
p_output_message := utl_tcp.get_line ( conn, TRUE );
IF DEBUG = 1
THEN -- No Output
NULL;
ELSE -- Then DBMS_OUTPUT messages
print_output ( p_output_message );
END IF;
-- DBMS_OUTPUT.put_line (UTL_TCP.get_line (conn, TRUE));
rc := utl_tcp.write_line ( conn, 'QUIT' );
----- ENDS EMAIL TRANSACTION
p_output_message := utl_tcp.get_line ( conn, TRUE );
-- Capture '.' Message sent dialog
IF DEBUG = 1
THEN -- No Output
NULL;
ELSE -- Then DBMS_OUTPUT messages
print_output ( p_output_message );
END IF;
BEGIN
FOR i_idx IN 1 .. 100
LOOP
p_output_message := utl_tcp.get_line ( conn, TRUE );
IF DEBUG = 1
THEN -- No Output
NULL;
ELSE -- Then DBMS_OUTPUT messages
print_output ( p_output_message );
END IF;
END LOOP;
EXCEPTION
WHEN OTHERS
THEN
IF DEBUG = 1
THEN -- No Output
NULL;
ELSE -- Then DBMS_OUTPUT messages
print_output ( p_output_message );
END IF;
END;
END IF; -- err_server_reject
utl_tcp.close_connection ( conn ); ----- CLOSE SMTP PORT CONNECTION
EXCEPTION
WHEN err_message_send
THEN
print_output ( CHR ( 10 )
|| CHR ( 10 )
|| 'ERROR -'
|| ' Message was not submitted for delivery' );
print_output ( ' [FROM_NAME := ' || from_name || '] ' );
print_output ( ' [TO_NAME := ' || to_name || '] ' );
print_output ( ' [CC_NAME := ' || cc_name || '] ' );
print_output ( ' [BCC_NAME := ' || bcc_name || '] ' );
print_output ( ' [SUBJECT := ' || subject || '] ' );
print_output ( ' SERVER_MSG := ' || p_output_message );
utl_tcp.close_connection ( conn ); ----- CLOSE SMTP PORT CONNECTION
WHEN err_server_reject
THEN
print_output ( CHR ( 10 )
|| CHR ( 10 )
|| 'ERROR -'
|| ' Server Rejected Email' );
print_output ( ' [FROM_NAME := ' || from_name || '] ' );
print_output ( ' [TO_NAME := ' || to_name || '] ' );
print_output ( ' [CC_NAME := ' || cc_name || '] ' );
print_output ( ' [BCC_NAME := ' || bcc_name || '] ' );
print_output ( ' [SUBJECT := ' || subject || '] ' );
print_output ( ' SERVER_MSG := ' || p_output_message );
WHEN OTHERS
THEN
print_output ( CHR ( 10 )
|| CHR ( 10 )
|| 'ERROR :: '
|| SQLCODE
|| ' - '
|| SQLERRM );
print_output ( ' [FROM_NAME := ' || from_name || '] ' );
print_output ( ' [TO_NAME := ' || to_name || '] ' );
print_output ( ' [CC_NAME := ' || cc_name || '] ' );
print_output ( ' [BCC_NAME := ' || bcc_name || '] ' );
print_output ( ' [SUBJECT := ' || subject || '] ' );
print_output ( ' SERVER_MSG := ' || p_output_message );
END sendmail;
END;
/Perhaps your new SMTP server requires a more secure form of authentication than AUTH LOGIN. If you telnet to this new SMTP server on port 25 you should be issue the HELO or EHLO command to find out what AUTH mechanisms the server supports. You could then alter your code to use one of the supported authentication mechanisms.
Maybe you are looking for
-
An email keeps crashing mail whenever it is selected and I am unable to delete it.
I have been able to remove it from the other email account that it was initially sent to. I deleted the account from mail and then set it up again but this particular email has re-appeared still causing my mac to crash on each occasion of the email
-
Since 10.2, youtube is not working...
hi, i just install flash 10.2 and youtube is not working. i have a black rectangle instead of the video... i can see the animation on your flash site. and the strangest is that i can play youtube video, when they are embed in a website... thanks in a
-
Show / Hide characteristic in Bex Web
Hi, since we use a fixed Template without the possibility to choose the characterstics / key figures from the Navigational Menu the question is if its possible to show / hide a characteristic in Bex Web via a button in the template. Thanks for help,
-
Data Guard - Steps to install Physical standby database in an RHEL 5.6 x86
HI Team, I need to install Physical standby database in a OS installed from factory with most basic packages. Please find the info in detail Standby Server : Database Version : 10g Release 2 Operating System : Red Hat Enterprise Linux Server release
-
hai , could anyone give the important tables in srm shopping carts and purchasing documents.could i see the tables in BBP_PD. thanks and regards, chakradhar