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
Related
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
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;
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.
How to sent email in Oracle PL/SQL package to multiple receivers? I have below pl/sql procedure within an oracle package, it works only for one receiver. I need to improve it functional to let it can send email to multiple receivers at same time like "To: David Festool; Peter Makita; John Dewalt". Any body can help me out will be great appreciate! Please provide me modified code.
procedure email(p_recip in varchar2,
p_subject in varchar2,
p_message in varchar2) is
c utl_smtp.connection;
msg varchar2(4000);
procedure send_header(name in varchar2, header in varchar2) as
begin
utl_smtp.write_data(c, name || ': ' || header || utl_tcp.crlf);
end;
begin
--Open SMTP connection
c := utl_smtp.open_connection('ExchangeServerName');
-- Write SMTP header
utl_smtp.helo(c, 'ExchangeServerName');
utl_smtp.mail(c, 'Email#MyCompany.on.ca');
utl_smtp.rcpt(c, p_recip);
utl_smtp.open_data(c);
send_header('From', '"Title" <Email#MyCompany.on.ca');
send_header('To', p_recip);
send_header('Subject', p_subject);
send_header('Mime-Version', '1.0');
send_header('Content-Type', 'multipart/mixed; boundary="DMW.Boundary.605592468"');
-- Write MIME boundary line for the message body
msg := utl_tcp.crlf || '--DMW.Boundary.605592468' || utl_tcp.crlf ||
'Content-Type: text/plain' || utl_tcp.crlf ||
'Content-Transfer-Encoding: 7bit' || utl_tcp.crlf ||
utl_tcp.crlf;
utl_smtp.write_data(c, msg);
-- Write message body
utl_smtp.write_data(c, p_message || utl_tcp.crlf);
-- Clean up
utl_smtp.close_data(c);
utl_smtp.quit(c);
exception
when utl_smtp.transient_error or utl_smtp.permanent_error then
begin
utl_smtp.quit(c);
exception
when utl_smtp.transient_error or utl_smtp.permanent_error then
null;
-- When the SMTP server is down or unavailable, we don't have
-- a connection to the server. The QUIT call will raise an
-- exception that we can ignore.
end;
raise_application_error(-20000, 'Failed to send mail due to the following error: ' ||
sqlerrm);
end;
--------------------------------------------------------------
You need to call utl_smtp.rcpt multiple times, once for each recipient; you can't give a list of values in one call.
From the UTL_SMTP.RCPT documentation:
To send a message to multiple recipients, call this routine multiple
times. Each invocation schedules delivery to a single e-mail address.
That means you can't really pass a string of names, unless you're happy to parse the individual addresses out; it would be easier to pass an array of values, probably.
The TO header is a separate issue; if I recall correctly, that is really just for display, and having an address as a rcpt but not in the TO (or CC) header is how BCC is implemented. Citation needed though...
Here's an old AskTom article demonstrating this. jonearles suggestion to use UTL_MAIL should be investigated though.
The format is:
UTL_MAIL.SEND (sender, recipientlist, cc, bcc, subject, Message, mime_type, priority)
The recipientlist, cc, and bcc parameters are all comma-separated lists of recipient, copy to, and blind copy e-mail addresses.
The sender, subject, message, and mime_type parameters are all single item fields.
Just run below procedure with change code:
v_Mail_Host VARCHAR2(50) := 'uacemail.rxcorp.com'; -- your host ip or name
Execute:
begin prc_email_send( 'sohid10#yahoo.com', -- Mail From
'smolla#bd.imshealth.com',---Recipient
'sohidatibd#gmail.com;smokarem#bd.imshealth.com',-- Cc List
'This is mail subject ', 'This is mail body' );
end; /
Procedure Code:
Create or replace procedure prc_email_send(
v_From VARCHAR2,
v_Recipient VARCHAR2,
v_cc_list varchar2,
v_Subject VARCHAR2,
v_Mail_body VARCHAR2
)
is
v_Mail_Host VARCHAR2(50) := 'uacemail.rxcorp.com';
v_Mail_Conn utl_smtp.Connection;
crlf VARCHAR2(2) := chr(13)||chr(10);
CC_parties varchar2(2000);
begin
v_Mail_Conn := utl_smtp.Open_Connection(v_Mail_Host, 25);
utl_smtp.Helo(v_Mail_Conn, v_Mail_Host);
utl_smtp.Mail(v_Mail_Conn, v_From);
utl_smtp.Rcpt(v_Mail_Conn, v_Recipient);
for i in (SELECT LEVEL AS id, REGEXP_SUBSTR(v_cc_list, '[^;]+', 1, LEVEL) AS cc_email_name
FROM dual
CONNECT BY REGEXP_SUBSTR(v_cc_list, '[^;]+', 1, LEVEL) IS NOT NULL) loop
CC_parties := CC_parties||';'|| i.cc_email_name;
utl_smtp.Rcpt(v_Mail_Conn,i.cc_email_name);
end loop;
utl_smtp.Data(v_Mail_Conn,
'Date: ' || to_char(sysdate, 'Dy, DD Mon YYYY hh24:mi:ss') || crlf ||
'From: ' || v_From || crlf ||
'Subject: '|| v_Subject || crlf ||
'To: ' || v_Recipient || crlf ||
'Cc: ' || CC_parties|| crlf ||
'Content-Type: text/html;' ||crlf ||
v_Mail_body);
utl_smtp.Quit(v_mail_conn);
EXCEPTION
WHEN OTHERS THEN
BEGIN
DBMS_OUTPUT.put_line (
SUBSTR (
'Unable to send mail to recipients. Error message: '
|| SQLERRM
|| CHR (10)
|| DBMS_UTILITY.FORMAT_ERROR_BACKTRACE (),
1,255));
UTL_SMTP.quit (v_Mail_Conn);
UTL_TCP.close_all_connections;
EXCEPTION
WHEN UTL_SMTP.transient_error OR UTL_SMTP.permanent_error THEN
NULL;
END;
END;
This is working fine for myself
This has been bugging me for a while. I'm using oracle streams to write messages to an oracle AQ queue as part of a stored procedure. Below is the stored proc with relevent sections shown:
CREATE OR REPLACE PROCEDURE ESBEVENT.esb_dml_handler(in_any IN ANYDATA) IS
l_enqueue_options dbms_aq.enqueue_options_t;
l_message_properties dbms_aq.message_properties_t;
l_message sys.aq$_jms_text_message;
l_msgid raw(16);
l_xmlmsg SYS.XMLTYPE;
err_num NUMBER;
err_msg VARCHAR2(100);
BEGIN
BEGIN
l_message := sys.aq$_jms_text_message.construct;
l_xmlmsg := DBMS_STREAMS.CONVERT_LCR_TO_XML(in_any);
l_message.set_text(l_xmlmsg.getClobVal());
dbms_aq.enqueue
( queue_name => 'esbevent.esb_jms_queue'
, enqueue_options => l_enqueue_options
, message_properties => l_message_properties
, payload => l_message
, msgid => l_msgid
);
COMMIT;
err_num := '';
err_msg := 'Message Queued Successfully';
EXCEPTION
WHEN OTHERS THEN
err_num := SQLCODE;
err_msg := SUBSTR(SQLERRM, 1, 1000);
INSERT INTO esbevent.esb_dml_handler_error_t VALUES (SYSDATE, err_num||' - '||err_msg );
END;
INSERT INTO esbevent.esb_jms_msg_memento_t VALUES (esb_jms_msg_memento_seq.nextval, SYSDATE, l_xmlmsg, err_num||' - '||err_msg );
COMMIT;
END;
Following the enqueue I store the message that was sent as an XMLTYPE in the table esb_jms_msg_memento_t. This is to enable resends if we have issues in subsequent processing. I'm now trying to write a block that will extract the XMLTYPE field data and write it again to the AQ. This is currently as follows:
DECLARE
l_enqueue_options DBMS_AQ.ENQUEUE_OPTIONS_T;
l_message_properties DBMS_AQ.MESSAGE_PROPERTIES_T;
l_message SYS.aq$_jms_text_message;
l_msgid RAW (16);
l_xmlmsg XMLTYPE;
BEGIN
SELECT msg_payload
INTO l_xmlmsg
FROM esb_jms_msg_memento_t
WHERE UNIQUE_ID = '815929';
l_message.set_text (l_xmlmsg.getClobVal ()); --null self error here
DBMS_AQ.enqueue (queue_name => 'esbevent.esb_jms_queue',
enqueue_options => l_enqueue_options,
message_properties => l_message_properties,
payload => l_message,
msgid => l_msgid);
COMMIT;
END;
When i run this I get the error:
ORA-30625: method dispatch on NULL SELF argument is disallowed
ORA-06512: at line 22
It appears I can insert and XMLTYPE variable to an XMLTYPE field but not the other way around???
As soon as I post I solve it...
forgot to construct the l_message:
l_message := sys.aq$_jms_text_message.construct;
doh!