Email From Oracle PL/SQL (UTL_SMTP)

The UTL_SMTP package was introduced in Oracle 8i and can be used to send emails from PL/SQL.
Simple Emails
In its simplest form a single string or variable can be sent as the message body using the following procedure. In this case we have not included any header information or subject line in the message, so it is not very useful, but it is small.
CREATE OR REPLACE PROCEDURE send_mail (p_to IN VARCHAR2,
p_from IN VARCHAR2,
p_message IN VARCHAR2,
p_smtp_host IN VARCHAR2,
p_smtp_port IN NUMBER DEFAULT 25)
AS
l_mail_conn UTL_SMTP.connection;
BEGIN
l_mail_conn := UTL_SMTP.open_connection(p_smtp_host, p_smtp_port);
UTL_SMTP.helo(l_mail_conn, p_smtp_host);
UTL_SMTP.mail(l_mail_conn, p_from);
UTL_SMTP.rcpt(l_mail_conn, p_to);
UTL_SMTP.data(l_mail_conn, p_message || UTL_TCP.crlf || UTL_TCP.crlf);
UTL_SMTP.quit(l_mail_conn);
END;
/

The code below shows how the procedure is called.
BEGIN
send_mail(p_to => ‘me@mycompany.com’,
p_from => ‘admin@mycompany.com’,
p_message => ‘This is a test message.’,
p_smtp_host => ‘smtp.mycompany.com’);
END;
/

Multi-Line Emails
Multi-line messages can be written by expanding the UTL_SMTP.DATA command using the UTL_SMTP.WRITE_DATA command as follows. This is a better method to use as the total message size is no longer constrained by the 32K limit on a VARCHAR2 variable. In the following example the header information has been included in the message also.
CREATE OR REPLACE PROCEDURE send_mail (p_to IN VARCHAR2,
p_from IN VARCHAR2,
p_subject IN VARCHAR2,
p_message IN VARCHAR2,
p_smtp_host IN VARCHAR2,
p_smtp_port IN NUMBER DEFAULT 25)
AS
l_mail_conn UTL_SMTP.connection;
BEGIN
l_mail_conn := UTL_SMTP.open_connection(p_smtp_host, p_smtp_port);
UTL_SMTP.helo(l_mail_conn, p_smtp_host);
UTL_SMTP.mail(l_mail_conn, p_from);
UTL_SMTP.rcpt(l_mail_conn, p_to);
UTL_SMTP.open_data(l_mail_conn);
UTL_SMTP.write_data(l_mail_conn, ‘Date: ‘ || TO_CHAR(SYSDATE, ‘DD-MON-YYYY HH24:MI:SS’) || UTL_TCP.crlf);
UTL_SMTP.write_data(l_mail_conn, ‘To: ‘ || p_to || UTL_TCP.crlf);
UTL_SMTP.write_data(l_mail_conn, ‘From: ‘ || p_from || UTL_TCP.crlf);
UTL_SMTP.write_data(l_mail_conn, ‘Subject: ‘ || p_subject || UTL_TCP.crlf);
UTL_SMTP.write_data(l_mail_conn, ‘Reply-To: ‘ || p_from || UTL_TCP.crlf || UTL_TCP.crlf);
UTL_SMTP.write_data(l_mail_conn, p_message || UTL_TCP.crlf || UTL_TCP.crlf);
UTL_SMTP.close_data(l_mail_conn);
UTL_SMTP.quit(l_mail_conn);
END;
/
The code below shows how the procedure is called.
BEGIN
send_mail(p_to => ‘me@mycompany.com’,
p_from => ‘admin@mycompany.com’,
p_subject => ‘Test Message’,
p_message => ‘This is a test message.’,
p_smtp_host => ‘smtp.mycompany.com’);
END;
/
HTML Emails
The following procedure builds on the previous version, allowing it include plain text and/or HTML versions of the email. The format of the message is explained here.

