Home > OS >  Send Email procedure to multiple receivers
Send Email procedure to multiple receivers

Time:11-17

May I know my procedure any problem? I try to run the procedure and it works only for "CC" list receivers but "TO" list receivers cannot to receive the email. Any body can help me out will be great appreciate! Please provide me modified code.

   create or replace PROCEDURE        check_ap_reject_list (errbuf VARCHAR2, retcode NUMBER) IS
     CURSOR c1 IS
    SELECT distinct b.NAME AP_ORG, a.ORG_ID ORG_ID, a.source source, 
                    a.INVOICE_ID INVOICE_ID,reject_lookup_code Reject_Reason, 
                    a.INVOICE_NUM Invoice_Num, a.INVOICE_DATE Invoice_Date, a.GL_DATE GL_Date, 
                    a.VENDOR_NAME Vendor_Name, a.VENDOR_SITE_CODE Vendor_Site_Code, 
                    a.INVOICE_AMOUNT INVOICE_AMOUNT, a.INVOICE_CURRENCY_CODE INVOICE_CURRENCY_CODE, a.EXCHANGE_RATE EXCHANGE_RATE
          
       FROM apps.ap_interface_rejections, 
            apps.ap_invoices_interface a, 
            apps.hr_all_organization_units b, 
            apps.ap_invoice_lines_interface d
          WHERE (((parent_id = a.invoice_id AND parent_table = 'AP_INVOICES_INTERFACE') OR (parent_id = d.invoice_line_id AND parent_table = 'AP_INVOICE_LINES_INTERFACE')))
           AND a.INVOICE_ID = d.INVOICE_ID
           AND a.ORG_ID = b.ORGANIZATION_ID
         AND a.source = 'RMS'
         ;
     r1 c1%rowtype;
       c utl_smtp.connection;
       v_instance varchar2(9);
       x_email_to varchar2(4000);
       x_email_cc varchar2(4000);
       v_temp_str varchar2(4000);
       
       v_temp     number;
       v_r1_row_num number;
       v_check number;
     PROCEDURE send_data(p_data in varchar2) as
       BEGIN
          utl_smtp.write_raw_data(c, utl_raw.cast_to_raw(p_data || utl_tcp.crlf));
       --fnd_file.put_line(fnd_file.output, p_data);
       END;
       BEGIN
      SELECT count(distinct a.INVOICE_NUM)  
       into v_check 
       FROM apps.ap_interface_rejections, apps.ap_invoices_interface a, apps.hr_all_organization_units b, apps.ap_invoice_lines_interface d
          WHERE (((parent_id = a.invoice_id AND parent_table = 'AP_INVOICES_INTERFACE') OR (parent_id = d.invoice_line_id AND parent_table = 'AP_INVOICE_LINES_INTERFACE')))
           AND a.INVOICE_ID = d.INVOICE_ID
           AND a.ORG_ID = b.ORGANIZATION_ID
         AND a.source = 'RMS';
     IF v_check > 0   THEN
    select name into v_instance from V$DATABASE;
     x_email_to := '[email protected], [email protected], [email protected]';
     x_email_cc := '[email protected], [email protected]';
     c := utl_smtp.open_connection('LCEX7',25);  
     --utl_smtp.open_connection('smtp.office365.com',587);
     --utl_smtp.helo(c, 'LCEX7');
     utl_smtp.helo(c, 'LCEX7');
     utl_smtp.mail(c, '[email protected]');
    -- utl_smtp.rcpt( c, x_email_to);
    -- utl_smtp.rcpt( c, x_email_cc);
     v_temp_str := replace(x_email_to, ',', ';');
     v_temp_str := replace(x_email_cc, ',', ';');
     while length(v_temp_str) > 0 loop
    v_temp := instr(v_temp_str, ';', 1, 1);
    if v_temp > 0 then
      utl_smtp.rcpt(c, trim(substr(v_temp_str, 1, v_temp - 1)));
      v_temp_str := substr(v_temp_str, v_temp   1, length(v_temp_str));
    else
      utl_smtp.rcpt(c, trim(v_temp_str));
      v_temp_str := null;
    end if;
    end loop;
     utl_smtp.open_data(c);
     utl_smtp.write_data(c,'From: "Oracle Fin (' || v_instance ||') " <[email protected]>' || utl_tcp.CRLF);
     utl_smtp.write_data(c, 'To: ' || x_email_to || utl_tcp.CRLF);
     utl_smtp.write_data(c, 'Cc: ' || x_email_cc || utl_tcp.CRLF);
     utl_smtp.write_data(c, 'Subject: AP invoice reject list ' || to_char(sysdate,'MM/dd/yyyy HH:mm:ss') || utl_tcp.CRLF);
       utl_smtp.write_data(c, 'MIME-Version:' || '1.0' || utl_tcp.CRLF);
       utl_smtp.write_data(c,'Content-Type: ' || 'text/html; charset=utf-8' ||utl_tcp.CRLF);
       utl_smtp.write_data(c, 'Content-Transfer-Encoding: ' || '"8Bit"' || utl_tcp.CRLF);
     
     send_data('<html><body>');
     send_data('<p>Dear All,</p>');
     send_data('<p>Please find the enclosed AP reject list and advise. Thanks!</p>');
     send_data('<table border=''0'' width=''100%'' cellpadding=''1'' cellspacing=''1''>');
     send_data('<tr style=''font-size:75%;font-weight:bold;''>');
     send_data('<td>AP ORG</td>
                  <td>ORG ID</td>
                  <td>Source</td>
                  <td>INVOICE ID</td>
                  <td>Reject Reason</td>
                  <td>Invoice Num</td>
                  <td>Invoice Date</td>
                  <td>GL Date</td>
                  <td>Vendor Name</td>
                  <td>Vendor Site Code</td>
                  <td>INVOICE AMOUNT</td>
                  <td>INVOICE CURRENCY CODE</td>
                  <td>EXCHANGE RATE</td>');
    v_r1_row_num := 0;
    open c1;
      loop
       fetch c1
      into r1;
     exit when c1%notfound;
     if (mod(v_r1_row_num,2)=0) then
      send_data('<tr style=''font-size:75%;background-color:#E0EBFF;''>');
     else
      send_data('<tr style=''font-size:75%;''>');
     end if;   
    send_data('<td>' || r1.AP_ORG || '</td>
             <td>' || r1.ORG_ID || '</td>
             <td>' || r1.source || '</td>
             <td>' || r1.INVOICE_ID || '</td>
             <td>' || r1.Reject_Reason || '</td>
             <td>' || r1.Invoice_Num || '</td>
             <td>' || r1.Invoice_Date || '</td>
             <td>' || r1.GL_Date || '</td>
             <td>' || r1.Vendor_Name || '</td>
             <td>' || r1.Vendor_Site_Code|| '</td>
             <td>' || r1.INVOICE_AMOUNT || '</td>
             <td>' || r1.INVOICE_CURRENCY_CODE || '</td>
             <td>' || r1.EXCHANGE_RATE || '</td></tr>');
     v_r1_row_num := v_r1_row_num   1;
      END LOOP;
      CLOSE c1;
      send_data('</table>');
      send_data('<p>Best Regards,</p>');
      send_data('<p>Technology Department</p>');
      send_data('</body></html>');
      utl_smtp.close_data(c);
      utl_smtp.quit(c);
     end if ;
      END check_ap_reject_list; 

CodePudding user response:

You need a RCPT for each email recipient (whether CC or TO), and then a line with "To" and "Cc" where appropriatein the email data. So some pseudo code would be along the lines of:

declare
    x_email_to sys.odcivarchar2list := sys.odcivarchar2list('[email protected], [email protected], [email protected]');
    x_email_cc sys.odcivarchar2list := sys.odcivarchar2list('[email protected], [email protected]');
    
begin
  ...
  ...  normal email initialisation (open,helo,etc)
  ...

  for i in 1 .. x_email_to.count loop
    utl_smtp.rcpt(l_conn, x_email_to(i));
  end loop;

  for i in 1 .. x_email_cc.count loop
    utl_smtp.rcpt(l_conn, x_email_cc(i));
  end loop;


  for i in 1 .. x_email_to.count loop
     utl_smtp.write_data(c, 'To: ' || x_email_to(i) || utl_tcp.CRLF);
  end loop;
  
  for i in 1 .. x_email_cc.count loop
    utl_smtp.write_data(c, 'Cc: ' || x_email_cc(i) || utl_tcp.CRLF);
  end loop;

  ...
  ...  rest of email 
  ...

end;

I'm using an array so it easy to loop through each email address. In your case, you can just parse the string looking for each comment, but the concept is the same.

  • One RCPT per recipient
  • One write_date per CC and TO

CodePudding user response:

Connor's answer is spot on if you must use the utl_smtp package.

Unless you have a need to directly operate against the SMTP protocol, however, that's a relatively cumbersome way to send an email. In older versions of Oracle, that was the way you had to send emails. Even back in the 10g days, Oracle had the utl_mail.send procedure that let you pass in comma-separated lists of recipients for the to, cc, and bcc lists along with an HTML message

utl_mail.send( sender => '[email protected]',
               recipients => x_email_to,
               cc => x_email_cc,
               subject => 'Subject: AP invoice reject list ' || 
                          to_char(sysdate,'MM/dd/yyyy HH:mm:ss'),
               message => x_html_document,
               mime_type => 'text/html' );

No need to worry about appending all the CRLF's manually, no need to make dozens of calls to write_data and/or write_raw_data. Just build the HTML document you want to send in a local variable and send it. Oracle already built the infrastructure for 99% of use cases.

If you happen to have APEX installed in your database (even if you don't have an APEX application), you can also use the apex_mail package which has a similar send package. That version simplifies the process if you want to send a HTML and a plain text version of the same email so that users whose email clients don't support HTML can view it. And since apex_mail enqueues messages to be sent rather than talking directly to the SMTP server, apex_mail calls are transactional so they'll roll back if the parent transaction fails which is nice to avoid spamming internal users if this is a process that can be retried in the event of an unexpected error.

  • Related