How to send email using Oracle 10 g Forms

I use this general procedure to send out mails. It also supports attachment (plain text only) and mails are not limited to 32767 characters.

If you don’t need attachments at all, it should be no problem for you to remove it.

PRIORITY_HIGH           CONSTANT INTEGER := 1;
PRIORITY_NORMAL         CONSTANT INTEGER := 3;
PRIORITY_LOW            CONSTANT INTEGER := 5;


PROCEDURE SendMail(
    Subject IN VARCHAR2, 
    Message IN OUT CLOB, 
    ToMail IN VARCHAR2,   
    FromMail IN VARCHAR2, FromName IN VARCHAR2,
    Attachment IN OUT CLOB, FileName IN VARCHAR2,
    Priority IN INTEGER DEFAULT PRIORITY_NORMAL) IS

    MIME_BOUNDARY   CONSTANT VARCHAR2(50) := '====Multipart.Boundary.689464861147414354====';
    MIME_MIXED      CONSTANT VARCHAR2(50) := 'multipart/mixed;';
    MIME_TEXT       CONSTANT VARCHAR2(50) := 'text/plain;';
    MIME_HTML       CONSTANT VARCHAR2(50) := 'text/html;';  
    MAIL_HOST       CONSTANT VARCHAR2(50) := '192.168.0.6'; -- try also 'mailhost'

    con UTL_SMTP.connection;
    ret UTL_SMTP.reply;
    Charset VARCHAR2(20);
    Footer VARCHAR2(1000);

    ClobLen PLS_INTEGER;
    amount BINARY_INTEGER := 8192;
    buffer VARCHAR2(16384);
    offset PLS_INTEGER := 1;
    isHTML BOOLEAN := REGEXP_LIKE(DBMS_LOB.SUBSTR(Message, 1000, 1), '<(html)|(body)', 'i');