CREATE OR REPLACE PROCEDURE send_mail (p_to IN VARCHAR2,
p_from IN VARCHAR2,
p_subject IN VARCHAR2,
p_text_msg IN VARCHAR2 DEFAULT NULL,
p_html_msg IN VARCHAR2 DEFAULT NULL,
p_smtp_host IN VARCHAR2,
p_smtp_port IN NUMBER DEFAULT 25)
AS
l_mail_conn UTL_SMTP.connection;
l_boundary VARCHAR2(50) := ‘—-=*#abc1234321cba#*=’;
BEGIN
l_mail_conn := UTL_SMTP.open_connection(p_smtp_host, p_smtp_port);
UTL_SMTP.helo(l_mail_conn, p_smtp_host);
UTL_SMTP.mail(l_mail_conn, p_from);
UTL_SMTP.rcpt(l_mail_conn, p_to);
UTL_SMTP.open_data(l_mail_conn);
UTL_SMTP.write_data(l_mail_conn, ‘Date: ‘ || TO_CHAR(SYSDATE, ‘DD-MON-YYYY HH24:MI:SS’) || UTL_TCP.crlf);
UTL_SMTP.write_data(l_mail_conn, ‘To: ‘ || p_to || UTL_TCP.crlf);
UTL_SMTP.write_data(l_mail_conn, ‘From: ‘ || p_from || UTL_TCP.crlf);
UTL_SMTP.write_data(l_mail_conn, ‘Subject: ‘ || p_subject || UTL_TCP.crlf);
UTL_SMTP.write_data(l_mail_conn, ‘Reply-To: ‘ || p_from || UTL_TCP.crlf);
UTL_SMTP.write_data(l_mail_conn, ‘MIME-Version: 1.0′ || UTL_TCP.crlf);
UTL_SMTP.write_data(l_mail_conn, ‘Content-Type: multipart/alternative; boundary=”‘ || l_boundary || ‘”‘ || UTL_TCP.crlf || UTL_TCP.crlf);
IF p_text_msg IS NOT NULL THEN
UTL_SMTP.write_data(l_mail_conn, ‘–’ || l_boundary || UTL_TCP.crlf);
UTL_SMTP.write_data(l_mail_conn, ‘Content-Type: text/plain; charset=”iso-8859-1″‘ || UTL_TCP.crlf || UTL_TCP.crlf);
UTL_SMTP.write_data(l_mail_conn, p_text_msg);
UTL_SMTP.write_data(l_mail_conn, UTL_TCP.crlf || UTL_TCP.crlf);
END IF;

IF p_html_msg IS NOT NULL THEN
UTL_SMTP.write_data(l_mail_conn, ‘–’ || l_boundary || UTL_TCP.crlf);
UTL_SMTP.write_data(l_mail_conn, ‘Content-Type: text/html; charset=”iso-8859-1″‘ || UTL_TCP.crlf || UTL_TCP.crlf);
UTL_SMTP.write_data(l_mail_conn, p_html_msg);
UTL_SMTP.write_data(l_mail_conn, UTL_TCP.crlf || UTL_TCP.crlf);
END IF;
UTL_SMTP.write_data(l_mail_conn, ‘–’ || l_boundary || ‘–’ || UTL_TCP.crlf);
UTL_SMTP.close_data(l_mail_conn);
UTL_SMTP.quit(l_mail_conn);
END;
/

The code below shows how the procedure is called.
DECLARE
l_html VARCHAR2(32767);
BEGIN
l_html := ‘<html>
<head>
<title>Test HTML message</title>
</head>
<body>
<p>This is a <b>HTML</b> <i>version</i> of the test message.</p>
<p><img src=”http://www.oracleport.com/images/site_logo.gif” alt=”Site Logo” />
</body>
</html>’;
send_mail(p_to => ‘me@mycompany.com’,
p_from => ‘admin@mycompany.com’,
p_subject => ‘Test Message’,
p_text_msg => ‘This is a test message.’,
p_html_msg => l_html,
p_smtp_host => ‘smtp.mycompany.com’);
END;
/

Emails with Attachments
Sending an email with an attachment is similar to the previous example as the message and the attachment must be separated by a boundary and identified by a name and mime type.

