Tôi sử dụng gói này để gửi thư. Nó hoạt động tốt với các tệp đính kèm, hãy thử:
CREATE OR REPLACE PACKAGE BODY SENDMAIL_PKG AS
PRIORITY_HIGH CONSTANT INTEGER := 1;
PRIORITY_NORMAL CONSTANT INTEGER := 3;
PRIORITY_LOW CONSTANT INTEGER := 5;
SMTP_PORT CONSTANT INTEGER := 25;
SMTP_SERVER CONSTANT VARCHAR2(50) := 'mailhost';
SMTP_DOMIAN CONSTANT VARCHAR2(50) := SYS_CONTEXT('USERENV', 'DB_DOMAIN');
MIME_BOUNDARY CONSTANT VARCHAR2(50) := '=====Boundary======';
MIME_MIXED CONSTANT VARCHAR2(50) := 'multipart/mixed;';
MIME_TEXT CONSTANT VARCHAR2(50) := 'text/plain;';
DEFAULT_FROM_NAME CONSTANT VARCHAR2(50) := SYS_CONTEXT('USERENV', 'CURRENT_SCHEMA');
DEFAULT_FROM_MAIL CONSTANT VARCHAR2(50) := DEFAULT_FROM_NAME||'@'||SMTP_DOMIAN;
FUNCTION OpenConnection(ToEmail IN VARCHAR2, FromEmail IN VARCHAR2) RETURN UTL_SMTP.connection IS
con UTL_SMTP.connection;
BEGIN
-- setup mail header
con := UTL_SMTP.OPEN_CONNECTION(SMTP_SERVER, SMTP_PORT);
UTL_SMTP.helo(con, SMTP_DOMIAN);
UTL_SMTP.Mail(con, LOWER(FromEmail));
UTL_SMTP.rcpt(con, LOWER(ToEmail));
UTL_SMTP.open_data(con);
RETURN con;
END OpenConnection;
PROCEDURE PutHeader(con IN OUT UTL_SMTP.connection,
Subject IN VARCHAR2, ToEmail IN VARCHAR2,
FromEmail IN VARCHAR2, FromName IN VARCHAR2,
Priority IN INTEGER) IS
BEGIN
UTL_SMTP.write_data(con, 'From: "'||FromName||'" <'||LOWER(FromEmail)||'>'||UTL_TCP.CRLF);
UTL_SMTP.write_data(con, 'To: <'||LOWER(ToEmail)||'>'||UTL_TCP.CRLF);
UTL_SMTP.write_data(con, 'Subject: '||Subject||UTL_TCP.CRLF);
UTL_SMTP.write_data(con, 'X-Priority: '||Priority||UTL_TCP.CRLF);
END PutHeader;
PROCEDURE CloseMail(con IN OUT UTL_SMTP.connection) IS
BEGIN
-- finish mail
UTL_SMTP.close_data(con);
UTL_SMTP.quit(con);
END CloseMail;
-- Append default footer at the end of mail
PROCEDURE PutFooter(con IN OUT UTL_SMTP.connection) IS
sender VARCHAR2(1000);
BEGIN
-- put footer to end of mail
UTL_SMTP.write_data(con, UTL_TCP.CRLF || UTL_TCP.CRLF);
sender := SYS_CONTEXT('USERENV', 'DB_NAME')||'.'||SYS_CONTEXT('USERENV', 'DB_DOMAIN');
UTL_SMTP.write_data(con, 'Message from '||sender||' sent at '||TO_CHAR(LOCALTIMESTAMP, 'yyyy-mm-dd hh24:mi:ss'));
UTL_SMTP.write_data(con, UTL_TCP.CRLF);
END PutFooter;
-- Send Mail with CLOB attachment
PROCEDURE SendMail(
Subject IN VARCHAR2,
Message IN VARCHAR2,
ToEmail IN VARCHAR2,
Attachment IN CLOB, FilenameAttachment IN VARCHAR2,
FromEmail IN VARCHAR2 DEFAULT DEFAULT_FROM_MAIL,
FromName IN VARCHAR2 DEFAULT DEFAULT_FROM_NAME,
Priority IN INTEGER DEFAULT PRIORITY_NORMAL) IS
con UTL_SMTP.connection;
AttachmentLength PLS_INTEGER;
amount BINARY_INTEGER := 30000;
BUFFER VARCHAR2(32000);
offset PLS_INTEGER := 1;
BEGIN
con := OpenConnection(ToEmail, FromEmail);
PutHeader(con, Subject, ToEmail, FromEmail, FromName, Priority);
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, '--'||MIME_BOUNDARY || UTL_TCP.CRLF);
UTL_SMTP.write_data(con, 'Content-type: text/plain' || UTL_TCP.CRLF);
-- 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);
PutFooter(con);
-- 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="'||FilenameAttachment||'"'|| UTL_TCP.CRLF);
UTL_SMTP.write_data(con, 'Content-Disposition: attachment; filename="'||FilenameAttachment||'"'|| UTL_TCP.CRLF);
UTL_SMTP.write_data(con, UTL_TCP.CRLF);
AttachmentLength := DBMS_LOB.GETLENGTH(Attachment);
LOOP
EXIT WHEN offset > AttachmentLength;
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);
CloseMail(con);
END SendMail;
-- Send plain Mail without attachment
PROCEDURE SendMail(
Subject IN VARCHAR2,
Message IN VARCHAR2,
ToEmail IN VARCHAR2,
FromEmail IN VARCHAR2 DEFAULT DEFAULT_FROM_MAIL,
FromName IN VARCHAR2 DEFAULT DEFAULT_FROM_NAME,
Priority IN INTEGER DEFAULT PRIORITY_NORMAL) IS
con UTL_SMTP.connection;
BEGIN
con := OpenConnection(ToEmail, FromEmail);
PutHeader(con, Subject, ToEmail, FromEmail, FromName, Priority);
UTL_SMTP.write_data(con, 'Content-type: '||MIME_TEXT ||' charset='||GetCharset||UTL_TCP.CRLF );
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);
PutFooter(con);
CloseMail(con);
END SendMail;
END SENDMAIL_PKG;