Subject: Simple Example of Sending Attachments Using UTL_SMTP
Doc ID: 414062.1
Modified Date: 15-MAY-2008
Applies to:
PL/SQL - Version: 9.2.0.1 to 10.2.0.1
Information in this document applies to any platform.
Goal
How to send attachments using the PL/SQL package UTL_SMTP. The sample code uses the DBMS_LOB package to open and read the external file.
Solution
1. Create a simple file to test. Place it into your directory.
2. From SQLPlus run the following commands (please change the v_smtp_server variable to point to your mail server):
connect system/manager
grant create any directory to scott;
grant drop any directory to scott;
conn scott/tiger
drop directory DIR; --請注意Directory Name 要大寫,不然又會報錯了!! (tinalee)
create directory DIR as '/tmp/mydir'; --Change this to your directory on the file system
create or replace procedure mail_files (from_name varchar2,
to_name varchar2,
subject varchar2,
message varchar2,
max_size number default
9999999999,
p_oracle_directory varchar2,
p_binary_file varchar2)
is
v_smtp_server varchar2(100) := 'mail server'; --change this to your mail server
v_smtp_server_port number := 25;
v_directory_name varchar2(100);
v_file_name varchar2(100);
v_line varchar2(1000);
crlf varchar2(2):= chr(13) || chr(10);
mesg varchar2(32767);
conn utl_smtp.connection;
v_slash_pos number;
v_file_handle utl_file.file_type;
invalid_path exception;
mesg_length_exceeded boolean := false;
PROCEDURE write_raw(p_conn in out nocopy utl_smtp.connection,
p_message in raw) is
BEGIN
utl_smtp.write_raw_data(p_conn, p_message);
END write_raw;
PROCEDURE write_mime_header(p_conn in out nocopy utl_smtp.connection,
p_name in varchar2,
p_value in varchar2) is
BEGIN
write_raw(p_conn => p_conn,
p_message => utl_raw.cast_to_raw(p_name || ': ' || p_value || utl_tcp.crlf));
END write_mime_header;
PROCEDURE write_boundary(p_conn in out nocopy utl_smtp.connection,
p_last in boolean default false) AS
BEGIN
if (p_last) then
utl_smtp.write_data(p_conn, '--DMW.Boundary.605592468--'||crlf);
else
utl_smtp.write_data(p_conn, '--DMW.Boundary.605592468'||crlf);
end if;
END write_boundary;
PROCEDURE end_attachment(p_conn in out nocopy utl_smtp.connection,
p_last in boolean default true) IS
BEGIN
utl_smtp.write_data(p_conn, utl_tcp.crlf);
if (p_last) then
write_boundary(p_conn, p_last);
end if;
END end_attachment;
PROCEDURE begin_attachment(p_conn in out nocopy utl_smtp.connection,
p_mime_type in varchar2 default
'text/plain',
p_inline in boolean default false,
p_filename in varchar2 default null,
p_transfer_enc in varchar2 default null) is
BEGIN
write_boundary(p_conn);
if (p_transfer_enc is not null) then
write_mime_header(p_conn, 'Content-Transfer-Encoding',
p_transfer_enc);
end if;
write_mime_header(p_conn, 'Content-Type', p_mime_type);
if (p_filename is not null) then
if (p_inline) then
write_mime_header(p_conn, 'Content-Disposition', 'inline;
filename="' || p_filename || '"');
else
write_mime_header(p_conn,'Content-Disposition', 'attachment;
filename="' || p_filename || '"');
end if;
end if;
utl_smtp.write_data(p_conn, utl_tcp.crlf);
END begin_attachment;
PROCEDURE binary_attachment(p_conn in out utl_smtp.connection,
p_file_name in varchar2,
p_mime_type in varchar2) is
k_max_line_width constant pls_integer default 54;
v_amt binary_integer := 672 * 3; /* ensures proper format; 2016 */
v_bfile bfile;
v_file_len pls_integer;
v_buf raw(2100);
v_modulo pls_integer;
v_pieces pls_integer;v_file_pos pls_integer := 1;
v_data raw(2100);
v_chunks pls_integer;
BEGIN
begin_attachment(p_conn => p_conn,
p_mime_type => p_mime_type,
p_inline => TRUE,
p_filename => p_file_name,
p_transfer_enc => 'base64');
BEGIN
v_bfile := bfilename(p_oracle_directory, p_file_name);
v_file_len := dbms_lob.getlength(v_bfile);
v_modulo := MOD(v_file_len, v_amt);
v_pieces := TRUNC(v_file_len / v_amt);
if (v_modulo <> 0) then
v_pieces := v_pieces + 1;
end if;
dbms_lob.fileopen(v_bfile, dbms_lob.file_readonly);
dbms_lob.read(v_bfile, v_amt, v_file_pos, v_buf);
v_data := null;
for i in 1 .. v_pieces loop
v_file_pos := I * v_amt + 1;
v_file_len := v_file_len - v_amt;
v_data := utl_raw.concat(v_data, v_buf);
v_chunks := TRUNC(utl_raw.length(v_data) / k_max_line_width);
if (i <> v_pieces) then
v_chunks := v_chunks - 1;
end if;
write_raw(p_conn => p_conn, p_message => utl_encode.base64_encode
(v_data));
v_data := null;
if (v_file_len < v_amt AND v_file_len > 0) then
v_amt := v_file_len;
end if;
dbms_lob.READ(v_bfile, v_amt, v_file_pos, v_buf);
end loop;
END;
dbms_lob.fileclose(v_bfile);
end_attachment(p_conn => p_conn);
EXCEPTION
when no_data_found then
end_attachment(p_conn => p_conn);
dbms_lob.fileclose(v_bfile);
END binary_attachment;
BEGIN
conn:= utl_smtp.open_connection( v_smtp_server, v_smtp_server_port );
utl_smtp.helo( conn, v_smtp_server );
utl_smtp.mail( conn, from_name );
utl_smtp.rcpt( conn, to_name );
utl_smtp.open_data ( conn );
utl_smtp.write_data(conn, 'Subject: '||subject||crlf);
mesg:= 'Content-Transfer-Encoding: 7bit' || crlf || 'Content-Type: multipart/mixed;
boundary="DMW.Boundary.605592468"' || crlf ||
'Mime-Version: 1.0' || crlf ||
'--DMW.Boundary.605592468' || crlf ||
'Content-Transfer-Encoding: binary'||crlf||
'Content-Type: text/plain' ||crlf ||
crlf || message || crlf ;
utl_smtp.write_raw_data ( conn, utl_raw.cast_to_raw(mesg) );
binary_attachment(p_conn => conn,
p_file_name => p_binary_file,
p_mime_type => 'text/plain;
name="'||p_binary_file||'"');
utl_smtp.close_data( conn );
utl_smtp.quit( conn );
END;
/
3. To run the mail_files PL/SQL procedure from SQLPlus enter the following command (change email@address to the appropriate email addresses and myfile.txt to your filename):
exec mail_files('email@address', 'email@address', 'Subject Test Email Attachment', 'Message Test Email Attachment', 9999999999, 'DIR', 'myfile.txt');
4. The result is that you will receive an email with an inline attachment.
留言列表