BLOB Attachment
Attaching a BLOB requires the binary data to be encoded and converted to text so it can be sent using SMTP.

CREATE OR REPLACE PROCEDURE send_mail (p_to IN VARCHAR2,
p_from IN VARCHAR2,
p_subject IN VARCHAR2,
p_text_msg IN VARCHAR2 DEFAULT NULL,
p_attach_name IN VARCHAR2 DEFAULT NULL,
p_attach_mime IN VARCHAR2 DEFAULT NULL,
p_attach_blob IN BLOB DEFAULT NULL,
p_smtp_host IN VARCHAR2,
p_smtp_port IN NUMBER DEFAULT 25)
AS
l_mail_conn UTL_SMTP.connection;
l_boundary VARCHAR2(50) := ‘—-=*#abc1234321cba#*=’;
l_step PLS_INTEGER := 24573;
BEGIN
l_mail_conn := UTL_SMTP.open_connection(p_smtp_host, p_smtp_port);
UTL_SMTP.helo(l_mail_conn, p_smtp_host);
UTL_SMTP.mail(l_mail_conn, p_from);
UTL_SMTP.rcpt(l_mail_conn, p_to);
UTL_SMTP.open_data(l_mail_conn);
UTL_SMTP.write_data(l_mail_conn, ‘Date: ‘ || TO_CHAR(SYSDATE, ‘DD-MON-YYYY HH24:MI:SS’) || UTL_TCP.crlf);
UTL_SMTP.write_data(l_mail_conn, ‘To: ‘ || p_to || UTL_TCP.crlf);
UTL_SMTP.write_data(l_mail_conn, ‘From: ‘ || p_from || UTL_TCP.crlf);
UTL_SMTP.write_data(l_mail_conn, ‘Subject: ‘ || p_subject || UTL_TCP.crlf);
UTL_SMTP.write_data(l_mail_conn, ‘Reply-To: ‘ || p_from || UTL_TCP.crlf);
UTL_SMTP.write_data(l_mail_conn, ‘MIME-Version: 1.0′ || UTL_TCP.crlf);
UTL_SMTP.write_data(l_mail_conn, ‘Content-Type: multipart/mixed; boundary=”‘ || l_boundary || ‘”‘ || UTL_TCP.crlf || UTL_TCP.crlf);
IF p_text_msg IS NOT NULL THEN
UTL_SMTP.write_data(l_mail_conn, ‘–’ || l_boundary || UTL_TCP.crlf);
UTL_SMTP.write_data(l_mail_conn, ‘Content-Type: text/plain; charset=”iso-8859-1″‘ || UTL_TCP.crlf || UTL_TCP.crlf);
UTL_SMTP.write_data(l_mail_conn, p_text_msg);
UTL_SMTP.write_data(l_mail_conn, UTL_TCP.crlf || UTL_TCP.crlf);
END IF;

IF p_attach_name IS NOT NULL THEN
UTL_SMTP.write_data(l_mail_conn, ‘–’ || l_boundary || UTL_TCP.crlf);
UTL_SMTP.write_data(l_mail_conn, ‘Content-Type: ‘ || p_attach_mime || ‘; name=”‘ || p_attach_name || ‘”‘ || UTL_TCP.crlf);
UTL_SMTP.write_data(l_mail_conn, ‘Content-Transfer-Encoding: base64′ || UTL_TCP.crlf);
UTL_SMTP.write_data(l_mail_conn, ‘Content-Disposition: attachment; filename=”‘ || p_attach_name || ‘”‘ || UTL_TCP.crlf || UTL_TCP.crlf);
FOR i IN 0 .. TRUNC((DBMS_LOB.getlength(p_attach_blob) – 1 )/l_step) LOOP
UTL_SMTP.write_data(l_mail_conn, UTL_RAW.cast_to_varchar2(UTL_ENCODE.base64_encode(DBMS_LOB.substr(p_attach_blob, l_step, i * l_step + 1))));
END LOOP;
UTL_SMTP.write_data(l_mail_conn, UTL_TCP.crlf || UTL_TCP.crlf);
END IF;

 UTL_SMTP.write_data(l_mail_conn, ‘–’ || l_boundary || ‘–’ || UTL_TCP.crlf);
