I have a button that runs the apex_mail.send functionality when clicked.
The code I have is the following:
DECLARE
l_body CLOB;
V_ID_MX number;
V_REQUESTER VARCHAR2(1000);
v_user varchar2(300);
BEGIN
--Basically selects the latest added row on my table:
SELECT max(id) INTO V_ID_MX FROM My_Table;
--Line to remove the #mail.com from user email:
select INITCAP(replace(regexp_replace(rep_assigned,'#[a-zA-z0-9.]*',''), '.', ' ')) into
v_user from My_table WHERE ID = V_ID_MX;
--Assigning Rep email to the v_requester variable:
select rep_assigned into V_REQUESTER from My_Table WHERE ID = V_ID_MX;
l_body := 'Hi ' || v_user ||',' || utl_tcp.crlf;
l_body := l_body || utl_tcp.crlf;
l_body := l_body || utl_tcp.crlf;
l_body := l_body || 'Please review latest added row.' ||utl_tcp.crlf;
l_body := l_body || utl_tcp.crlf;
l_body := l_body || 'ID: '|| V_ID_MX ||utl_tcp.crlf;
l_body := l_body || utl_tcp.crlf;
l_body := l_body || utl_tcp.crlf;
l_body := l_body || 'Thank you' || utl_tcp.crlf;
apex_mail.send(
p_to => V_REQUESTER,
p_from => 'generic_email#mail.com',
p_body => l_body,
p_subj => 'Some Subject';
END;
It works perfectly, with one annoying exception: it sends the same email twice.
Does anybody know how to avoid this email duplicity?
Thanks
Related
Need help in sending excel file as an attachment which is stored in directory of a server.
I have a procedure which writes a file to server and need to send it as as attachement with HTML body message which includes multiple tables and excel attachement. but i am quite stuck in attachment part for now!.
CREATE OR REPLACE PROCEDURE p_send_email_with_attach as
file_handle utl_file.file_type;
output VARCHAR2(32767);
attachment_text VARCHAR2(32767);
v_dir VARCHAR2(300) := 'RPT_DIR';
v_recipients VARCHAR2(2000) := 'abc#gmail.com';
v_sub VARCHAR2(300) := 'Hello';
v_smtp_server VARCHAR2(255) := 'mailhost';
conn utl_smtp.connection;
c_mime_boundary CONSTANT VARCHAR2(256) := 'the boundary can be almost anything';
v_from_name VARCHAR2(100) := 'xyz#yahoo.com';
BEGIN
file_handle := utl_file.fopen(
location => v_dir,
filename => 'My_First_CSV.CSV',
open_mode => 'R'
);
LOOP
BEGIN
utl_file.get_line(
file_handle,
output
); -- we read the file, line by line
attachment_text := attachment_text || utl_tcp.crlf; --and store every line in
the attachment_text variable, separated by a ?new line? character.
EXCEPTION
WHEN no_data_found THEN
EXIT;
END;
END LOOP;
utl_file.fclose(file_handle);
conn := utl_smtp.open_connection('mailhost');
utl_smtp.helo(conn, 'mailhost');
utl_smtp.mail(conn, v_from_name);
FOR cur_r IN (
SELECT level AS id, regexp_substr(email_id, '[^;]+', 1, level) AS v_recipient
FROM
email_address
CONNECT BY regexp_substr( email_id, '[^;]+', 1, level) IS NOT NULL
) LOOP
utl_smtp.rcpt(conn,cur_r.v_recipient);
END LOOP;
UTL_SMTP.write_data(conn, '--' || c_mime_boundary || UTL_TCP.crlf);
UTL_SMTP.write_data(conn, 'Content-Type: text/plain' || UTL_TCP.crlf);
UTL_SMTP.write_data(
conn,
'Content-Disposition: attachment; filename="' || 'My_First_CSV.CSV' || '"' || UTL_TCP.crlf
);
utl_smtp.open_data(conn);
EXCEPTION
WHEN OTHERS THEN
raise_application_error(
-20001,
'Error: ' || sqlerrm
);
END;
i beleive i am missing something while writing, kindly help in fixing this. thanks :)
In the below PL/SQL SP Cursor output store as HTML table and send as Excel file as attachment.
But I am getting the following error, even if I take CLOB datatype:
ORA-06502: PL/SQL: numeric or value error: raw variable length too long
ORA-06512: at "SYS.UTL_MAIL", line 654
ORA-06512: at "SYS.UTL_MAIL", line 739
CREATE OR REPLACE PROCEDURE sp_send_mail_with_attch (
p_mode char,
p_message VARCHAR2 := '.',
p_subject VARCHAR2 := '.',
p_from VARCHAR2 := 'ITTEAM'
) AS
msg_from VARCHAR2(50);
msg_to VARCHAR2(4000);
message_to VARCHAR2(50);
mailhost VARCHAR2(30);
mailport VARCHAR2(20);
crlf VARCHAR2(2) := chr(13)|| chr(10);
msg_subject VARCHAR2(250);
tablehead VARCHAR2(32767);
message VARCHAR2(32767);
mainmsg VARCHAR2(32767);
v_errortext VARCHAR2(200);
v_errormsg VARCHAR2(200) := ' ';
v_error VARCHAR2(2000) := ' ';
mail_conn utl_smtp.connection;
attachment_text clob;
v_messageatt clob;
v_filedate varchar2(100);
CURSOR main_cursor IS
select customer_id,customer_name, to_char(validity_date,'DD-MON-YYYY') validity_date
FROM
(select( trunc(validity_date) - trunc(sysdate) ) datediff,
a.* from table_name a WHERE lei_flag = 'Y'
) lei;
main_cursor_var main_cursor%rowtype;
begin
SELECT a.smtpserver,a.smtpserverport,'' toaddress,'' fromaddress
into mailhost,mailport,message_to,msg_from
from emailsettingtable a
WHERE ROWNUM < 2;
msg_from := p_from;
msg_to := '';
IF p_mode = '89' THEN
dbms_output.put_line('89');
msg_to := message_to;
msg_subject := 'CUSTOMER report';
message := '<html><head></head>';
message := message || '<body>';
message := message || 'Dear Sir/Madam,<br>';
message := message || 'Please find attached of Cutomer LEI Expiry<br>';
message := message || '<table>';
v_messageatt := '<html><head></head>';
v_messageatt := v_messageatt || '<body><br>';
v_messageatt := v_messageatt || '<table>';
OPEN main_cursor;
LOOP
FETCH main_cursor INTO main_cursor_var;
EXIT WHEN
( main_cursor%notfound );
IF main_cursor%rowcount = 1 THEN
v_messageatt := v_messageatt || '<tr><th>CUSTOMER ID</th><th>CUSTOMER NAME</th><th>VALIDITY DATE</th></tr>';
END IF;
v_messageatt := v_messageatt || '<tr>';
v_messageatt := v_messageatt|| '<td>'|| main_cursor%rowcount|| '</td>';
v_messageatt := v_messageatt|| '<td>'|| main_cursor_var.customer_id|| '</td>';
v_messageatt := v_messageatt || '<td>'|| main_cursor_var.CUSTOMER_NAME||'</td>';
v_messageatt := v_messageatt || '<td>'|| main_cursor_var.validity_date||'</td>';
v_messageatt := v_messageatt || '</tr>';
attachment_text := v_messageatt;
END LOOP;
CLOSE main_cursor;
dbms_output.put_line('89');
v_messageatt := v_messageatt || '</table>';
message := message || '</table>';
message := message|| '<br>'|| 'Regards,<br>'|| 'IT Team <br><br> ';
message := message || '</body></html>';
mainmsg := message;
dbms_output.put_line(message);
END IF;
dbms_output.put_line('msg_subject-->' || msg_subject);
dbms_output.put_line('MESSAGE-->' || message);
IF p_mode = '89' THEN
--msg_subject := 'LERM Counterparty - Exposure Data Uploaded sucessfully ...';
msg_to := msg_to || 'abc#gmail.com';
END IF;
select to_char(sysdate,'DD_MON_YYYYHH24:MI:SS') into v_filedate
from dual;
sys.utl_mail.send_attach_raw(
sender => msg_from,
recipients => msg_to,
cc => '',
bcc => '',
subject => msg_subject,
message => mainmsg,
mime_type => 'text/html',
priority => 1,
attachment => utl_raw.cast_to_raw(attachment_text),
att_inline => true,
att_mime_type => 'text/plain; charset=us-ascii',
att_filename => 'filename_'|| v_filedate|| '.xls',
replyto => ''
);
dbms_output.put_line('2');
msg_to := '';
dbms_output.put_line('Send Sucessfully ........');
EXCEPTION
WHEN others THEN
v_errortext := substr(sqlerrm,1,200);
dbms_output.put_line(sqlerrm);
END;
You cannot create a HTML document (using <table>..<tr>, etc.) and convert this simple to RAW. Creating a Excel file purely in PL/SQL is quite painful, perhaps you will find a solution here on SO. One solution is to call an external Java procedure which generates the Excel sheet.
In general you can format your e-mail as HTML with well known formation capabilities or you can attach a binary Excel file.
Attachment for utl_mail.send_attach_raw is limited to 32k, it also have some other limitation. I recommend to use UTL_SMTP, this package is more complex to use but it gives you much more flexibility. Have a look at how to export data from log table to email body in oracle to see a full featured example.
What is the syntax for sending emails to multiple recipients with APEX_MAIL.SEND?
The official page, https://docs.oracle.com/cd/E14373_01/apirefs.32/e13369/apex_mail.htm#AEAPI342, says; p_to
Valid email address to which the email will be sent (required). For multiple email addresses, use a comma-separated list However doesn't show an example of the syntax.
Using the example they give does anyone know the syntax?
DECLARE
l_body CLOB;
BEGIN
l_body := 'Thank you for your interest in the APEX_MAIL
package.'||utl_tcp.crlf||utl_tcp.crlf;
l_body := l_body ||' Sincerely,'||utl_tcp.crlf;
l_body := l_body ||' The APEX Dev Team'||utl_tcp.crlf;
apex_mail.send(
p_to => 'some_user#somewhere.com', -- change to your email address
p_from => 'some_sender#somewhere.com', -- change to a real senders email address
p_body => l_body,
p_subj => 'APEX_MAIL Package - Plain Text message');
END;
/
You just need to put multiple comma separated mail addresses into the p_to parameter.
See this example:
DECLARE
l_body CLOB;
BEGIN
l_body := 'Thank you for your interest in the APEX_MAIL package.'||utl_tcp.crlf||utl_tcp.crlf;
l_body := l_body ||' Sincerely,'||utl_tcp.crlf;
l_body := l_body ||' The APEX Dev Team'||utl_tcp.crlf;
apex_mail.send(
p_to => 'some_user#somewhere.com,other_user#elsewhere.com', -- separate multiple recipients with comma
p_from => 'some_sender#somewhere.com', -- change to a real senders email address
p_body => l_body,
p_subj => 'APEX_MAIL Package - Plain Text message');
END;
hth, Moritz
I have a stored procedure within Oracle that dynamically creates triggers for all of my tables (since they trigger the same stored procedure), by constructing SQL code and executing it with Oracle's PL/SQL EXECUTE command (although I am using SQL Commander for testing). How does one correctly create an if statement within a trigger? Below is my code, which gets syntax error on the line with there IF statement starts.
CREATE OR REPLACE TRIGGER "DATABASE"."TABLE_TRIGGER"
AFTER INSERT OR DELETE OR UPDATE ON TABLE
FOR EACH ROW
DECLARE
v_op VARCHAR2(20);
BEGIN
IF INSERTING THEN
v_op := 'INSERT';
ELSIF UPDATING THEN
v_op := 'UPDATE';
ELSE
v_op := 'DELETE';
END IF;
PKG.STORED_PROC(v_op, ' - MY_COLUMN: ' || :NEW.MY_COLUMN || '', 'MY_TABLE');
END;
This is a sample of the code I used to generate the SQL code.
PROCEDURE CREATE_TRIGGERS(
IN_TABLE_OMIT IN VARCHAR2, -- IN_TABLE_OMIT is a list of tables to not create a trigger on, as CSV
OUT_RESULT OUT VARCHAR2)
AS
v_table_results SYS_REFCURSOR;
v_column_results SYS_REFCURSOR;
v_template_head VARCHAR2(512);
v_template_body VARCHAR2(512);
v_template_operation VARCHAR(512);
v_template_column VARCHAR2(128);
v_template_data VARCHAR2(1024);
v_template_foot VARCHAR2(512);
v_result VARCHAR2(1024);
BEGIN
-- Create a template for each trigger
v_template_head := 'CREATE OR REPLACE TRIGGER "MY_DB"."MY_TABLE_TRIGGER"' || chr(10);
v_template_head := v_template_head || 'AFTER INSERT OR DELETE OR UPDATE ON MY_TABLE' || chr(10);
v_template_head := v_template_head || 'FOR EACH ROW' || chr(10) || 'DECLARE' || chr(10) || 'v_op VARCHAR2(20);' || chr(10) || 'BEGIN' || chr(10) || chr(10);
v_template_operation := 'IF INSERTING THEN v_op := ''INSERT''; ELSIF UPDATING THEN v_op := ''UPDATE''; ELSE v_op := ''DELETE''; END IF;' || chr(10);
v_template_body := 'MY_DB.STORED_PROC(' || chr(10) || 'v_op,' || chr(10);
v_template_column := ''' - MY_COLUMN: '' || :NEW.MY_COLUMN || ';
v_template_foot := '''MY_TABLE'');' || chr(10) || chr(10) || 'END;';
-- Insert double quotes into template
-- Loop through each table
FOR LOOP_TABLE IN (SELECT TABLE_NAME FROM USER_TABLES ORDER BY TABLE_NAME) LOOP
IF INSTR(IN_TABLE_OMIT, LOOP_TABLE.TABLE_NAME) != 0 OR INSTR('AUDIT_TABLE', LOOP_TABLE.TABLE_NAME) != 0 THEN
FOR LOOP_COLUMN IN (SELECT COLUMN_NAME FROM ALL_TAB_COLUMNS WHERE TABLE_NAME = LOOP_TABLE.TABLE_NAME) LOOP
v_template_data := v_template_data || REPLACE(v_template_column, 'MY_COLUMN', LOOP_COLUMN.COLUMN_NAME);
END LOOP;
v_template_head := REPLACE(v_template_head, 'MY_TABLE', LOOP_TABLE.TABLE_NAME);
v_template_data := v_template_data || ''''',' || chr(10);
v_template_foot := REPLACE(v_template_foot, 'MY_TABLE', LOOP_TABLE.TABLE_NAME);
v_result := v_template_head || v_template_operation || v_template_body || v_template_data || v_template_foot;
v_template_data := '';
OUT_RESULT := chr(10) || v_result;
ELSE
dbms_output.put_line('Searched for ' || LOOP_TABLE.TABLE_NAME || ' in ' || IN_TABLE_OMIT);
END IF;
END LOOP;
END;
The trigger was successfully created when removing all semi-colons from the generated trigger statement.
I have the following procedure, but no scheduler job is getting created and I cannot find any errors while running the job. How can I debug this and what is wrong with the code?
CREATE OR REPLACE PROCEDURE test
IS
prod_no varchar2(32);
prod_date date;
employee varchar2(32);
assurer varchar2(32);
prod_description varchar2(32);
prod_days number;
assig varchar2(32);
reg_no number;
l_v number;
BEGIN
prod_no := '300';
prod_date := sysdate;
employee := 'SAM';
assurer := 'MAT';
prod_description := 'test';
prod_days := 1;
assig := 'A';
reg_no := 1;
DBMS_SCHEDULER.create_job (
job_name => DBMS_SCHEDULER.generate_job_name ('FR'),
job_type => 'PLSQL_BLOCK',
job_action => 'BEGIN test_job('
|| i_prod_no
|| ','''
|| prod_date
|| ','''
|| employee
|| ','''
|| assurer
|| ','''
|| prod_description
|| ','''
|| prod_days
|| ','''
|| assig
|| ','''
|| reg_no
|| '''); end;',
start_date => SYSDATE,
end_date => NULL,
enabled => TRUE,
comments => 'test product'
);
commit;
exception
when others then
dbms_output.put_line (dbms_utility.format_error_stack);
END test;
/
If job action is syntactically incorrect you won't get any warning, but you won't get a job either.
Here is your statement:
BEGIN test_job(300,'04-OCT-12,'SAM,'MAT,'test,'1,'A,'1'); end;
You are missing some ' to close the string values.
CREATE OR REPLACE PROCEDURE test
IS
prod_no varchar2(32);
prod_date date;
employee varchar2(32);
assurer varchar2(32);
prod_description varchar2(32);
prod_days number;
assig varchar2(32);
reg_no number;
l_v number;
l_statement varchar2(32767);
BEGIN
prod_no := '300';
prod_date := sysdate;
employee := 'SAM';
assurer := 'MAT';
prod_description := 'test';
prod_days := 1;
assig := 'A';
reg_no := 1;
l_statement := 'BEGIN test_job('
|| i_prod_no
|| ','''
|| prod_date
|| ','''
|| employee
|| ','''
|| assurer
|| ','''
|| prod_description
|| ','''
|| prod_days
|| ','''
|| assig
|| ','''
|| reg_no
|| '''); end;'
dbms_output.put_line(l_statement);
DBMS_SCHEDULER.create_job (
job_name => DBMS_SCHEDULER.generate_job_name ('FR'),
job_type => 'PLSQL_BLOCK',
job_action => l_statement,
start_date => SYSDATE,
end_date => NULL,
enabled => TRUE,
comments => 'test product'
);
commit;
exception
when others then
dbms_output.put_line (dbms_utility.format_error_stack);
END test;
/