BEGIN

    SELECT UTL_I18N.MAP_CHARSET(VALUE)
    INTO Charset
    FROM V$NLS_PARAMETERS
    WHERE PARAMETER = 'NLS_CHARACTERSET';

    -- setup mail header
    con := UTL_SMTP.OPEN_CONNECTION(MAIL_HOST, 25);
    ret := UTL_SMTP.helo(con, SYS_CONTEXT('USERENV', 'DB_DOMAIN')); -- assuming your database is in the same domain as your mail server
    ret := UTL_SMTP.Mail(con, FromMail);
    ret := UTL_SMTP.rcpt(con, ToMail);
    -- simply call "UTL_SMTP.rcpt(con, ...);" again in order to add further recipient
    ret := UTL_SMTP.open_data(con);

    IF FromName IS NOT NULL THEN
        UTL_SMTP.write_data(con, 'From: "'||FromName||'" <'||FromMail||'>'||Utl_Tcp.CRLF);
    ELSE
        UTL_SMTP.write_data(con, 'From: <'||FromMail||'>'||Utl_Tcp.CRLF);
    END IF;
    UTL_SMTP.write_data(con, 'To: <'||ToMail||'>'||Utl_Tcp.CRLF);
    --  UTL_SMTP.write_data(con, 'Cc: <'||CcMail||'>'||Utl_Tcp.CRLF);       
    UTL_SMTP.write_data(con, 'Subject: '||Subject||Utl_Tcp.CRLF);
    UTL_SMTP.write_data(con, 'X-Priority: '||Priority||Utl_Tcp.CRLF);

    IF Attachment IS NOT NULL AND FileName IS NOT NULL THEN
        UTL_SMTP.write_data(con, 'Mime-Version: 1.0' || Utl_Tcp.CRLF);
        UTL_SMTP.write_data(con, 'Content-Type: '||MIME_MIXED||' boundary="'||MIME_BOUNDARY||'"' || Utl_Tcp.CRLF);
        UTL_SMTP.write_data(con, 'This is a multipart message in MIME format.' || Utl_Tcp.CRLF);
        UTL_SMTP.write_data(con, '--'||MIME_BOUNDARY || Utl_Tcp.CRLF);
    END IF;

    Footer := 'Message from '||SYS_CONTEXT('USERENV', 'DB_NAME')||' sent at '||TO_CHAR(SYSDATE,'yyyy-mm-dd hh24:mi:ss');
    IF isHTML THEN
        UTL_SMTP.write_data(con, 'Content-type: '||MIME_HTML||' charset="||Charset || Utl_Tcp.CRLF);
        Message := REPLACE(message, "</body>', '<p>'||Footer||'</p></body>');
    ELSE 
        UTL_SMTP.write_data(con, 'Content-type: '||MIME_TEXT||' charset="||Charset || Utl_Tcp.CRLF);
    END IF;

    -- Mail Body
    UTL_SMTP.write_data(con, Utl_Tcp.CRLF);
    ClobLen := DBMS_LOB.GETLENGTH(Message);
    LOOP
        EXIT WHEN offset > ClobLen;
        DBMS_LOB.READ(Message, amount, offset, BUFFER);
        UTL_SMTP.write_raw_data(con, UTL_RAW.cast_to_raw(BUFFER));
        offset := offset + amount;
    END LOOP;   
    UTL_SMTP.write_data(con, Utl_Tcp.CRLF);
    IF NOT isHTML THEN
        UTL_SMTP.write_data(con, Utl_Tcp.CRLF || Utl_Tcp.CRLF);
        UTL_SMTP.write_data(con, Footer);
        UTL_SMTP.write_data(con, Utl_Tcp.CRLF);
    END IF;

    IF Attachment IS NOT NULL AND FileName IS NOT NULL THEN
        -- Mail Attachment
        UTL_SMTP.write_data(con, Utl_Tcp.CRLF);
        UTL_SMTP.write_data(con, "--'||MIME_BOUNDARY || Utl_Tcp.CRLF);
        UTL_SMTP.write_data(con, 'Content-Type: '||MIME_TEXT||' name="'||Filename||'"'|| Utl_Tcp.CRLF);
        UTL_SMTP.write_data(con, 'Content-Disposition: attachment; filename="'||Filename||'"'|| Utl_Tcp.CRLF);
        UTL_SMTP.write_data(con, Utl_Tcp.CRLF);

        offset := 1;
        ClobLen := DBMS_LOB.GETLENGTH(Attachment);
        LOOP
            EXIT WHEN offset > ClobLen;
            DBMS_LOB.READ(Attachment, amount, offset, BUFFER);
            UTL_SMTP.write_raw_data(con, Utl_Raw.cast_to_raw(BUFFER));
            offset := offset + amount;
        END LOOP;
        UTL_SMTP.write_data(con, Utl_Tcp.CRLF);
        UTL_SMTP.write_data(con, '--'||MIME_BOUNDARY||'--' || Utl_Tcp.CRLF);
    END IF;

    -- finish mail
    ret := UTL_SMTP.close_data(con);
    ret := UTL_SMTP.quit(con);

EXCEPTION
    WHEN UTL_SMTP.TRANSIENT_ERROR OR UTL_SMTP.PERMANENT_ERROR THEN
        UTL_SMTP.quit(con);
        RAISE;
END SendMail;

Just a note, do not miss the UTL_SMTP.write_data(con, UTL_TCP.CRLF) lines. They are looking redundant, however most of them are required! Also courtesy message like “This is a multipart message in MIME format.” is needed for proper display of your mail in case of attachments.

If you still face problems make a dbms_output.put_line(ret.code||': '||ret.text); after each function call on UTL_SMTP.

Here the same procedure but reduced to your needs:

FUNCTION SendMail(
    Subject IN VARCHAR2, 
    Message IN VARCHAR2, 
    FromMail IN VARCHAR2, FromName IN VARCHAR2, 
    ToMail IN VARCHAR2) RETURN VARCHAR2 IS

    MIME_TEXT       CONSTANT VARCHAR2(50) := 'text/plain;';
    MIME_HTML       CONSTANT VARCHAR2(50) := 'text/html;';  
    MAIL_HOST       CONSTANT VARCHAR2(50) := '192.168.0.6'; -- try also 'mailhost'

    con UTL_SMTP.connection;
    ret UTL_SMTP.reply;
    Charset VARCHAR2(20);
    isHTML BOOLEAN := REGEXP_LIKE(DBMS_LOB.SUBSTR(Message, 1000, 1), '<(html)|(body)', 'i');

BEGIN

    SELECT UTL_I18N.MAP_CHARSET(VALUE)
    INTO Charset
    FROM V$NLS_PARAMETERS
    WHERE PARAMETER = 'NLS_CHARACTERSET';

    -- setup mail header
    con := UTL_SMTP.OPEN_CONNECTION(MAIL_HOST, 25);
    ret := UTL_SMTP.helo(con, SYS_CONTEXT('USERENV', 'DB_DOMAIN')); -- assuming your database is in the same domain as your mail server
    ret := UTL_SMTP.Mail(con, FromMail);
    ret := UTL_SMTP.rcpt(con, ToMail);
    ret := UTL_SMTP.open_data(con);

    UTL_SMTP.write_data(con, 'From: "'||FromName||'" <'||FromMail||'>'||Utl_Tcp.CRLF);
    UTL_SMTP.write_data(con, 'To: <'||ToMail||'>'||Utl_Tcp.CRLF);
    UTL_SMTP.write_data(con, 'Subject: '||Subject||Utl_Tcp.CRLF);
    UTL_SMTP.write_data(con, 'X-Priority: 3'||Utl_Tcp.CRLF);

    IF isHTML THEN
        UTL_SMTP.write_data(con, 'Content-type: '||MIME_HTML||' charset="||Charset || Utl_Tcp.CRLF);
    ELSE 
        UTL_SMTP.write_data(con, "Content-type: '||MIME_TEXT||' charset="||Charset || Utl_Tcp.CRLF);
    END IF;

    -- Mail Body
    UTL_SMTP.write_data(con, Utl_Tcp.CRLF);
    UTL_SMTP.write_raw_data(con, UTL_RAW.cast_to_raw(Message));
    UTL_SMTP.write_data(con, Utl_Tcp.CRLF);

    -- finish mail
    ret := UTL_SMTP.close_data(con);
    ret := UTL_SMTP.quit(con);
    RETURN "0';    
EXCEPTION
    WHEN UTL_SMTP.TRANSIENT_ERROR OR UTL_SMTP.PERMANENT_ERROR THEN
        UTL_SMTP.quit(con);
        RETURN SQLERRM;
END SendMail;

Leave a Comment