UTL_SMTP.close_data(l_mail_conn);
UTL_SMTP.quit(l_mail_conn);
END;
/

The code below shows how the procedure is called.
DECLARE
l_name images.name%TYPE := ‘site_logo.gif’;
l_blob images.image%TYPE;
BEGIN
SELECT image
INTO l_blob
FROM images
WHERE name = l_name;
send_mail(p_to => ‘me@mycompany.com’,
p_from => ‘admin@mycompany.com’,
p_subject => ‘Test Message’,
p_text_msg => ‘This is a test message.’,
p_attach_name => ‘site_logo.gif’,
p_attach_mime => ‘image/gif’,
p_attach_blob => l_blob,
p_smtp_host => ‘smtp.mycompany.com’);
END;
/

CLOB Attachment

Attaching a CLOB is similar to attaching a BLOB, but we don’t have to worry about encoding the data because it is already plain text.

CREATE OR REPLACE PROCEDURE send_mail (p_to IN VARCHAR2,
p_from IN VARCHAR2,
p_subject IN VARCHAR2,
p_text_msg IN VARCHAR2 DEFAULT NULL,
p_attach_name IN VARCHAR2 DEFAULT NULL,
p_attach_mime IN VARCHAR2 DEFAULT NULL,
p_attach_clob IN CLOB DEFAULT NULL,
p_smtp_host IN VARCHAR2,
p_smtp_port IN NUMBER DEFAULT 25)

AS
l_mail_conn UTL_SMTP.connection;
l_boundary VARCHAR2(50) := ‘—-=*#abc1234321cba#*=’;
l_step PLS_INTEGER := 24573;

BEGIN
l_mail_conn := UTL_SMTP.open_connection(p_smtp_host, p_smtp_port);
UTL_SMTP.helo(l_mail_conn, p_smtp_host);
UTL_SMTP.mail(l_mail_conn, p_from);
UTL_SMTP.rcpt(l_mail_conn, p_to);

 UTL_SMTP.open_data(l_mail_conn);
UTL_SMTP.write_data(l_mail_conn, ‘Date: ‘ || TO_CHAR(SYSDATE, ‘DD-MON-YYYY HH24:MI:SS’) || UTL_TCP.crlf);
UTL_SMTP.write_data(l_mail_conn, ‘To: ‘ || p_to || UTL_TCP.crlf);
UTL_SMTP.write_data(l_mail_conn, ‘From: ‘ || p_from || UTL_TCP.crlf);
UTL_SMTP.write_data(l_mail_conn, ‘Subject: ‘ || p_subject || UTL_TCP.crlf);
UTL_SMTP.write_data(l_mail_conn, ‘Reply-To: ‘ || p_from || UTL_TCP.crlf);
UTL_SMTP.write_data(l_mail_conn, ‘MIME-Version: 1.0′ || UTL_TCP.crlf);
UTL_SMTP.write_data(l_mail_conn, ‘Content-Type: multipart/mixed; boundary=”‘ || l_boundary || ‘”‘ || UTL_TCP.crlf || UTL_TCP.crlf);
IF p_text_msg IS NOT NULL THEN
UTL_SMTP.write_data(l_mail_conn, ‘–’ || l_boundary || UTL_TCP.crlf);
UTL_SMTP.write_data(l_mail_conn, ‘Content-Type: text/plain; charset=”iso-8859-1″‘ || UTL_TCP.crlf || UTL_TCP.crlf);
UTL_SMTP.write_data(l_mail_conn, p_text_msg);
UTL_SMTP.write_data(l_mail_conn, UTL_TCP.crlf || UTL_TCP.crlf);
END IF;

 IF p_attach_name IS NOT NULL THEN
