Skip to content

Instantly share code, notes, and snippets.

@seraphy
Created December 25, 2011 13:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save seraphy/1519233 to your computer and use it in GitHub Desktop.
Save seraphy/1519233 to your computer and use it in GitHub Desktop.
Oracle11gR2 Expressで本文UTF8エンコードの添付ファイルつきメール送信用ヘルパをパッケージとして作ってみた。
CREATE OR REPLACE PACKAGE MAILHELPER AS
/**
* SMTP接続先サーバ
*/
VC_MAILHOST VARCHAR2(64) := '127.0.0.1';
/**
* SMTP接続先ポート
*/
VC_MAILPORT NUMBER := 25;
/**
* メールアドレスの情報
*/
TYPE MAIL_ADDRESS IS RECORD(
/**
* アドレスの表記、不要ならばNULL
*/
DESCRIPTION NVARCHAR2(64),
/**
* アドレス.
* (RFCでは、メールアドレスは全体で256文字)
*/
EMAIL VARCHAR2(256)
);
/**
* メールアドレス情報のリスト
*/
TYPE MAIL_ADDRESS_LIST IS TABLE OF MAIL_ADDRESS INDEX BY binary_integer;
/**
* 添付ファイル情報
*/
TYPE ATTACHED_FILE IS RECORD(
/**
* 添付ファイル名.
* UTF8/16進数でのエンコードで出力される.
*/
FILE_NAME NVARCHAR2(256),
/**
* コンテンツタイプ。
* text/csvとか、application/octet-streamなど。
*/
CONTENT_TYPE VARCHAR2(48),
/**
* 添付ファイルとするバイナリデータ
*/
CONTENT BLOB
);
/**
* 複数添付ファイル
*/
TYPE ATTACHED_FILES IS TABLE OF ATTACHED_FILE INDEX BY binary_integer;
/**
* 添付なしのメール送信を行う。
* @param p_from 送信元メールアドレス
* @param p_to 送信先メールアドレス
* @param p_subject 件名
* @param p_message 本文
*/
PROCEDURE SENDMAIL(
p_from NVARCHAR2,
p_to NVARCHAR2,
p_subject NVARCHAR2,
p_message NVARCHAR2
);
/**
* 添付なしのメール送信を行う。
* @param p_from 送信元メールアドレス情報
* @param p_to 送信先メールアドレス情報のリスト
* @param p_subject 件名
* @param p_message 本文
*/
PROCEDURE SENDMAIL(
p_from MAIL_ADDRESS,
p_to_list MAIL_ADDRESS_LIST,
p_subject NVARCHAR2,
p_message NVARCHAR2
);
/**
* 添付ファイルありのメール送信を行う.
* @param p_from 送信元メールアドレス
* @param p_to 送信先メールアドレス
* @param p_subject 件名
* @param p_message 本文
* @param p_file 添付ファイル情報
*/
PROCEDURE SENDMAIL(
p_from NVARCHAR2,
p_to NVARCHAR2,
p_subject NVARCHAR2,
p_message NVARCHAR2,
p_file ATTACHED_FILE
);
/**
* 添付ファイルありのメール送信を行う.
* @param p_from 送信元メールアドレス情報
* @param p_to_list 送信先メールアドレス情報のリスト
* @param p_subject 件名
* @param p_message 本文
* @param p_files 添付ファイル情報
*/
PROCEDURE SENDMAIL(
p_from MAIL_ADDRESS,
p_to_list MAIL_ADDRESS_LIST,
p_subject NVARCHAR2,
p_message NVARCHAR2,
p_files ATTACHED_FILES
);
END MAILHELPER;
/
CREATE OR REPLACE package body MAILHELPER as
-- UTF8のOracle表現
UTF8 constant nvarchar2(250) := 'AL32UTF8';
-- 改行コード
CRLF CONSTANT VARCHAR2(2) := chr(13) || chr(10);
-- タブコード
TAB CONSTANT VARCHAR2(1) := chr(9);
-- 内部用、UTL_SMTPのハンドル
vHANDLE UTL_SMTP.CONNECTION;
/**
* 引数に指定した非ASCII文字を含む文字列を、UTF8/BASE64でエンコードし
* 80桁以内に収まるように折り返した複数行形式のデータに変換して返す.
* 返されたRAW型はASCII文字だけを含んでおり、メールヘッダの値として使用できる.
* 末尾に改行コードを付与するか指定することが可能.
*/
FUNCTION MAKE_HEADER_VALUE(
p_value NVARCHAR2,
p_CRLF BOOLEAN := TRUE
) RETURN RAW IS
-- ヘッダ部のUTF-8/BASE64エンコード開始マーカー
ENCMARK constant varchar2(10) := '=?UTF-8?B?';
-- ヘッダ部のエンコード終了マーカー
ENCMARK_EN constant varchar2(2) := '?=';
-- 変換結果 (32KiBが最大)
ret RAW(32767);
BEGIN
DECLARE
-- エンコード後のヘッダ行を1行80byteに納めるための分割文字数
-- UTF8なので日本語は3バイト程度に膨らむことを想定 (サロゲートペアは考慮外)
-- BASE64なので1.333倍に膨らむことを想定
CHUNKSIZE CONSTANT PLS_INTEGER := 12;
-- 入力データ(p_value)の文字数
MXLEN CONSTANT PLS_INTEGER := LENGTH(p_value);
-- 現在処理中の桁
pos PLS_INTEGER := 1;
-- 1行ごとに処理する対象文字列の切り出しバッファ
linechunk NVARCHAR2(12);
-- BASE64エンコード処理用バッファ
rawdata RAW(80);
BEGIN
LOOP
-- すべて処理したらループ終了
EXIT WHEN pos > MXLEN;
-- 分割後であれば改行+タブ
IF pos > 1 THEN
ret := UTL_RAW.CONCAT(
ret,
UTL_I18N.STRING_TO_RAW(CRLF || TAB, UTF8)
);
END IF;
-- 分割文字列の取得
linechunk := substr(p_value, pos, CHUNKSIZE);
-- UTF8に変換
rawdata := UTL_I18N.STRING_TO_RAW(linechunk, UTF8);
IF rawdata IS NULL THEN
RAISE_APPLICATION_ERROR(-20101, 'UTF8に変換できません。', FALSE);
END IF;
-- 出力
ret := UTL_RAW.CONCAT(
ret,
UTL_I18N.STRING_TO_RAW(ENCMARK, UTF8),
UTL_ENCODE.BASE64_ENCODE(rawdata),
UTL_I18N.STRING_TO_RAW(ENCMARK_EN, UTF8)
);
-- 次の位置へ進む
pos := pos + chunksize;
END LOOP;
IF p_CRLF THEN
-- 改行終端
ret := UTL_RAW.CONCAT(
ret,
UTL_I18N.STRING_TO_RAW(CRLF, UTF8)
);
END IF;
END;
RETURN ret;
END;
/**
* 添付ファイルのファイル名のエンコードをRFC2231により行う.
* 「filename*N*=xxxx」の形式の複数行となり、継続する場合は末尾はセミコロンとなる。
* エンコードは文字コード名の識別子につづいて16進数でエンコードされた文字が続く.
* (例) filename*0*=UTF-8''%E6%96%B0%E8%A6
* http://www.asahi-net.or.jp/~BD9Y-KTU/htmlrel_f/dtd_f/rfc_f/rfc2231j.html
* http://adiary.blog.abk.nu/0253
* @param filename 添付ファイル名
* @return UTF8の16進数表現でエンコードされたファイル名表現
*/
FUNCTION MAKE_ATTACHED_FILE_NAME(filename NVARCHAR2) RETURN RAW AS
buf RAW(32760);
c RAW(1);
pos PLS_INTEGER := 1;
mxlen PLS_INTEGER;
linebuf VARCHAR2(80) := 'UTF-8''''';
TYPE t_lines IS TABLE OF VARCHAR2(80) INDEX BY binary_integer;
lines t_lines;
BEGIN
IF filename IS NULL THEN
RETURN NULL;
END IF;
-- ファイル名をUTF8のバイナリに変換
buf := UTL_I18N.STRING_TO_RAW(filename, UTF8);
-- バイナリから「16進数」の文字列に変換。
-- 54文字を超えた場合は次の行に折り返す.
mxlen := UTL_RAW.LENGTH(buf);
LOOP
EXIT WHEN pos > mxlen;
IF LENGTH(linebuf) > 54 THEN
lines(lines.COUNT) := linebuf || ';';
linebuf := NULL;
END IF;
c := utl_raw.substr(buf, pos, 1);
linebuf := linebuf || '%' || rawtohex(c);
pos := pos + 1;
END LOOP;
lines(lines.COUNT) := linebuf;
-- ヘッダを構築してバイナリとして構築する.
buf := NULL;
FOR idx IN lines.FIRST .. lines.LAST
LOOP
IF lines.COUNT > 1 THEN
linebuf := TAB || 'filename*' || idx || '*=' || lines(idx);
ELSE
linebuf := TAB || 'filename*=' || lines(0);
END IF;
buf := UTL_RAW.CONCAT(
buf,
UTL_RAW.CAST_TO_RAW(linebuf),
UTL_RAW.CAST_TO_RAW(CRLF)
);
END LOOP;
RETURN buf;
END;
/**
* 内部用.
* From/Toなどのメールアドレスをもつヘッダを出力する。
* @param p_header ヘッダ
* @param p_to_list メールアドレスのリスト
*/
PROCEDURE WRITE_ADDRESS(
p_header VARCHAR2,
p_address_list MAIL_ADDRESS_LIST
) AS
BEGIN
-- ヘッダキー
UTL_SMTP.WRITE_RAW_DATA(
vHANDLE,
UTL_RAW.CONCAT(
UTL_RAW.CAST_TO_RAW(p_header)
)
);
-- メールアドレスの個数分繰り返す
FOR idx IN p_address_list.FIRST .. p_address_list.LAST
LOOP
IF idx > 1 THEN
UTL_SMTP.WRITE_RAW_DATA(
vHANDLE,
UTL_RAW.CONCAT(
UTL_I18N.STRING_TO_RAW(', '),
UTL_RAW.CAST_TO_RAW(CRLF),
UTL_RAW.CAST_TO_RAW(TAB)
)
);
END IF;
-- メールの表記が指定されていればUTF8+BASE64のMIMEヘッダエンコードで
-- 出力する。(必要に応じて継続行にする。)
DECLARE
description NVARCHAR2(60) := p_address_list(idx).DESCRIPTION;
mailaddr VARCHAR2(256) := p_address_list(idx).EMAIL;
nameraw RAW(32767);
linelen PLS_INTEGER;
BEGIN
IF description IS NOT NULL THEN
-- エンコードしたアドレス表記を出力
nameraw := MAKE_HEADER_VALUE(description, FALSE);
UTL_SMTP.WRITE_RAW_DATA(
vHANDLE,
nameraw
);
-- アドレス部をつづけて出力できるか、継続行にするか判定
linelen := UTL_RAW.LENGTH(nameraw) + length(mailaddr);
IF linelen >= 70 THEN -- アドレス前後の山括弧とヘッダ名を含まず
-- EMAILを出力するに桁数が足りない場合は継続行とする.
UTL_SMTP.WRITE_RAW_DATA(
vHANDLE,
UTL_RAW.CONCAT(
UTL_RAW.CAST_TO_RAW(CRLF),
UTL_RAW.CAST_TO_RAW(TAB)
)
);
ELSE
-- つづけてアドレス出力可能
UTL_SMTP.WRITE_RAW_DATA(
vHANDLE,
UTL_RAW.CAST_TO_RAW(' ')
);
END IF;
END IF;
END;
-- メールアドレスの出力。
-- 前後には山括弧をつける。
UTL_SMTP.WRITE_RAW_DATA(
vHANDLE,
UTL_RAW.CONCAT(
UTL_I18N.STRING_TO_RAW('<'),
UTL_I18N.STRING_TO_RAW(p_address_list(idx).EMAIL),
UTL_I18N.STRING_TO_RAW('>')
)
);
END LOOP;
-- ヘッダ終端
UTL_SMTP.WRITE_RAW_DATA(
vHANDLE,
UTL_RAW.CAST_TO_RAW(CRLF)
);
END;
/**
* 内部用.
* UTL_SMTPメール送信でハンドルを取得、送信先と基本ヘッダの設定までを行う.
* @param p_from 送信元メールアドレス
* @para, p_to 送信先メールアドレス
* @param p_subject 件名
*/
PROCEDURE OPEN_MAIL(
p_from MAIL_ADDRESS,
p_to_list MAIL_ADDRESS_LIST,
p_subject NVARCHAR2
) AS
p_from_list MAIL_ADDRESS_LIST;
BEGIN
p_from_list(1) := p_from;
-- SMTPサーバへの接続
vHANDLE := UTL_SMTP.OPEN_CONNECTION(VC_MAILHOST, VC_MAILPORT);
BEGIN
UTL_SMTP.HELO(vHANDLE, VC_MAILHOST);
-- MAIL FROM
UTL_SMTP.MAIL(vHANDLE, '<' || p_from.EMAIL || '>');
-- RCPT TOを宛先ごとに繰り返す
FOR idx IN p_to_list.FIRST .. p_to_list.LAST
LOOP
UTL_SMTP.RCPT(vHANDLE, '<' || p_to_list(idx).EMAIL || '>');
END LOOP;
-- メールデータ開始
UTL_SMTP.OPEN_DATA(vHANDLE);
-- FROMヘッダ
WRITE_ADDRESS('From: ', p_from_list);
-- TOヘッダ
WRITE_ADDRESS('To: ', p_to_list);
-- 件名ヘッダ
UTL_SMTP.WRITE_RAW_DATA(
vHANDLE,
UTL_RAW.CAST_TO_RAW('Subject: ')
);
UTL_SMTP.WRITE_RAW_DATA(
vHANDLE,
MAKE_HEADER_VALUE(p_subject)
);
EXCEPTION WHEN OTHERS THEN
BEGIN
-- コネクションをクローズする.
UTL_SMTP.QUIT(vHANDLE);
EXCEPTION WHEN OTHERS THEN
-- クローズの失敗は無視する.
NULL;
END;
vHANDLE := NULL;
RAISE;
END;
END;
/**
* メールオープン後の状態において、メール送信を閉じる.
*/
PROCEDURE QUIT_MAIL(p_abort IN BOOLEAN) IS
BEGIN
IF vHANDLE.HOST IS NOT NULL THEN
IF p_abort THEN
BEGIN
-- メールデータ破棄
UTL_SMTP.RSET(vHANDLE);
EXCEPTION WHEN OTHERS THEN
-- 破棄の失敗は無視する.
NULL;
END;
ELSE
-- メールデータ完了
UTL_SMTP.CLOSE_DATA(vHANDLE);
END IF;
BEGIN
-- コネクションをクローズする.
UTL_SMTP.QUIT(vHANDLE);
EXCEPTION WHEN OTHERS THEN
-- クローズの失敗は無視する.
NULL;
END;
-- ハンドルをクリアする.
vHANDLE := NULL;
END IF;
END;
/**
* 添付なしのメール送信を行う。
* @param p_from 送信元メールアドレス
* @param p_to 送信先メールアドレス
* @param p_subject 件名
* @param p_message 本文
*/
PROCEDURE SENDMAIL(
p_from NVARCHAR2,
p_to NVARCHAR2,
p_subject NVARCHAR2,
p_message NVARCHAR2
) AS
p_to_list MAIL_ADDRESS_LIST;
v_mail_from MAIL_ADDRESS;
v_mail_to MAIL_ADDRESS;
BEGIN
v_mail_from.EMAIL := p_from;
v_mail_to.EMAIL := p_to;
p_to_list(1) := v_mail_to;
SENDMAIL(v_mail_from, p_to_list, p_subject, p_message);
END;
/**
* 添付なしのメール送信を行う。
* @param p_from 送信元メールアドレス
* @param p_to 送信先メールアドレスのリスト
* @param p_subject 件名
* @param p_message 本文
*/
PROCEDURE SENDMAIL(
p_from MAIL_ADDRESS,
p_to_list MAIL_ADDRESS_LIST,
p_subject NVARCHAR2,
p_message NVARCHAR2
) IS
BEGIN
OPEN_MAIL(p_from, p_to_list, p_subject);
BEGIN
UTL_SMTP.WRITE_RAW_DATA(
vHANDLE,
UTL_RAW.CONCAT(
UTL_RAW.CAST_TO_RAW('MIME-version: 1.0'),
UTL_RAW.CAST_TO_RAW(CRLF),
UTL_RAW.CAST_TO_RAW('Content-type: text/plain; '),
UTL_RAW.CAST_TO_RAW('charset=UTF-8'),
UTL_RAW.CAST_TO_RAW(CRLF),
UTL_RAW.CAST_TO_RAW('Content-transfer-encoding: BASE64'),
UTL_RAW.CAST_TO_RAW(CRLF),
UTL_RAW.CAST_TO_RAW(CRLF),
UTL_ENCODE.BASE64_ENCODE(
UTL_I18N.STRING_TO_RAW(p_message, UTF8)
)
)
);
QUIT_MAIL(p_abort => false);
EXCEPTION WHEN OTHERS THEN
QUIT_MAIL(p_abort => true);
RAISE_APPLICATION_ERROR(-20120, 'メール送信に失敗しました。' || SQLERRM, TRUE);
END;
END;
/**
* 1個の添付ファイルありのメール送信を行う.
* @param p_from 送信元メールアドレス
* @param p_to 送信先メールアドレス
* @param p_subject 件名
* @param p_message 本文
* @param p_file 添付ファイル情報
*/
PROCEDURE SENDMAIL(
p_from NVARCHAR2,
p_to NVARCHAR2,
p_subject NVARCHAR2,
p_message NVARCHAR2,
p_file ATTACHED_FILE
) AS
p_files ATTACHED_FILES;
p_to_list MAIL_ADDRESS_LIST;
v_mail_from MAIL_ADDRESS;
v_mail_to MAIL_ADDRESS;
BEGIN
v_mail_from.EMAIL := p_from;
v_mail_to.EMAIL := p_to;
p_to_list(1) := v_mail_to;
p_files(p_files.COUNT + 1) := p_file;
SENDMAIL(v_mail_from, p_to_list, p_subject, p_message, p_files);
END;
/**
* 添付ファイルありのメール送信を行う.
* ただし、p_filesが空である場合は添付なしで送信される.
* @param p_from 送信元メールアドレス
* @param p_to_list 送信先メールアドレス
* @param p_subject 件名
* @param p_message 本文
* @param p_files 添付ファイル情報のコレクション、空の場合は添付なし
*/
PROCEDURE SENDMAIL(
p_from MAIL_ADDRESS,
p_to_list MAIL_ADDRESS_LIST,
p_subject NVARCHAR2,
p_message NVARCHAR2,
p_files ATTACHED_FILES
) AS
SEPARATOR CONSTANT varchar2(50) := '----_' || DBMS_RANDOM.STRING('A', 45);
BEGIN
IF p_files.FIRST IS NULL THEN
-- 添付ファイルなしの場合
SENDMAIL(p_from, p_to_list, p_subject, p_message);
RETURN;
END IF;
OPEN_MAIL(p_from, p_to_list, p_subject);
BEGIN
-- ヘッダ部の作成 (MIME)
UTL_SMTP.WRITE_RAW_DATA(
vHANDLE,
UTL_RAW.CONCAT(
UTL_RAW.CAST_TO_RAW('MIME-version: 1.0'),
UTL_RAW.CAST_TO_RAW(CRLF),
UTL_RAW.CAST_TO_RAW('Content-type: multipart/mixed;'),
UTL_RAW.CAST_TO_RAW(CRLF),
UTL_RAW.CAST_TO_RAW(' boundary=' || SEPARATOR),
UTL_RAW.CAST_TO_RAW(CRLF),
UTL_RAW.CAST_TO_RAW(CRLF)
)
);
-- 本文の作成
UTL_SMTP.WRITE_RAW_DATA(
vHANDLE,
UTL_RAW.CONCAT(
UTL_RAW.CAST_TO_RAW('--' || SEPARATOR),
UTL_RAW.CAST_TO_RAW(CRLF),
UTL_RAW.CAST_TO_RAW('Content-Type: text/plain; '),
UTL_RAW.CAST_TO_RAW('Charset=UTF-8'),
UTL_RAW.CAST_TO_RAW(CRLF),
UTL_RAW.CAST_TO_RAW('Content-transfer-encoding: BASE64'),
UTL_RAW.CAST_TO_RAW(CRLF),
UTL_RAW.CAST_TO_RAW(CRLF),
UTL_ENCODE.BASE64_ENCODE(
UTL_I18N.STRING_TO_RAW(p_message, UTF8)
),
UTL_RAW.CAST_TO_RAW(CRLF)
)
);
-- すべての添付ファイルを出力するループ
FOR idx IN p_files.FIRST .. p_files.LAST
LOOP
DECLARE
-- 対象添付ファイル
p_file ATTACHED_FILE := p_files(idx);
BEGIN
-- 添付ファイル開始
UTL_SMTP.WRITE_RAW_DATA(
vHANDLE,
UTL_RAW.CONCAT(
UTL_RAW.CAST_TO_RAW('--' || SEPARATOR),
UTL_RAW.CAST_TO_RAW(CRLF),
-- 添付ファイルのコンテンツタイプ
UTL_RAW.CAST_TO_RAW('Content-Type: '
|| p_file.CONTENT_TYPE || ';' || CRLF || TAB || 'name="'),
-- MIMEによるファイル名の指定 (Outlookなどは、こちらで認識する。)
MAKE_HEADER_VALUE(p_file.FILE_NAME, FALSE),
UTL_RAW.CAST_TO_RAW('"' || CRLF),
-- 添付ファイルのファイル名
-- Thunderbirdなどは、こちらで認識する。
UTL_RAW.CAST_TO_RAW('Content-Disposition: attachment;'),
UTL_RAW.CAST_TO_RAW(CRLF),
MAKE_ATTACHED_FILE_NAME(p_file.FILE_NAME),
-- 添付ファイルデータはBASE64によるエンコードされていることを示す.
UTL_RAW.CAST_TO_RAW('Content-transfer-encoding: BASE64'),
UTL_RAW.CAST_TO_RAW(CRLF),
-- MIMEヘッダ終了
UTL_RAW.CAST_TO_RAW(CRLF)
)
);
-- 添付ファイル出力
DECLARE
amount BINARY_INTEGER := 768; -- 48の倍数(3と4で割り切れる数, 48バイト=64桁);
pos pls_integer := 1;
blob_len pls_integer := dbms_lob.getlength(p_file.CONTENT);
buf raw(1152); -- BASE64変換後のサイズ(余裕を見て読み込みバイトの1.5倍を確保)
BEGIN
WHILE pos < blob_len
LOOP
DBMS_LOB.READ(p_file.CONTENT, amount, pos, buf);
UTL_SMTP.WRITE_RAW_DATA(
vHANDLE,
UTL_ENCODE.BASE64_ENCODE(buf) -- 64文字ごとに自動で改行コードが入る
);
buf := NULL;
pos := pos + amount;
END LOOP;
END;
END;
-- 添付ファイル終端
UTL_SMTP.WRITE_RAW_DATA(
vHANDLE,
UTL_RAW.CONCAT(
UTL_RAW.CAST_TO_RAW(CRLF)
)
);
END LOOP;
-- MIME終端
UTL_SMTP.WRITE_RAW_DATA(
vHANDLE,
UTL_RAW.CONCAT(
UTL_RAW.CAST_TO_RAW('--' || SEPARATOR || '--'),
UTL_RAW.CAST_TO_RAW(CRLF)
)
);
QUIT_MAIL(p_abort => false);
EXCEPTION WHEN OTHERS THEN
QUIT_MAIL(p_abort => true);
RAISE_APPLICATION_ERROR(-20120, 'メール送信に失敗しました。' || SQLERRM, TRUE);
END;
END;
END MAILHELPER;
/
DECLARE
P_FROM MAILHELPER.MAIL_ADDRESS;
P_TO MAILHELPER.MAIL_ADDRESS;
P_TO_LIST MAILHELPER.MAIL_ADDRESS_LIST;
P_SUBJECT NVARCHAR2(4000);
P_MESSAGE NVARCHAR2(4000);
P_FILES MAILHELPER.ATTACHED_FILES;
mes varchar2(4096);
rd raw(4096);
BEGIN
P_FROM.EMAIL := 'user2@localhost';
P_TO.EMAIL := 'user1@localhost';
P_TO_LIST(1) := P_TO;
P_SUBJECT := 'これはとてもながいとてもながいとてもながいとてもながいとてもながい件名';
FOR x IN 1..10 LOOP
P_MESSAGE := P_MESSAGE || 'これは添付ありテストメールです。' || chr(10);
END LOOP;
DECLARE
P_FILE MAILHELPER.ATTACHED_FILE;
BEGIN
FOR cnt IN 1 .. 10
LOOP
-- 添付ファイルデータを作成するためのバッファとして一時BLOBを作成する.
DBMS_LOB.CREATETEMPORARY(p_file.CONTENT, TRUE, DBMS_LOB.CALL);
-- 添付用テストデータ作成
FOR idx IN 1..10000
LOOP
mes := 'data-' || cnt || ': メッセージNo. ' || to_char(idx) || chr(10);
rd := UTL_I18N.STRING_TO_RAW(mes, 'UTF8');
DBMS_LOB.WRITEAPPEND(p_file.CONTENT, UTL_RAW.LENGTH(rd), rd);
END LOOP;
p_file.CONTENT_TYPE := 'text/plain; charset=UTF-8';
p_file.FILE_NAME := '添付ファイル・ダミーデータ №' || cnt || '.txt';
P_MESSAGE := '添付サイズ(' || cnt || ')=' || DBMS_LOB.GETLENGTH(p_file.CONTENT)
|| CHR(10) || P_MESSAGE;
p_files(cnt) := p_file;
END LOOP;
END;
MAILHELPER.SENDMAIL(
P_FROM => P_FROM,
P_TO_LIST => P_TO_LIST,
P_SUBJECT => P_SUBJECT,
P_MESSAGE => P_MESSAGE,
P_FILES => P_FILES
);
-- 一時BLOBの解放
FOR idx IN p_files.FIRST .. p_files.LAST
LOOP
DBMS_LOB.FREETEMPORARY(p_files(idx).CONTENT);
END LOOP;
END;
DECLARE
P_SUBJECT NVARCHAR2(200);
P_MESSAGE NVARCHAR2(200);
P_MAIL_FROM MAILHELPER.MAIL_ADDRESS;
P_MAIL_TO MAILHELPER.MAIL_ADDRESS;
P_MAIL_TO_LIST MAILHELPER.MAIL_ADDRESS_LIST;
BEGIN
P_MAIL_FROM.DESCRIPTION := '"開発用メール送信"<テスト担当>';
P_MAIL_FROM.EMAIL := 'user1@localhost';
P_MAIL_TO.DESCRIPTION := '開発用<1a>';
P_MAIL_TO.EMAIL := 'user1@localhost';
P_MAIL_TO_LIST(1) := P_MAIL_TO;
P_MAIL_TO.DESCRIPTION := '開発用,メール送信サーバ,テストユーザ2';
P_MAIL_TO.EMAIL := 'user2@localhost';
P_MAIL_TO_LIST(2) := P_MAIL_TO;
P_SUBJECT := 'テストメール123';
P_MESSAGE := 'これは添付なしメールテストです。';
MAILHELPER.SENDMAIL(
P_FROM => P_MAIL_FROM,
P_TO_LIST => P_MAIL_TO_LIST,
P_SUBJECT => P_SUBJECT,
P_MESSAGE => P_MESSAGE
);
END;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment