sql statment in email messge utl_mail.send - oracle

I am sending emails true oracle apex which works fine. what i need however is to have an sql count statement in the message of the email.
what i have is
begin
utl_mail.send(sender => 'a#test.com',
recipients =>'a#test.com',
subject => 'FileRequest',
message => 'select count(filenumber) where status is assigned' files from registry '||:p5_filenumber ||''||' ' ||:p5_filename || ' has now been assigned to the ' || :p5_department || '');
end;
which obviously is not working
what i will like to see is
begin
utl_mail.send(sender => 'a#test.com',
recipients =>'a#test.com',
subject => 'FileRequest',
message => 5 files from registry '||:p5_filenumber ||''||' ' ||:p5_filename || ' has now been assigned to the ' || :p5_department || '');
end;

Compute the value BEFORE sending the mail. Something like this:
declare
l_cnt number;
l_msg varchar2(200);
begin
-- select number you're interested in
select count(*)
into l_cnt
from some_table
where some_conditions;
-- compose the message
l_msg := l_cnt ||' files from registry ...';
-- send mail
utl_mail.send(sender => 'a#test.com',
recipients => 'a#test.com',
subject => 'FileRequest',
message => l_msg);
end;

Related

Apex page DML Mail Alert Trigger

I have a Trigger and Function which sends mail with "updated" column(s),
when i am updating in my back-end (sql developer), i receive a mail with that particular column.
But when i do UPDATE directly through Apex Page i get mail listing all columns names indicating all are updated.
Function Code:
create or replace function SNAP_FUN(inTableName in varchar2) return varchar2 is
result varchar2(4000);
sep varchar2(2) := null;
begin
for c in (select column_name from user_tab_columns where table_name = inTableName) loop
if updating(c.column_name) then
result := result || sep || c.column_name;
sep := ', ';
end if;
end loop;
return result;
end;
/
Trigger
create or replace trigger SNAP_TRIG
after update on dw.W_SUPPL_SNAPSHOT_CONTROL_G
for each row
DECLARE X VARCHAR2(4000);
begin
begin
X:=X||('Updated:' || snap_fun('W_SUPPL_SNAPSHOT_CONTROL_G'));
end;
dlr_send_mail('***.com', 'SUPPLEMENTAL_SNAPSHOT', 'These are the column changes observed' || X
, '****', 'host')
end;

ORA 6502 character string buffer too small

I am a newbie in PL/SQL
I have an PL SQL. And im getting an error shown in the title. ORA 6502 character string buffer too small.
create or replace
PROCEDURE MailSender IS
tmpVar VARCHAR2(2048);
BEGIN
FOR cur_rec IN
(SELECT * FROM dom_email1 where rownum <= 50 and eto is not null ORDER BY eid asc)
LOOP
tmpVar := ltrim(cur_rec.ETO, ' ; ');
tmpVar := rtrim(tmpVar, '; ');
tmpVar := rtrim(tmpVar, ' ');
DOMSYS_EMAIL.SEND_EMAIL(msg_from => 'noreply#gmail.com'
, msg_tos => tmpVar
, msg_subject => cur_rec.SUBJ
, msg_text => cur_rec.MSG
, mailhost => '10.63.17.38');
UPDATE DOM_EMAIL1 SET eid='1' WHERE eid= cur_rec.EID;
END LOOP;
DELETE FROM DOM_EMAIL1 WHERE eid='1';
EXCEPTION
WHEN NO_DATA_FOUND THEN
NULL;
WHEN OTHERS THEN
-- Consider logging the error and then re-raise
RAISE;
END MailSender;
Issue is due to the size is not satisfied for any of the below variables/cursor value you are passing in your procedure
tmpVar
cur_rec.SUBJ
cur_rec.MSG
Add the below line in your procedure before send mail (DOMSYS_EMAIL.SEND_EMAIL) to validate the size of each value you passed and check whether it satisfies the parameter size limit of the DOMSYS_EMAIL.SEND_EMAIL procedure
dbms_output.put_line('tmpVar :' || length(tmpVar) ||' - '|| 'cur_rec.SUBJ :'|| length(cur_rec.SUBJ) ||' - '|| 'cur_rec.MSG :' || length(cur_rec.MSG));
For varchar2,you can update the size limit if required after validation

Send SQL query output as CSV attachment (pl/sql)

I have a pl/sql query and I want it's output to be sent in email in CSV format straightaway. I have no directory to first create and save a CSV file and then pick it up to send as an attachment.
Please help with your inputs as I am not able to get away.
Regards,
Sachin
Finally figured out a solution with the help of pointers received and providing the same to further help in case someone else needs in future.
My problem was that I was mostly seeing the examples where i could either save the file on a directory or pick the file from a directory to send as an attchment but I had no provision of directory and I wanted query result to be put in CSV and sent in email dynamically. So here is the complete solution.
CREATE OR REPLACE PROCEDURE SEND_CSV_ATTACHMENT AS
v_sender VARCHAR2(130);
v_recipients VARCHAR2(4000);
v_cc VARCHAR2(4000);
v_bcc VARCHAR2(2000);
v_subj VARCHAR2(200);
v_msg CLOB;
v_mime VARCHAR2(40);
v_tbl VARCHAR2(20000);
c_cr_lf CONSTANT CHAR (2) := (CHR (13) || CHR (10)); -- Carriage Return/Line Feed characters for formatting text emails
v_loop_count PLS_INTEGER := 0;
v_attachment CLOB;
v_block_qry VARCHAR2(3000);
v_block_row VARCHAR2(6000);
TYPE bl_cur IS REF CURSOR;
v_result bl_cur;
v_rowcount NUMBER;
errMsg VARCHAR2(15000);
BEGIN
v_sender := 'somesender#xyzcommunications.com';
SELECT NVL(EMAIL_LIST, 'someone#abcd.com')
FROM
(
SELECT LISTAGG(EMAIL_ID, ',') WITHIN GROUP (ORDER BY EMAIL_ID) AS EMAIL_LIST FROM RECIPEINTS_TABLE WHERE SEND_TO = 1 AND IS_ACTIVE = 1
);
SELECT NVL(EMAIL_LIST, 'someone#abcd.com')
FROM
(
SELECT LISTAGG(EMAIL_ID, ',') WITHIN GROUP (ORDER BY EMAIL_ID) AS EMAIL_LIST FROM RECIPEINTS_TABLE WHERE SEND_CC = 1 AND IS_ACTIVE = 1
);
v_bcc := 'someone#abcd.com';
-- Generate attachment - Begin
v_attachment := '"COL1", "COL2"' || CHR(13) || CHR(10);
v_block_qry := 'SELECT ''"'' || COL1 || ''", "'' || COL2 || ''"'' AS ROWTXT
FROM MY_TABLE';
OPEN v_result FOR v_block_qry;
LOOP
v_rowcount := v_result%ROWCOUNT;
FETCH v_result INTO v_block_row;
EXIT WHEN v_result%NOTFOUND;
v_attachment := v_attachment || v_block_row || chr(13) || chr(10);
END LOOP;
CLOSE v_result;
-- Generate attachment - End
v_subj:= 'MAIL_SUBJECT ' || TO_CHAR(TRUNC(SYSDATE-1), 'YYYY-MM-DD');
UTL_MAIL.send_attach_varchar2(sender => v_sender,
recipients => v_recipients,
cc => v_cc,
bcc => v_bcc,
subject => v_subj,
message => v_msg,
mime_type => 'text/html; charset=us-ascii', -- send html e-mail
attachment => v_attachment,
att_inline => FALSE,
att_filename => 'Change_Report' || TO_CHAR(TRUNC(SYSDATE-1), 'YYYY-MM-DD') || '.csv');
EXCEPTION
WHEN OTHERS THEN
errMsg := SQLERRM;
SEND_MAIL_HTML ('someone#abcd.com', NULL, NULL, errMsg, 'SEND_MAIL ERROR: ' || errMsg);
END SEND_CSV_ATTACHMENT;
You may create such a procedure :
create or replace procedure prFileSend is
v_mail_owner varchar2(100):='myname#someComp.com';
v_url varchar2(4000);
v_rep varchar2(4000);
delimiter varchar2(1) := chr(38);
begin
for c in ( select * from myTable )
loop
begin
v_url := 'http://www.mycompany.com/einfo/default.aspx?email='||c.email || delimiter || 'p1=' || c.col1 || delimiter ||'p2='||c.col2;
v_rep := utl_http.request(utl_url.escape(v_url, false,'ISO-8859-9'));
end;
end loop;
exception
when others then
prErrorMsgSend(v_mail_owner,'Error : ' || sqlerrm); -- a function like this one which sends an error message back to you.
end;
and create a scheduler job
begin
dbms_scheduler.create_job (
job_name => 'jbFileSend ',
job_type => 'STORED_PROCEDURE',
job_action => 'prFileSend',
start_date => '22-jan-2018 09:00:00 am',
repeat_interval => 'FREQ=DAILY; INTERVAL=1',
comments => 'Sending Every day'
enabled => true);
end;
working every day as an example.

Job/Procedure to PL/SQL execution?

I've this PL/SQL and is working correctly also email is sended.
BEGIN
FOR cur_rec IN
(select JOB, SCHEMA_USER, WHAT from dba_jobs where Broken = 'Y') LOOP
BEGIN
SCHEMA2.send_mail(
p_to => 'receive#test.com',
p_from => 'send#test.com',
p_subject => 'JOB Report',
p_message => 'Job name is: ' || cur_rec.what,
p_smtp_host => 'webmail.test.com');
END;
END LOOP;
END;
/
I need to schedule that PL/SQL execution every 4 hours, But I don't know how to create a job or a procedure with that code, I've tried a lot but still saying:
Completed with warnings
Any help to construct the job or/and procedure is appreciated.
begin
DBMS_SCHEDULER.CREATE_JOB (
job_name=>'my_job',
job_type=>'PLSQL_BLOCK',
job_action=>
'BEGIN
FOR cur_rec IN
(select JOB, SCHEMA_USER, WHAT from dba_jobs where Broken = ''Y'') LOOP
BEGIN
SCHEMA2.send_mail(
p_to => ''receive#test.com'',
p_from => ''send#test.com'',
p_subject => ''JOB Report'',
p_message => ''Job name is: '' || cur_rec.what,
p_smtp_host => ''webmail.test.com'');
END;
END LOOP;
END;',
start_date=>sysdate+1, --start tomorrow at this time
repeat_interval=>'FREQ=HOURLY; INTERVAL=4', --repeat every 4 hours
auto_drop=>false
);
end;
/
Review documentation for additional options.. create job

Send Email Using PLSQL

I want to Send Email via gmail or yahoo host using PL_SQL, i searched in google and find SMT.Mail package but it did't work for me, Please any one can guide me how will i achieve this goal ?
CREATE OR REPLACE PROCEDURE
send_mail (sender IN VARCHAR2,
recipient IN VARCHAR2,
message IN VARCHAR2,
nStatus OUT NUMBER)
IS
mailhost VARCHAR2(30) := 'smtp.gmail.com '; -- host mail addr
mail_conn utl_smtp.connection;
BEGIN
nStatus := 0;
mail_conn := utl_smtp.open_connection(mailhost, 25);
utl_smtp.helo(mail_conn, mailhost);
utl_smtp.mail(mail_conn, sender);
utl_smtp.rcpt(mail_conn, recipient);
utl_smtp.data(mail_conn, message);
utl_smtp.quit(mail_conn);
EXCEPTION
WHEN OTHERS THEN
nStatus := SQLCODE;
END send_mail;
when i test this procedure I get: ORA-29278: SMTP transient error: 421 Service not available
You missed your authentication at the server, see AUTH Function and Procedure
However, I do not know whether gmail allows to use port 25 which is not secure by default.
My experience has been that the utl_mail package is much easier to use. Here is a silly example:
BEGIN
UTL_MAIL.send (sender => 'bighearted#somewhere.com'
, recipients => 'receiver#footballreceiver.com'
, subject => 'Goofy Messages'
, MESSAGE => 'Please don''t send any more goofy messages'
, mime_type => 'text/html; charset=us-ascii');
END;
You must set the system parameter smtp_out_server to the name of your email server.
With Oracle 11G R2 and beyond, you must set up the proper access control list (ACL) for this to work. This is the code that I use to do so.
DECLARE
-- ACL name to be used for email access reuse the same value for all
-- future calls
l_acl VARCHAR2 (30) := 'utl_smtp.xml';
-- Oracle user to be given permission to send email
l_principal VARCHAR2 (30) := 'CEAADMIN';
-- Name of email server
g_mailhost VARCHAR2 (60) := 'mail.yourserver.com';
l_cnt INTEGER;
PROCEDURE validate_smtp_server
AS
l_value v$parameter.VALUE%TYPE;
l_parameter v$parameter.name%TYPE := 'smtp_out_server';
BEGIN
SELECT VALUE
INTO l_value
FROM v$parameter
WHERE name = l_parameter;
IF l_value IS NULL
THEN
raise_application_error (
-20001
, 'Oracle parameter '
|| l_parameter
|| ' has not been set'
|| UTL_TCP.crlf
|| 'it s/b mail.yourserver.com'
);
END IF;
DBMS_OUTPUT.put_line ('parameter ' || l_parameter || ' value is ' || l_value);
END validate_smtp_server;
PROCEDURE create_if_needed (p_acl IN VARCHAR2)
AS
l_cnt INTEGER;
BEGIN
SELECT COUNT (*) c
INTO l_cnt
FROM dba_network_acls a
WHERE SUBSTR (acl, INSTR (acl, '/', -1) + 1) = p_acl;
IF l_cnt = 0
THEN
DBMS_OUTPUT.put_line ('creating acl ' || p_acl);
DBMS_NETWORK_ACL_ADMIN.create_acl (
acl => p_acl
, description => 'Allow use of utl_smtp'
, principal => l_principal
, is_grant => TRUE
, privilege => 'connect'
);
DBMS_NETWORK_ACL_ADMIN.assign_acl (acl => p_acl, HOST => g_mailhost);
COMMIT;
ELSE
DBMS_OUTPUT.put_line (p_acl || ' acl already exists');
END IF;
END create_if_needed;
PROCEDURE add_if_needed (
p_principal IN VARCHAR2
, p_acl IN VARCHAR2
)
AS
l_cnt INTEGER;
BEGIN
SELECT COUNT (*) c
INTO l_cnt
FROM dba_network_acl_privileges
WHERE SUBSTR (acl, INSTR (acl, '/', -1) + 1) = p_acl
AND principal = p_principal;
IF l_cnt = 0
THEN
DBMS_NETWORK_ACL_ADMIN.add_privilege (
acl => 'utl_smtp.xml'
, principal => p_principal
, is_grant => TRUE
, privilege => 'connect'
);
COMMIT;
DBMS_OUTPUT.put_line ('access to ' || p_acl || ' added for ' || p_principal);
ELSE
DBMS_OUTPUT.put_line (p_principal || ' already has access to ' || p_acl);
END IF;
END add_if_needed;
BEGIN
EXECUTE IMMEDIATE 'grant execute on utl_mail to ' || l_principal;
create_if_needed (p_acl => l_acl);
add_if_needed (p_principal => l_principal, p_acl => l_acl);
DBMS_OUTPUT.put_line ('Verification SQL:');
DBMS_OUTPUT.put_line (' SELECT * FROM dba_network_acls;');
DBMS_OUTPUT.put_line (' SELECT * FROM dba_network_acl_privileges;');
COMMIT;
validate_smtp_server;
END;

Resources