UTL_SMTP.write_data(l_mail_conn, ‘–’ || l_boundary || UTL_TCP.crlf);
UTL_SMTP.write_data(l_mail_conn, ‘Content-Type: ‘ || p_attach_mime || ‘; name=”‘ || p_attach_name || ‘”‘ || UTL_TCP.crlf);
UTL_SMTP.write_data(l_mail_conn, ‘Content-Disposition: attachment; filename=”‘ || p_attach_name || ‘”‘ || UTL_TCP.crlf || UTL_TCP.crlf);
FOR i IN 0 .. TRUNC((DBMS_LOB.getlength(p_attach_clob) – 1 )/l_step) LOOP
UTL_SMTP.write_data(l_mail_conn, DBMS_LOB.substr(p_attach_clob, l_step, i * l_step + 1));
END LOOP;
UTL_SMTP.write_data(l_mail_conn, UTL_TCP.crlf || UTL_TCP.crlf);
END IF;
UTL_SMTP.write_data(l_mail_conn, ‘–’ || l_boundary || ‘–’ || UTL_TCP.crlf);
UTL_SMTP.close_data(l_mail_conn);
UTL_SMTP.quit(l_mail_conn);
END;
/

The code below shows how the procedure is called.

DECLARE
l_clob CLOB := ‘This is a very small CLOB!’;
BEGIN
send_mail(p_to => ‘me@mycompany.com’,
p_from => ‘admin@mycompany.com’,
p_subject => ‘Test Message’,
p_text_msg => ‘This is a test message.’,
p_attach_name => ‘test.txt’,
p_attach_mime => ‘text/plain’,
p_attach_clob => l_clob,
p_smtp_host => ‘smtp.mycompany.com’);
END;
/

Miscellaneous
For emails with multiple recipients, simply call the RCPT procedure once for each separate email address.
The UTL_SMTP package requires Jserver which can be installed by running the following scripts as SYS.
SQL> @$ORACLE_HOME/javavm/install/initjvm.sql
SQL> @$ORACLE_HOME/rdbms/admin/initplsj.sql


Install Oracle E-Business Suite Release 12 on MS Windows

In this article i will explain how to install Oracle EBS R12 in MS Windows. I am going to explain two methods 1) EBS R12 on Windows 2003 Server
2) EBS R12 on Windows XP.
I will strongly  recommend to install R12 on Windows 2003 server. It is more reliable and will provide you maximum functionality.

Oracle E-Business Suite Release 12 on Windows 2003 Server.

My Hardware & Software Specifications:  Booting and Running speed is excellent by using following hardware.
- Intel Pentium Core 2 DUO, CPU 2.0 GHz
- 4 GB of RAM
- 250 GB Hard Drive
- Windows 2003 Server with Service Pack 2

- R12 Stage  Down load from http://edelivery.oracle.com
- MKS Tool Kit   licenced  download from http://webstore.mkssoftware.com
- Visual C++ 8.0 licenced (Included in Microsoft Visual Studio 2005)

Installation Steps:
1) Install Windows 2003 Server with SP2
Make sure you have installed Network driver successfully.
2) Set ‘Computer Name’ .



- Right click on ‘My Computer’ > Properties > ‘Computer Name’ > Change
- Set ‘Computer Name’ to r12   (you can other give any name)



3) Set the domain
- Click on More
- Set a ‘Primary DNS Suffix of this Computer’ to   oracle.com    you can choose any other name (myoreacle.com)


 

4) Add a new entry in C:\windows\system32\drivers\etc\hosts as follows:



replace localhost  with   r12.oracle.com

5) From the command prompt, make sure you can do the following:  
        C:\> ping   r12.oracle.com

6) Install Visual C++ 8.0 (Which is included in Microsoft Visual Studio 2005) in ‘C:\VS8′  Directory name should not contain spaces

7) Download ‘MKS toolkit’ and install in c:\mksnt\

8- Copy  link.exe  ,   cl.exe  from  c:\vs8\vs\bin to c:\mksnt\mksnt\

9) Copy which.exe from   c:\mksnt\mksnt\ to c:\vs8\lib\

10) Copy GNUMAKE.EXE  to c:\windows\system32   

11) Restart Computer

 12) Set Up the Stage Area:
