ACE Director Alum Daniel Morgan, founder of Morgan's Library, is scheduling
complimentary technical Workshops on Database Security for the first 30
Oracle Database customers located anywhere in North America, EMEA, LATAM, or
APAC that send an email to
asra_us@oracle.com. Request a Workshop for
your organization today.
Purpose
Send emails from inside the database. For demos written by Bryn Llewellyn [click here].
AUTHID
CURRENT_USER
Constants
Name
Data Type
Value
ALL_SCHEMES
VARCHAR2(80)
'CRAM-MD5 PLAIN LOGIN'
NON_CLEARTEXT_PASSWORD_SCHEMES
VARCHAR2(80)
'CRAM-MD5'
Data Types
-- connection
TYPE connection IS RECORD(
host VARCHAR2(255), -- remote host name
port PLS_INTEGER, -- remote port number
tx_timeout PLS_INTEGER, -- Transfer time-out (sec.)
private_tcp_con utl_tcp.connection,
private_state PLS_INTEGER);
/
-- reply & replies
TYPE reply IS RECORD (
code PLS_INTEGER, -- 3-digit reply code
text VARCHAR2(508) -- text message);
/
TYPE replies IS TABLE OF reply INDEX BY BINARY_INTEGER;
/
NO_SUPPORTED_SCHEME: No supported authentication scheme
ORA-29277
INVALID_OPERATION: Operation is invalid
ORA-29278
TRANSIENT_ERROR: Transient server error in 400 range
ORA-29279
PERMANENT_ERROR: Permanent server error in 500 range
First Available
8.1.7
Reply Codes
Codes
Description
211
System status, or system help reply
214
Help message [Information on how to use the receiver or the meaning of a particular non-standard command; this reply is useful only to the human user]
220
<domain> Service ready
221
<domain> Service closing transmission channel
250
Requested mail action okay, completed
251
User not local; will forward to <forward-path>
252
OK, pending messages for node <node> started. Cannot VRFY user (for example, info is not local), but will take message for this user and attempt delivery.
253
OK, <messages> pending messages for node <node> started
354
Start mail input; end with <CRLF>.<CRLF>
355
Octet-offset is the transaction offset
421
<domain> Service not available, closing transmission channel (This may be a reply to any command if the service knows it must shut down)
450
Requested mail action not taken: mailbox unavailable [for example, mailbox busy]
451
Requested action terminated: local error in processing
452
Requested action not taken: insufficient system storage
453
You have no mail.
454
TLS not available due to temporary reason. Encryption required for requested authentication mechanism.
458
Unable to queue messages for node <node>
459
Node <node> not allowed: reason
500
synt error, command unrecognized (This may include errors such as command line too long.)
501
synt error in parameters or arguments
502
Command not implemented
503
Bad sequence of commands
504
Command parameter not implemented
521
<Machine> does not accept mail.
530
Must issue a STARTTLS command first. Encryption required for requested authentication.
534
Authentication mechanism is too weak.
538
Encryption required for requested authentication mechanism.
550
Requested action not taken: mailbox unavailable [for mailbox not found, no access]
551
User not local; please try <forward-path>
552
Requested mail action terminated: exceeded storage allocation
553
Requested action not taken: mailbox name not allowed [for example, mailbox synt incorrect]
554
Transaction failed
Security Model
Owned by SYS with EXECUTE granted to PUBLIC
Best practice is to REVOKE EXECUTE from PUBLIC and grant on an as-need basis to specific application owners only
Sends AUTH command to authenticate to the SMTP server
Overload 1
utl_smtp.auth(
c IN OUT NOCOPY connection,
username IN VARCHAR2,
password IN VARCHAR2,
schemes IN VARCHAR2 DEFAULT NON_CLEARTEXT_PASSWORD_SCHEMES)
RETURN REPLY;
TBD
Overload 2
utl_smtp.auth(
c IN OUT NOCOPY connection,
username IN VARCHAR2,
password IN VARCHAR2,
schemes IN VARCHAR2 DEFAULT NON_CLEARTEXT_PASSWORD_SCHEMES);
utl_smtp.open_connection(
host IN VARCHAR2,
port IN PLS_INTEGER DEFAULT 25,
c OUT connection,
tx_timeout IN PLS_INTEGER DEFAULT NULL,
wallet_path IN VARCHAR2 DEFAULT NULL,
wallet_password IN VARCHAR2 DEFAULT NULL,
secure_connection_before_smtp IN BOOLEAN DEFAULT FALSE)
RETURN reply;
See Demos Below
Overload 2
utl_smtp.open_connection(
host IN VARCHAR2,
port IN PLS_INTEGER DEFAULT 25,
c OUT connection,
tx_timeout IN PLS_INTEGER DEFAULT NULL,
wallet_path IN VARCHAR2 DEFAULT NULL,
wallet_password IN VARCHAR2 DEFAULT NULL,
secure_connection_before_smtp IN BOOLEAN DEFAULT FALSE)
RETURN connection;
utl_smtp.helo(mail_conn, mailhost);
utl_smtp.mail(mail_conn, pSender);
utl_smtp.rcpt(mail_conn, pRecipient);
utl_smtp.data(mail_conn, mesg);
utl_smtp.quit(mail_conn);
EXCEPTION
WHEN INVALID_OPERATION THEN
utl_smtp.close_connection(mail_conn);
WHEN TRANSIENT_ERROR THEN
utl_smtp.close_connection(mail_conn);
WHEN PERMANENT_ERROR THEN
utl_smtp.close_connection(mail_conn);
WHEN OTHERS THEN
utl_smtp.close_connection(mail_conn);
END send_mail;
/
Demo from OTN
DECLARE
c utl_smtp.connection;
PROCEDURE send_header(name VARCHAR2, header VARCHAR2) AUTHID DEFINER AS
BEGIN
utl_smtp.write_data(c,name ||':'|| header || UTL_TCP.CRLF);
END;
BEGIN
c := utl_smtp.open_connection('smtp-server.morganslibrary.org');
utl_smtp.helo(c, 'morganslibrary.org');
utl_smtp.mail(c, 'mailsys@morganslibrary.com');
utl_smtp.rcpt(c, 'recipient@oracle.com');
utl_smtp.open_data(c);
send_header('From', '"Sender" <sender@morganslibrary.org>');
send_header('To', '"Recipient" <recipient@oracle.com>');
send_header('Subject', 'Hello');
utl_smtp.write_data(c, UTL_TCP.CRLF || 'Hello, world!');
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;
END;
raise_application_error(-20000, SQLERRM);
END;
/