htm#GENSQL
CREATE OR REPLACE PROCEDURE SEND_MAIL ( msg_from varchar2 := 'oracle', msg_to varchar2, msg_subject varchar2 := 'E-Mail message from your database', msg_text varchar2 := '' ) IS c utl_tcp.connection; rc integer; BEGIN c := utl_tcp.open_connection('127.0.0.1', 25); -- open the SMTP port 25 on local machine dbms_output.put_line(utl_tcp.get_line(c, TRUE)); rc := utl_tcp.write_line(c, 'HELO localhost'); dbms_output.put_line(utl_tcp.get_line(c, TRUE)); rc := utl_tcp.write_line(c, 'MAIL FROM: '||msg_from); dbms_output.put_line(utl_tcp.get_line(c, TRUE)); rc := utl_tcp.write_line(c, 'RCPT TO: '||msg_to); dbms_output.put_line(utl_tcp.get_line(c, TRUE)); rc := utl_tcp.write_line(c, 'DATA'); -- Start message body dbms_output.put_line(utl_tcp.get_line(c, TRUE)); rc := utl_tcp.write_line(c, 'Subject: '||msg_subject); rc := utl_tcp.write_line(c, ''); rc := utl_tcp.write_line(c, msg_text); rc := utl_tcp.write_line(c, '.'); -- End of message body dbms_output.put_line(utl_tcp.get_line(c, TRUE)); rc := utl_tcp.write_line(c, 'QUIT'); dbms_output.put_line(utl_tcp.get_line(c, TRUE)); utl_tcp.close_connection(c); -- Close the connection EXCEPTION when others then raise_application_error( -20000, 'Unable to send e-mail message from pl/sql because of: '|| sqlerrm); END; / show errors -- Examples: set serveroutput on exec send_mail(msg_to =>'you@yourdomain.com');
exec send_mail(msg_to =>'you@yourdomain.com', msg_text=>'Look Ma, I can send mail from plsql' );
Notes:
From Oracle8i release 8.1.6 one can send e-mail messages directly from PL/SQL using either the UTL_TCP or UTL_SMTP packages. Jserver needs to be installed and configured. No pipes or external procedures required. Date: 15-MAR-2001 Author: Virgilio Nunes (Virgilio@logtek.co.za) ----------------------------------------------------------------------
CREATE OR REPLACE PROCEDURE SEND_MAIL ( msg_from varchar2 := 'EMAILADDRESS@DOMAIN.COM', ----- MAIL BOX SENDING THE EMAIL msg_to varchar2 := 'EMAILADDRESS@DOMAIN.COM', ----- MAIL BOX RECIEVING THE EMAIL msg_subject varchar2 := 'Output file TEST1', ----- EMAIL SUBJECT msg_text varchar2 := 'THIS IS THE TEXT OF THE EMAIL MESSAGE.', v_output1 varchar2 := 'THIS IS THE TEXT OF THE ATTACHMENT FILE. THIS TEXT SHOULD BE IN A TEXT FILE ATTACHED TO THE EMAIL.') IS c utl_tcp.connection; rc integer; crlf VARCHAR2(2):= CHR(13)||CHR(10); mesg VARCHAR2( 32767 ); BEGIN c := utl_tcp.open_connection('196.35.140.18', 25); ----- OPEN SMTP PORT CONNECTION rc := utl_tcp.write_line(c, 'HELO 196.35.140.18'); ----- PERFORMS HANDSHAKING WITH SMTP SERVER dbms_output.put_line(utl_tcp.get_line(c, TRUE)); rc := utl_tcp.write_line(c, 'EHLO 196.35.140.18'); ----- PERFORMS HANDSHAKING WITH SMTP SERVER, INCLUDING EXTRA INFORMATION dbms_output.put_line(utl_tcp.get_line(c, TRUE)); rc := utl_tcp.write_line(c, 'MAIL FROM: '||msg_from); ----- MAIL BOX SENDING THE EMAIL dbms_output.put_line(utl_tcp.get_line(c, TRUE)); rc := utl_tcp.write_line(c, 'RCPT TO: '||msg_to); ----- MAIL BOX RECIEVING THE EMAIL dbms_output.put_line(utl_tcp.get_line(c, TRUE)); rc := utl_tcp.write_line(c, 'DATA'); ----- EMAIL MESSAGE BODY START dbms_output.put_line(utl_tcp.get_line(c, TRUE)); rc := utl_tcp.write_line(c, 'Date: '||TO_CHAR( SYSDATE, 'dd Mon yy hh24:mi:ss' )); rc := utl_tcp.write_line(c, 'From: '||msg_from||' <'||msg_from||'>'); rc := utl_tcp.write_line(c, 'MIME-Version: 1.0'); rc := utl_tcp.write_line(c, 'To: '||msg_to||' <'||msg_to||'>'); rc := utl_tcp.write_line(c, 'Subject: '||msg_subject); rc := utl_tcp.write_line(c, 'Content-Type: multipart/mixed;'); ----- INDICATES THAT THE BODY CONSISTS OF MORE THAN ONE PART rc := utl_tcp.write_line(c, ' boundary="-----SECBOUND"'); ----- SEPERATOR USED TO SEPERATE THE BODY PARTS rc := utl_tcp.write_line(c, ''); ----- INSERTS A BLANK LINE. PART OF THE MIME FORMAT AND NONE OF THEM SHOULD BE REMOVED. rc := utl_tcp.write_line(c, '-------SECBOUND'); rc := utl_tcp.write_line(c, 'Content-Type: text/plain'); ----- 1ST BODY PART. EMAIL TEXT MESSAGE rc := utl_tcp.write_line(c, 'Content-Transfer-Encoding: 7bit'); rc := utl_tcp.write_line(c, ''); rc := utl_tcp.write_line(c, msg_text); ----- TEXT OF EMAIL MESSAGE rc := utl_tcp.write_line(c, ''); rc := utl_tcp.write_line(c, '-------SECBOUND'); rc := utl_tcp.write_line(c, 'Content-Type: text/plain;'); ----- 2ND BODY PART. rc := utl_tcp.write_line(c, ' name="Test.txt"'); rc := utl_tcp.write_line(c, 'Content-Transfer_Encoding: 8bit'); rc := utl_tcp.write_line(c, 'Content-Disposition: attachment;'); ----- INDICATES THAT THIS IS AN ATTACHMENT rc := utl_tcp.write_line(c, ' filename="Test.txt"'); ----- SUGGESTED FILE NAME FOR ATTACHMENT rc := utl_tcp.write_line(c, ''); rc := utl_tcp.write_line(c, v_output1); rc := utl_tcp.write_line(c, '-------SECBOUND--'); rc := utl_tcp.write_line(c, ''); rc := utl_tcp.write_line(c, '.'); ----- EMAIL MESSAGE BODY END dbms_output.put_line(utl_tcp.get_line(c, TRUE)); rc := utl_tcp.write_line(c, 'QUIT'); ----- ENDS EMAIL TRANSACTION dbms_output.put_line(utl_tcp.get_line(c, TRUE)); utl_tcp.close_connection(c); ----- CLOSE SMTP PORT CONNECTION EXCEPTION when others then raise_application_error(-20000, SQLERRM); END; /
rem ---------------------------------------------------------------------DECLARE v_From VARCHAR2(80) := 'oracle@mycompany.com'; v_Recipient VARCHAR2(80) := 'test@mycompany.com'; v_Subject VARCHAR2(80) := 'test subject'; v_Mail_Host VARCHAR2(30) := 'mail.mycompany.com'; v_Mail_Conn utl_smtp.Connection; crlf VARCHAR2(2) := chr(13)||chr(10); 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); 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 || 'MIME-Version: 1.0'|| crlf || -- Use MIME mail standard 'Content-Type: multipart/mixed;'|| crlf || ' boundary="-----SECBOUND"'|| crlf || crlf || '-------SECBOUND'|| crlf || 'Content-Type: text/plain;'|| crlf || 'Content-Transfer_Encoding: 7bit'|| crlf || crlf || 'some message text'|| crlf || -- Message body 'more message text'|| crlf || crlf || '-------SECBOUND'|| crlf || 'Content-Type: text/plain;'|| crlf || ' name="excel.csv"'|| crlf || 'Content-Transfer_Encoding: 8bit'|| crlf || 'Content-Disposition: attachment;'|| crlf || ' filename="excel.csv"'|| crlf || crlf || 'CSV,file,attachement'|| crlf || -- Content of attachment crlf || '-------SECBOUND--' ); utl_smtp.Quit(v_mail_conn); EXCEPTION WHEN utl_smtp.Transient_Error OR utl_smtp.Permanent_Error then raise_application_error(-20000, 'Unable to send mail: '||sqlerrm); END; / -- End MIME mail
Next, the SMTP_OUT_SERVER parameter must be configured. You must connect to SYS and then use the alter system command to configure SMTP_OUT_SERVER parameter as shown here:
SQL> alter system set smtp_out_server = '<ip-address:port' scope=Both; System altered.
That's it! The installation and setup for UTL_MAIL is complete. The UTL_MAIL package only has one procedure, called Send, for sending e-mail (see Listing 2 for the syntax for the Send procedure). This package bundles the e-mail message and sends it to the UTL_SMTP package, and then the e-mail message is sent to the SMTP server. Listing 2. Syntax for UTL_MAIL.SEND
UTL_MAIL.SEND( sender IN VARCHAR2, recipients IN VARCHAR2, cc IN VARCHAR2 DEFAULT NULL, bcc IN VARCHAR2 DEFAULT NULL, subject IN VARCHAR2 DEFAULT NULL, message IN VARCHAR2, mime_type IN VARCHAR2 DEFAULT 'text/plain; charset=us-ascii', priority IN PLS_INTEGER DEFAULT NULL);
Examples: I've created a database trigger that will send an e-mail using UTL_MAIL (see Listing 3). Listing 3. Database shutdown using UTL_MAIL
CREATE OR REPLACE TRIGGER SCOTT.db_shutdown before shutdown on database begin utl_mail.send( sender => 'gjwilliams01@yahoo.com', recipients => ' gjwilliams01@yahoo.com', subject => 'Testing utl_mail', message => 'The receipt of this email means'|| ' that shutting down the database'|| ' works for UTL_MAIL ' ); end; /
Conclusion
There are two other procedures within the UTL_MAIL package that make life easy: UTL_MAIL.ATTACH_VARCHAR2 and UTL_MAIL.ATTACH_RAW. These procedures are for varchar2 and raw attachments, respectively. Q > Fax documents from database R > You can also programatically (using PL/SQL packages) send fax/e-mail from Oracle. Search Metalink and follow the steps in Article 47498.1.
http://www.dbasupport.com/oracle/ora9i/oracleemail.shtml Sending E-mails from Oracle Database Oracle 8i introduces an e-mail server option that allows you to send mail from within your code. So imagine firing e-mails to concerned persons when a critical parameter is altered, when a huge report is generated, when a night-job process fails, when a database has some issues (for DBAs), when an accounting process is completed, or when a month closing is over and so on. The list is infinite and varies from company to company on what level of alerts/notification and information sharing is to be maintained. What's more, if your local service provider supports SMS, you can even trigger an e-mail to a person's mobile.
What To Do
To get started, we'll need to make use of the UTL_SMTP and UTL_TCP packages. UTL_SMTP is the key package that liaises with the operating system protocol service to trigger the emails. You will have to write a customized routine to make use of these built-in packages and eventually call it in all applicable places in the system. E-mails can be triggered online as an event occurs or can be scheduled as a batch job (using the DBMS_JOB package). I have created a package available for download here. Compile this package in the required database and call the anonymous block present at the end with the appropriate e-mail IDs. Once successfully tested, analyze how useful it can be to your product. You may also try the simple example given below.
Any Disadvantages?
I have come across one disadvantage while testing that isn't related to Oracle. The sender's e-mail ID can be framed, although this should be taken care of by the e-mail service in use. This option is enabled on most Unix servers. So it is up to the developer to instill stringent checks so that e-mails are not faked. E-mails can be sent with a default "system" ID if autogenerated; otherwise, e-mails needs to be pegged with a valid sender ID in order to maintain authenticity. There might be an option that can be set at the OS or e-mail server level, but I am not aware of one presently. Care should also be taken to maintain a reasonable size for the e-mails. A large number of huge e-mails may overload the server. The size of the e-mail body would depend on what datatype is being used.
Simple example
declare l_maicon utl_smtp.connection; begin l_maicon :=utl_smtp.open_connection('localhost'); utl_smtp.helo(l_maicon,'hostname'); utl_smtp.mail(l_maicon,'ts2017@emirates.com'); utl_smtp.rcpt(l_maicon,'ts2017@emirates.com'); utl_smtp.data(l_maicon,'From: ts2017@emirates.com' || utl_tcp.crlf|| 'To: ts2017@emirates.com' || utl_tcp.crlf || 'Subject: database e-mail option' || utl_tcp.crlf || 'You have received this mail from database!'); utl_smtp.quit(l_maicon); end;
Common Errors
If the SMTP service is not available, the following error would occur:
ORA-20001: 421 Service not available
-- Note : refer original mail. -compile the below code in your database. -Execute the anonymous block at the end -of this script along with the right -e-mail address. ---------------------------------------------------------------create or replace package email is procedure send_mail(pi_frmadd in pi_tooadd in pi_subjct in pi_msg in pio_status in out nocopy end email; / show err create or replace package body email is g_maicon utl_smtp.connection; procedure open_mail_server(pio_status in out nocopy varchar2) is l_maihst varchar2(100) := 'localhost'; -- mail server IP address/name, instead of hardcoding this can be made a system parameter. begin pio_status := 'OK'; g_maicon := utl_smtp.open_connection(l_maihst); utl_smtp.helo(g_maicon, l_maihst); -- perform initial handshake. exception when others then pio_status := substr(sqlerrm, 1, 200); end open_mail_server; procedure close_mail_server(pio_status in out nocopy varchar2) is begin pio_status := 'OK'; utl_smtp.quit(g_maicon); exception when others then pio_status := substr(sqlerrm, 1, 200); end close_mail_server; procedure send_mail(pi_frmadd pi_tooadd pi_subjct pi_msg pio_status errexc exception; begin --< open connection >-pio_status := 'OK'; open_mail_server(pio_status); if pio_status != 'OK' then raise errexc; end if; --< assign from and to >-utl_smtp.mail(g_maicon, pi_frmadd); utl_smtp.rcpt(g_maicon, pi_tooadd); --< create message text >-utl_smtp.open_data(g_maicon); in in in in in out nocopy varchar2, varchar2, varchar2, varchar2, varchar2) is varchar2, varchar2, varchar2, varchar2, varchar2);
utl_smtp.write_data(g_maicon, 'From: "' || pi_frmadd || '"<' || pi_frmadd || '>' || utl_tcp.crlf); utl_smtp.write_data(g_maicon, 'To: "' || pi_tooadd || '"<' || pi_tooadd || '>' || utl_tcp.crlf); utl_smtp.write_data(g_maicon, 'Subject: ' || pi_subjct || utl_tcp.crlf); utl_smtp.write_data(g_maicon, pi_msg); utl_smtp.close_data(g_maicon); --< close connection >-close_mail_server(pio_status); exception when errexc then return; when others then pio_status := substr(sqlerrm, 1, 200); end send_mail; end email; / show err /* --Cut-paste the below code and execute it to send email from Oracle. --Specify the receipent e-mail ids. set serverout on size 1000000 declare l_frmadd varchar2(100) := 'ts2017@emirates.com'; l_tooadd varchar2(100) := 'ts2017@emirates.com'; l_subjct varchar2(100) := 'Cool Oracle mail'; l_msg varchar2(500) := 'You have received this mail from the database server BINGO!!' || utl_tcp.crlf || 'Checking if the content is acceptable!!!' ; l_status varchar2(200); begin email.send_mail(l_frmadd, l_tooadd, l_subjct, l_msg, l_status); dbms_output.put_line(l_status); end; / */