Stage Area (c:\stage12) requires a 32 GB hard disk space.  Make sure stage12 name should not contain spaces and should have read/write permissions.
Extract the zip files which have been downloaded from (http://edelivery.oracle.com). Nothing special to do since the extracted files will create the stage area directory structure by itself. You should see the following structure under ‘C:\stage12′ once you are done with the files extraction: Make sure there should not be spaces stage directory name.
- startCD
- oraAppDB
- oraApps
- oraAS
- oraDB


13) Start the installation:
Run rapidwiz from following path
C:\stage12\startCD\Disk1\rapidwiz> RapidWiz.cmd

For ‘VC++’ and ‘mks’ I have provided the following paths:
s_MSDEVdir=C:\VS8\VC
s_MKSdir=C:\mksnt\mksnt


14) Follow the wizard and sit back and relax until installation completed.

15) After installation complete open the browser and write following URL    r12.oracle.com:8000

Sample Code and Output- Run Work Flow API

To get a notification/email that looks similar to below, all you need to do is to call a PL/SQL API
Sample Below Desired Notification from API is shown below

To generate such Notification, call the API

STEP 1
RUN BELOW SQL and DO COMMIT;
xx_dev>>SET serveroutput on;
DECLARE
  n_not_id INTEGER;
BEGIN
  xx_notifications_api_pkg.send_notification(
     x_email_address       => 'PASSIA'
    ,x_user_name           => ''
    ,x_notification_api_id => n_not_id
    ,x_message_type        => 'TEXT_AND_QUERY'
    ,x_process_short_code  => 'DEMO-'
    ,x_message_subject     => 'ANIL TESTING ANOTHER ONE Customer Run Id 100329'
    ,x_message_text        => 'ANIL Customer Customers in AR on ' ||
    to_char(SYSDATE,'DD-Mon-RRRR HH24:MI'));

  xx_notifications_api_pkg.add_query(
     x_notification_api_id => n_not_id
    ,x_query_title_text    => 'List of TCA Customers Created During Last 24Hrs'
    ,x_from_clause         => 'hz_parties'
    ,x_where_clause        => 'creation_date > sysdate - 1'
    ,x_bind_values         => NULL
    ,x_column_title_1      => 'Party Number'
    ,x_column_name_1       => 'PARTY_NUMBER'
    ,x_column_title_2      => 'Creation Date'
    ,x_column_name_2       => 'CREATION_DATE'
    ,x_column_title_3      => 'Org System Ref'
    ,x_column_name_3       => 'orig_system_reference');

  xx_notifications_api_pkg.add_query(
     x_notification_api_id => n_not_id
    ,x_query_title_text    => 'Second List of TCA Parties in Last 48Hrs'
    ,x_from_clause         => 'hz_parties'
    ,x_where_clause        => 'creation_date > sysdate -2'
    ,x_bind_values         => NULL
    ,x_column_title_1      => 'Party Number'
    ,x_column_name_1       => 'PARTY_NUMBER'
    ,x_column_title_2      => 'Party Name'
    ,x_column_name_2       => 'PARTY_NAME'
    ,x_column_title_3      => 'Org System Ref'
    ,x_column_name_3       => 'orig_system_reference');
  dbms_output.put_line('n_not_id: ' || n_not_id);
COMMIT ;
END;
/

The serveroutput displays message below
n_not_id: 1000

PL/SQL procedure successfully completed.


STEP 2
R
UN BELOW THE BACKGROUND PROCESS AS BELOW
Ideally this will be scheduled to run every 15minutes or so on Production.
Hence notifications will be sent out every 15minutes by email/worklist


Step 3.
Item Key used by this wf api internally will use value in parameter x_process_short_code concatenated with Reference Number returned.
If you wish to send notification related to PO Number 1032, then pass parameter 
x_process_short_code=>'PO-Num-1032'

Issue:- If concurrent manager is not running then start this using command below
adcmctl.sh start apps appspassword




How to find all cancel Requisitions

SELECT prha . *   FROM po_Requisition_headers_all prha , po_action_history pah   WHERE      1 = 1        AND pah . object_id ...