/*
 * Copyright (c) 2009 The openGion Project.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */
package org.opengion.hayabusa.taglib;

import org.opengion.hayabusa.common.HybsSystem;
import org.opengion.hayabusa.common.HybsSystemException;
import org.opengion.hayabusa.resource.LDAPSearch;
import org.opengion.hayabusa.mail.MailPattern;
import org.opengion.fukurou.db.DBUtil;
import org.opengion.fukurou.mail.MailTX;
import org.opengion.fukurou.util.StringUtil;
import org.opengion.fukurou.util.ToString;						// 6.1.1.0 (2015/01/17)

import static org.opengion.fukurou.util.StringUtil.nval ;

import org.opengion.hayabusa.mail.MailModuleUtil;				// 5.9.2.3 (2015/11/27)

import java.util.List;
// import java.io.ObjectOutputStream;
// import java.io.ObjectInputStream;
// import java.io.IOException;

/**
 * メールを送信するための簡易タグです。
 *
 * Body 部に、メッセージを記述します。
 *
 * @og.formSample
 * ●形式:&lt;og:mailSender from="…" to="…" subject="･･･"/&gt;
 * ●body:あり(EVAL_BODY_BUFFERED:BODYを評価し、{&#064;XXXX} を解析します)
 *
 * ●Tag定義:
 *   &lt;og:mailSender
 *       subject            【TAG】タイトルを指定します
 *       from               【TAG】送信元(ＦＲＯＭ)アドレスを指定します
 *       to                 【TAG】送信先(ＴＯ)アドレスをCSV形式で指定します
 *       cc                 【TAG】送信先(ＣＣ)アドレスをCSV形式で指定します
 *       bcc                【TAG】送信先(ＢＣＣ)アドレスをCSV形式で指定します
 *       replyTo            【TAG】返信先(replyTo)アドレスをCSV形式で指定します
 *       host               【TAG】メールサーバーを指定します (初期値:COMMON_MAIL_SERVER[=])
 *       smtpPort           【TAG】SMTPポートをCSV形式で指定します(初期値:SMTP_PORT)	// 5.8.1.1 (2014/11/14)
 *       authType           【TAG】認証方式            初期値:MAIL_SEND_AUTH			// 5.8.1.1 (2014/11/14)
 *       authPort           【TAG】認証ポート          初期値:MAIL_SEND_AUTH_PORT		// 5.8.1.1 (2014/11/14)
 *       authUser           【TAG】認証ユーザー        初期値:MAIL_SEND_AUTH_USER		// 5.8.1.1 (2014/11/14)
 *       authPass           【TAG】認証パスワード      初期値:MAIL_SEND_AUTH_PASSWORD	// 5.8.1.1 (2014/11/14)
 *       useSSL             【TAG】SSL接続[false/true] 初期値:MAIL_SEND_USE_SSL			// 6.3.8.0 (2015/09/11)
 *       charset            【TAG】文字エンコーディングを指定します (初期値:MAIL_DEFAULT_CHARSET[=ISO-2022-JP])
 *       fileURL            【TAG】添付ファイルのセーブディレクトリを指定します (初期値:FILE_URL[=filetemp/])
 *       filename           【TAG】添付ファイル名をCSV形式で指定します
 *       useLDAP            【TAG】メールアドレスをLDAPを利用して取得するかどうか[true/false]を指定します(初期値:false)
 *       ldapKey            【TAG】アドレスを検索するキーを指定します(初期値:LDAP_MAILSEND_KEY[=uid] C社員番号)
 *       ldapVals           【TAG】LDAP検索時の属性名を指定します(初期値:LDAP_MAILSEND_VALS[=cn,mail])
 *       useDB              【TAG】メールアドレスをDB(GE35)を利用して取得するかどうか[true/false]を指定します(初期値:false)
 *       useHistory         【TAG】GE32,34に送信履歴を保存するかどうか[true/false]を指定します(初期値:USE_MAILSENDER_HISTORY)
 *       debug              【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false)
 *   &gt;   ... Body ...
 *   &lt;/og:mailSender&gt;
 *
 * ●使用例
 *     &lt;og:mailSender from=&quot;C00000&quot; to=&quot;C99999&quot; subject=&quot;{&#064;SUBJECT}&quot; &gt;
 *          メール内容
 *     &lt;/og:mailSender &gt;
 *
 *        charset   = キャラクタセット  (例:Windows-31J , ISO-2022-JP)
 *        from      = From       送信元
 *        to        = To         送信先(複数登録可能)
 *        cc        = Cc         送信先(複数登録可能)
 *        bcc       = Bcc        送信先(複数登録可能)
 *        replyTo   = ReplyTo    返信先先(複数登録可能)
 *        useLDAP   = false/true メールアドレスをLDAPを利用して取得するかどうか
 *        ldapKey   = "uid"      アドレスを検索するキー(初期値:システムリソース C社員番号)
 *        ldapVals  = "cn,mail"  LDAP検索時の属性名。ひとつならアドレス。２つなら名前とアドレス
 *        host      = SMTPサーバー名
 *        smtpPort  = SMTPポート          初期値:SMTP_PORT					// 5.8.1.1 (2014/11/14)
 *        authType  = 認証方式            初期値:MAIL_SEND_AUTH				// 5.8.1.1 (2014/11/14)
 *        authPort  = 認証ポート          初期値:MAIL_SEND_AUTH_PORT		// 5.8.1.1 (2014/11/14)
 *        authUser  = 認証ユーザー        初期値:MAIL_SEND_AUTH_USER		// 5.8.1.1 (2014/11/14)
 *        authPass  = 認証パスワード      初期値:MAIL_SEND_AUTH_PASSWORD	// 5.8.1.1 (2014/11/14)
 *        useSSL    = SSL接続[false/true] 初期値:MAIL_SEND_USE_SSL			// 6.3.8.0 (2015/09/11)
 *        subject   = タイトル
 *        fileURL   = 添付ファイルのセーブディレクトリ
 *        filename  = 添付ファイル名(ローカルにセーブされたファイル名)(複数登録可能)
 *        debug     = true/false;
 *
 * 複数登録可能な個所は、CSV形式で、複数登録できます。
 * アドレス(from,to,cc,bcc,replyTo)は、『"名称" &lt;メールアドレス&gt;』形式が
 * 指定できます。&lt; と &gt; で囲まれた範囲がメールアドレスになります。
 * 名称には、漢字が使用できます。
 *
 * host は、システムパラメータ の COMMON_MAIL_SERVER 属性が初期値で設定されます。
 * charset は、システムパラメータ の MAIL_DEFAULT_CHARSET 属性が初期値で設定されます。
 *
 * @og.group その他出力
 *
 * @version  4.0
 * @author   Kazuhiko Hasegawa
 * @since    JDK5.0,
 */
public class MailSenderTag extends CommonTagSupport {
	/** このプログラムのVERSION文字列を設定します。	{@value} */
	private static final String VERSION = "6.4.2.1 (2016/02/05)" ;
	private static final long serialVersionUID = 642120160205L ;

	private transient MailTX mail ;
	private String		host	= HybsSystem.sys( "COMMON_MAIL_SERVER" );
	private String		charset	= HybsSystem.sys( "MAIL_DEFAULT_CHARSET" );	// 3.5.6.6 (2004/08/23)
	private String		from	;
	private String[]	to		;
	private String[]	cc		;
	private String[]	bcc		;
	private String[]	replyTo	;
	private String		subject	;
	private String[]	filename;
	private String		fileURL	= HybsSystem.sys( "FILE_URL" );

	private String		smtpPort= HybsSystem.sys( "SMTP_PORT" );					// 5.8.1.1 (2014/11/14)
	private String		authType= HybsSystem.sys( "MAIL_SEND_AUTH" );				// 5.8.1.1 (2014/11/14)
	private String		authPort= HybsSystem.sys( "MAIL_SEND_AUTH_PORT" );			// 5.8.1.1 (2014/11/14)
	private String		authUser= HybsSystem.sys( "MAIL_SEND_AUTH_USER" );			// 5.8.1.1 (2014/11/14)
	private String		authPass= HybsSystem.sys( "MAIL_SEND_AUTH_PASSWORD" );		// 5.8.1.1 (2014/11/14)
	private boolean		useSSL	= HybsSystem.sysBool( "MAIL_SEND_USE_SSL" );		// 6.3.8.0 (2015/09/11)

	private boolean		useLDAP	;				// 3.7.1.0 (2005/04/15)
	// uid C社員番号 、employeeNumber 社員番号
	private String		ldapKey	= HybsSystem.sys( "LDAP_MAILSEND_KEY" );		// 5.6.7.0 (2013/07/27)
	private String		ldapVals= HybsSystem.sys( "LDAP_MAILSEND_VALS" );		// 5.6.7.0 (2013/07/27)

	private boolean		useDB	;				// 5.6.9.3 (2013/10/25) GE35からメールアドレスを取得
	private final String DBID	= HybsSystem.sys( "RESOURCE_DBID" );

	// 5.9.2.3 (2015/11/27) ログを残す設定
	private boolean		useHistory	= HybsSystem.sysBool( "USE_MAILSENDER_HISTORY" );
	private String		message;

	/**
	 * デフォルトコンストラクター
	 *
	 * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor.
	 */
	public MailSenderTag() {
		super();		// これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。
	}

	/**
	 * Taglibの開始タグが見つかったときに処理する doStartTag() を オーバーライドします。
	 *
	 * @og.rev 6.3.8.0 (2015/09/11) SSL接続するかどうかを指定するパラメータを追加します。
	 *
	 * @return	後続処理の指示( EVAL_BODY_BUFFERED )
	 */
	@Override
	public int doStartTag() {
//		mail = new MailTX( host,charset,smtpPort,authType,authPort,authUser,authPass );			// 5.8.1.1 (2014/11/14)
		mail = new MailTX( host,charset,smtpPort,authType,authPort,authUser,authPass,useSSL );	// 6.3.8.0 (2015/09/11)
		return EVAL_BODY_BUFFERED ;	// Body を評価する。( extends BodyTagSupport 時)
	}

	/**
	 * Taglibのタグ本体を処理する doAfterBody() を オーバーライドします。
	 *
	 * @og.rev 3.1.1.0 (2003/03/28) ボディの内容を取得する処理を、CommonTagSupport で行う。
	 * @og.rev 5.9.2.3 (2015/11/27) messageをインスタンス変数に変更。
	 *
	 * @return	後続処理の指示(SKIP_BODY)
	 */
	@Override
	public int doAfterBody() {
//		final String message = getBodyString();
		message = getBodyString();				// 5.9.2.3

		mail.setMessage( message );

		return SKIP_BODY ;
	}

	/**
	 * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。
	 *
	 * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応。release2() を doEndTag()で呼ぶ。
	 * @og.rev 3.7.1.0 (2005/04/15) LDAP検索 新規追加
	 * @og.rev 5.6.9.3 (2013/10/25) 送信後に履歴を残す(history追加)。mailSender2同様、ここがエラーでもメール送信は完了しているので注意。
	 * @og.rev 5.9.3.0 (2015/12/04) useHistory対応
	 *
	 * @return	後続処理の指示
	 */
	@Override
	public int doEndTag() {
		debugPrint();		// 4.0.0 (2005/02/28)

		// 3.7.1.0 (2005/04/15) LDAP検索 新規追加
		if( useLDAP ) {
			final String[] vals = StringUtil.csv2Array( ldapVals );

			final LDAPSearch serch = new LDAPSearch();
			serch.setAttributes( vals );
			serch.init();

			from	= setLDAPAddress( serch,from	);
			to		= setLDAPAddress( serch,to		);
			cc		= setLDAPAddress( serch,cc		);
			bcc		= setLDAPAddress( serch,bcc		);
			replyTo	= setLDAPAddress( serch,replyTo	);
		}
		else if( useDB ){ // 5.6.9.3 (2013/10/25) GE35からメールアドレスを取得
			final String[] from_array = {from};
			from	= getAddressArray( from_array )[0];
			to		= getAddressArray( to		);
			cc		= getAddressArray( cc		);
			bcc		= getAddressArray( bcc		);
			replyTo	= getAddressArray( replyTo	);
		}

		mail.setFrom( from );
		mail.setTo( to );
		mail.setCc( cc );
		mail.setBcc( bcc );
		mail.setReplyTo( replyTo );
		mail.setSubject( subject );
		mail.setDebug( isDebug() );

		String[] temp = null;
		if( filename != null && filename.length > 0 ) {
//			String[] temp = new String[filename.length];
			temp = new String[filename.length];
			final String directory = HybsSystem.url2dir( fileURL );
			for( int i=0; i<temp.length; i++ ) {
				temp[i] = StringUtil.urlAppend( directory, filename[i] );
			}
			mail.setFilename( temp );
		}

		mail.sendmail() ;

		// 5.9.2.3 (2015/11/27) 送信後に履歴を残す(history追加)。mailSender2同様、ここがエラーでもメール送信は完了しているので注意。
		if( useHistory ){
			final MailModuleUtil mmu = new MailModuleUtil();
//			mmu.setInitParams( sys("SYSTEM_ID"), from, to, cc, bcc, message, subject, getUserInfo("ID"), getGUIInfoAttri("KEY") );
			mmu.setInitParams( sys("SYSTEM_ID"), from, to, cc, bcc, message, subject, getUserInfo("ID"), getGUIInfoAttri("KEY") ,temp ); // 5.9.3.0
			mmu.commitMailDB();
		}

		return EVAL_PAGE ;
	}

	/**
	 * タグリブオブジェクトをリリースします。
	 * キャッシュされて再利用されるので、フィールドの初期設定を行います。
	 *
	 * @og.rev 2.0.0.4 (2002/09/27) カスタムタグの release() メソッドを、追加
	 * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応。release2() を doEndTag()で呼ぶ。
	 * @og.rev 3.7.1.0 (2005/04/15) LDAP検索 useLDAP,ldapKey,ldapVals 属性追加
	 * @og.rev 5.6.7.0 (2013/07/27) ldapKey,ldapValsの取得をリソースに変更
	 * @og.rev 5.6.9.3 (2013/10/25) useDB追加
	 * @og.rev 5.8.1.1 (2014/11/14) メール送信時認証追加。smtpPort,authPort,authType,authUser,authPass
	 * @og.rev 6.3.8.0 (2015/09/11) SSL接続するかどうかを指定するパラメータを追加します。
	 * @og.rev 5.6.9.3 (2013/10/25) 送信後に履歴を残す(history追加)。
	 */
	@Override
	protected void release2() {
		super.release2();
		mail	 	= null;
		host	 	= HybsSystem.sys( "COMMON_MAIL_SERVER" );
		charset  	= HybsSystem.sys( "MAIL_DEFAULT_CHARSET" );			// 3.5.6.6 (2004/08/23)
		from	 	= null;
		to			= null;
		cc		 	= null;
		bcc 	 	= null;
		replyTo  	= null;
		subject  	= null;
		fileURL  	= HybsSystem.sys( "FILE_URL" );
		filename 	= null;
		useLDAP	 	= false;											// 3.7.1.0 (2005/04/15)
		ldapKey		= HybsSystem.sys( "LDAP_MAILSEND_KEY" );			// 5.6.7.0 (2013/07/27)
		ldapVals	= HybsSystem.sys( "LDAP_MAILSEND_VALS" );			// 5.6.7.0 (2013/07/27)
		useDB 		= false;				// 5.6.9.3 (2013/10/25) GE35からメールアドレスを取得
		smtpPort	= HybsSystem.sys( "SMTP_PORT" );					// 5.8.1.1 (2014/11/14)
		authType	= HybsSystem.sys( "MAIL_SEND_AUTH" );				// 5.8.1.1 (2014/11/14)
		authPort	= HybsSystem.sys( "MAIL_SEND_AUTH_PORT" );			// 5.8.1.1 (2014/11/14)
		authUser	= HybsSystem.sys( "MAIL_SEND_AUTH_USER" );			// 5.8.1.1 (2014/11/14)
		authPass	= HybsSystem.sys( "MAIL_SEND_AUTH_PASSWORD" );		// 5.8.1.1 (2014/11/14)
		useSSL		= HybsSystem.sysBool( "MAIL_SEND_USE_SSL" );		// 6.3.8.0 (2015/09/11)
		useHistory	= HybsSystem.sysBool( "USE_MAILSENDER_HISTORY" );	// 5.9.2.3 (2015/11/27)
		message		= null;												// 5.9.2.3 (2015/11/27)
	}

	/**
	 * LDAP を利用したメールアドレスを設定し直します。
	 *
	 * LDAPより、ldapKeyをキーに、ldapVals を設定値として、読み込みます。
	 * 初期値は、ldapKeyは、uid(ユニークID) ldapValsは、cn,mail(名前、メールアドレス)となっています。
	 * from,to,cc,bcc,replyTo の設定値を、target にセットして、検索します。
	 * 通常、このメソッドは、useLDAP=true の場合に呼び出すように設定します。
	 * target が null か、ゼロ文字列か メールアドレス(ここでは、&#064; 文字を含むかどうかで判定)の場合、
	 * そのまま target を返します。
	 *
	 * @og.rev 3.7.1.0 (2005/04/15) LDAP検索 新規追加
	 *
	 * @param	serch	LDAPSearchオブジェクト
	 * @param	target	ldapKeyキーに対する設定値
	 *
	 * @return	メールアドレス
	 * @see   #setLDAPAddress( LDAPSearch serch, String[] targets )
	 */
	private String setLDAPAddress( final LDAPSearch serch, final String target ) {
		final String rtnAdrs ;

		if( target != null && target.indexOf( '@' ) < 0 ) {
			final List<String[]> list = serch.search( ldapKey + "=" + target );
			if( list.size() == 1 ) {
				final String[] vals = list.get(0);
				if( ldapVals.indexOf(',') < 0 ) {	// 検索値が２つの場合でない
					rtnAdrs = vals[0] ;		// メールアドレスのみ
				}
				else {
					rtnAdrs = vals[0] + "<" + vals[1] + ">" ;	// "名前<aaaa@bbbb>" 形式
				}
			}
			else {
				final String errMsg = "LDAP検索の結果、メールアドレスが見つかりませんでした。"
							+ "設定値=[" + target + "] , 検索キー=[" + ldapKey + "] , 検索属性=["
							+ ldapVals + "]" ;
				throw new HybsSystemException( errMsg );
			}
		}
		else {
			rtnAdrs = target;
		}

		return rtnAdrs ;
	}

	/**
	 * LDAP を利用した複数のメールアドレスを取得します。
	 *
	 * LDAPより、ldapKeyをキーに、ldapVals を設定値として、読み込みます。
	 * 初期値は、ldapKeyは、uid(ユニークID) ldapValsは、cn,mail(名前、メールアドレス)となっています。
	 * from,to,cc,bcc,replyTo の設定値を、target にセットして、検索します。
	 * 通常、このメソッドは、useLDAP=true の場合に呼び出すように設定します。
	 * target がメールアドレスの場合、(ここでは、&#064; 文字を含むかどうかで判定)そのまま返します。
	 *
	 * @og.rev 3.7.1.0 (2005/04/26) LDAP検索 新規追加
	 *
	 * @param	serch	LDAPSearchオブジェクト
	 * @param	targets	ldapKeyキーに対する設定値の配列
	 *
	 * @return	複数のメールアドレス配列
	 * @og.rtnNotNull
	 * @see   #setLDAPAddress( LDAPSearch serch, String target )
	 */
	private String[] setLDAPAddress( final LDAPSearch serch, final String[] targets ) {
		// 6.1.1.0 (2015/01/17) 可変長引数でもnullは来る。
		if( targets == null || targets.length == 0 ) { return targets; }

		String[] rtn = new String[targets.length];

		for( int i=0; i<targets.length; i++ ) {
			rtn[i] = setLDAPAddress( serch,targets[i] );
		}
		return rtn ;
	}

	/**
	 * 【TAG】送信元(ＦＲＯＭ)アドレスを指定します。
	 *
	 * @og.tag 送信元(ＦＲＯＭ)アドレスを指定します。
	 *
	 * @param   fromAdrs 送信元(ＦＲＯＭ)アドレス
	 */
	public void setFrom( final String fromAdrs ) {
		from = nval( getRequestParameter( fromAdrs ), from );
	}

	/**
	 * 【TAG】送信先(ＴＯ)アドレスをCSV形式で指定します。
	 *
	 * @og.tag
	 * 複数アドレスをCSV形式でセットできます。
	 *
	 * @og.rev 3.5.6.2 (2004/07/05) 先に配列に分解してからリクエスト変数の値を取得
	 * @og.rev 3.5.6.4 (2004/07/16) 先にリクエスト変数の値を取得してから配列に分解
	 *
	 * @param   toAdrs 送信先(ＴＯ)アドレス(CSV形式)
	 */
	public void setTo( final String toAdrs ) {
		to = StringUtil.csv2ArrayOnly( getRequestParameter( toAdrs ) );
	}

	/**
	 * 【TAG】送信先(ＣＣ)アドレスをCSV形式で指定します。
	 *
	 * @og.tag
	 * 複数アドレスをCSV形式でセットできます。
	 *
	 * @og.rev 3.5.6.2 (2004/07/05) 先に配列に分解してからリクエスト変数の値を取得
	 * @og.rev 3.5.6.4 (2004/07/16) 先にリクエスト変数の値を取得してから配列に分解
	 *
	 * @param   ccAdrs 送信先(ＣＣ)アドレス(CSV形式)
	 */
	public void setCc( final String ccAdrs ) {
		cc = StringUtil.csv2ArrayOnly( getRequestParameter( ccAdrs ) );
	}

	/**
	 * 【TAG】送信先(ＢＣＣ)アドレスをCSV形式で指定します。
	 *
	 * @og.tag
	 * 複数アドレスをCSV形式でセットできます。
	 *
	 * @og.rev 3.5.6.2 (2004/07/05) 先に配列に分解してからリクエスト変数の値を取得
	 * @og.rev 3.5.6.4 (2004/07/16) 先にリクエスト変数の値を取得してから配列に分解
	 *
	 * @param   bccAdrs 送信先(ＢＣＣ)アドレス(CSV形式)
	 */
	public void setBcc( final String bccAdrs ) {
		bcc = StringUtil.csv2ArrayOnly( getRequestParameter( bccAdrs ) );
	}

	/**
	 * 【TAG】返信先(replyTo)アドレスをCSV形式で指定します。
	 *
	 * @og.tag
	 * 複数アドレスをCSV形式でセットできます。
	 *
	 * @og.rev 3.5.6.6 (2004/08/23) 新規追加
	 *
	 * @param   replyToAdrs 返信先(replyTo)アドレス(CSV形式)
	 */
	public void setReplyTo( final String replyToAdrs ) {
		replyTo = StringUtil.csv2ArrayOnly( getRequestParameter( replyToAdrs ) );
	}

	/**
	 * 【TAG】メールサーバーを指定します
	 *		(初期値:COMMON_MAIL_SERVER[={@og.value SystemData#COMMON_MAIL_SERVER}])。
	 *
	 * @og.tag メールサーバーを指定します。
	 * (初期値:システム定数のCOMMON_MAIL_SERVER[={@og.value SystemData#COMMON_MAIL_SERVER}])。
	 *
	 * @og.rev 3.5.6.6 (2004/08/23) 初期値を考慮するように変更。
	 *
	 * @param   hst メールサーバー
	 * @see		org.opengion.hayabusa.common.SystemData#COMMON_MAIL_SERVER
	 */
	public void setHost( final String hst ) {
		host = nval( getRequestParameter( hst ),host );
	}

	/**
	 * 【TAG】タイトルを指定します。
	 *
	 * @og.tag タイトルを指定します。
	 *
	 * @param   subjct タイトル
	 */
	public void setSubject( final String subjct ) {
		this.subject = getRequestParameter( subjct );
	}

	/**
	 * 【TAG】添付ファイル名をCSV形式で指定します。
	 *
	 * @og.tag
	 * 複数ファイルをセットできます。
	 * 設定方法は、カンマで区切って並べ複数指定できます。
	 *
	 * @og.rev 3.5.6.6 (2004/08/23) 複数ファイル指定方法を、重複リクエストからCSV形式に変更
	 *
	 * @param   fname 添付ファイル名(CSV形式)
	 */
	public void setFilename( final String fname ) {
		filename = StringUtil.csv2ArrayOnly( getRequestParameter( fname ) );
	}

	/**
	 * 【TAG】文字エンコーディングを指定します
	 *		(初期値:MAIL_DEFAULT_CHARSET[={@og.value SystemData#MAIL_DEFAULT_CHARSET}])。
	 *
	 * @og.tag
	 * 文字エンコーディングは、メール本文に対するエンコーディング指定です。
	 * これは、Windows-31J 、MS932、Shift_JIS のどれかが指定された場合、
	 * 『指定の文字コード + 8bit 送信』します。
	 * それ以外の指定は、『ISO-2022-JP に独自変換 + 7bit 送信』になります。
	 * (初期値:システム定数のMAIL_DEFAULT_CHARSET[={@og.value SystemData#MAIL_DEFAULT_CHARSET}])。
	 *
	 * @param   chset 文字エンコーディング
	 * @see		org.opengion.hayabusa.common.SystemData#MAIL_DEFAULT_CHARSET
	 */
	public void setCharset( final String chset ) {
		charset = nval( getRequestParameter( chset ),charset );
	}

	/**
	 * 【TAG】添付ファイルのセーブディレクトリを指定します
	 *		(初期値:FILE_URL[={@og.value SystemData#FILE_URL}])。
	 *
	 * @og.tag
	 * この属性で指定されるディレクトリに、添付ファイルが存在すると仮定します。
	 * 指定方法は、通常の fileURL 属性と同様に、先頭が、'/' (UNIX) または、２文字目が、
	 * ":" (Windows)の場合は、指定のURLそのままのディレクトリに、そうでない場合は、
	 * fileURL = "{&#064;USER.ID}" と指定すると、FILE_URL 属性で指定のフォルダの下に、
	 * さらに、各個人ID別のフォルダを作成して、そこを使用します。
	 * (初期値:システム定数のFILE_URL[={@og.value SystemData#FILE_URL}])。
	 *
	 * @og.rev 4.0.0.0 (2005/01/31) StringUtil.urlAppend メソッドの利用
	 * @og.rev 4.0.0.0 (2007/11/20) 指定されたディレクトリ名の最後が"\"or"/"で終わっていない場合に、"/"を付加する。
	 * @og.rev 6.4.2.1 (2016/02/05) URLの最後に、"/" を追加する処理を廃止。
	 *
	 * @param	url 添付ファイルのセーブディレクトリ
	 * @see		org.opengion.hayabusa.common.SystemData#FILE_URL
	 */
	public void setFileURL( final String url ) {
		final String furl = nval( getRequestParameter( url ),null );
		if( furl != null ) {
//			final char ch = furl.charAt( furl.length()-1 );
//			if( ch != '/' && ch != '\\' ) { furl = furl + "/"; }
			fileURL = StringUtil.urlAppend( fileURL,furl );
		}
	}

	/**
	 * 【TAG】メールアドレスをLDAPを利用して取得するかどうか[true/false]を指定します(初期値:false)。
	 *
	 * @og.tag
	 * LDAP のメールアドレスを取得する場合は、true をセットします。false の場合は、
	 * from,to,cc,bcc,replyTo の設定値がそのまま使用されます。
	 * 上記アドレスに、&#064; を含む場合は、LDAP を検索せず、メールアドレスとして
	 * そのまま使用します。LDAP の検索結果が存在しない場合は、不正なアドレスとして、
	 * エラーとします。
	 * 初期値は、false です。
	 *
	 * @og.rev 3.7.1.0 (2005/04/15) LDAP検索 新規追加
	 *
	 * @param   useLDAP メールアドレスのLDAP利用 [true:利用する/false:利用しない]
	 */
	public void setUseLDAP( final String useLDAP ) {
		this.useLDAP = nval( getRequestParameter( useLDAP ),this.useLDAP );
	}

	/**
	 * 【TAG】アドレスを検索するキーを指定します(初期値:uid C社員番号)。
	 *
	 * @og.tag
	 * LDAP のメールアドレスを取得する場合の、検索するキーを指定します。
	 * from,to,cc,bcc,replyTo の設定値を、このキーにセットして、検索します。
	 * uid C社員番号 、employeeNumber 社員番号 などが考えられます。
	 * 初期値は、uid(C社員番号)です。
	 * このキーで複数の検索結果が得られた場合は、エラーとします。
	 *
	 * @og.rev 3.7.1.0 (2005/04/15) LDAP検索 新規追加
	 *
	 * @param   ldapKey アドレスを検索するキー
	 */
	public void setLdapKey( final String ldapKey ) {
		this.ldapKey = nval( getRequestParameter( ldapKey ),this.ldapKey );
	}

	/**
	 * 【TAG】LDAP検索時の属性名を指定します(初期値:cn,mail)。
	 *
	 * @og.tag
	 * LDAPを検索する場合、"担当者名"&lt;メールアドレス&gt;形式のメールアドレスを作成する
	 * 場合、検索する属性値を指定します。
	 * ひとつならアドレス。２つなら名前とアドレスの順で指定されたと認識します。
	 *
	 * @og.rev 3.7.1.0 (2005/04/15) LDAP検索 新規追加
	 *
	 * @param   ldapVals LDAP検索時の属性名
	 */
	public void setLdapVals( final String ldapVals ) {
		this.ldapVals = nval( getRequestParameter( ldapVals ),this.ldapVals );
	}

	/**
	 * 【TAG】メールアドレスをGE35を利用して取得するかどうか[true/false]を指定します(初期値:false)。
	 *
	 * @og.tag
	 * GE35からメールアドレスを取得する場合は、true をセットします。false の場合は、
	 * from,to,cc,bcc,replyTo の設定値がそのまま使用されます。
	 * 上記アドレスに、&#064; を含む場合は、DB を検索せず、メールアドレスとして
	 * そのまま使用します。DB の検索結果が存在しない場合は、不正なアドレスとして、
	 * エラーとします。
	 * useLDAPと同時に設定されている場合は、LDAP設定が優先されます。
	 * 初期値は、false です。
	 *
	 * @og.rev 5.6.9.3 (2013/10/25) 新規追加
	 *
	 * @param   flag メールアドレスのGE35利用 [true:利用する/false:利用しない]
	 */
	public void setUseDB( final String flag ) {
		useDB = nval( getRequestParameter( flag ),useDB );
	}

	/**
	 * 【TAG】メール送信ポート番号をセットします
	 * 		(初期値:システム定数のSMTP_PORT[={@og.value SystemData#SMTP_PORT}])。
	 *
	 * @og.tag
	 * 初期値は、システム定数のSMTP_PORT を使用します。
	 *
	 * (初期値:システム定数のSMTP_PORT[={@og.value SystemData#SMTP_PORT}])。
	 * 
	 * @og.rev 5.8.1.1 (2014/11/14) メール送信時認証「POP_BEFORE_SMTP」追加
	 * 
	 * @param  port SMTPポート
	 */
	public void setSmtpPort( final String port ) {
		smtpPort = nval( getRequestParameter(port), smtpPort );
	}

	/**
	 * 【TAG】メール送信時認証方式をセットします
	 *		 (初期値:システム定数のMAIL_SEND_AUTH[={@og.value SystemData#MAIL_SEND_AUTH}])。
	 *
	 * @og.tag
	 * 認証を行う場合は「POP_BEFORE_SMTP」または、「SMTP_AUTH」が指定できます。
	 * 認証時には認証ユーザと認証パスワードを設定する必要があります。
	 * 初期値は、システム定数のMAIL_SEND_AUTH を使用します。
	 *
	 * (初期値:システム定数のMAIL_SEND_AUTH[={@og.value SystemData#MAIL_SEND_AUTH}])。
	 * 
	 * @og.rev 5.8.1.1 (2014/11/14) メール送信時認証「POP_BEFORE_SMTP」追加
	 * @og.rev 6.2.4.1 (2015/05/22) SMTP_AUTH 対応。「SMTP_AUTH」追加(コメントのみ修正)
	 * 
	 * @param  type 認証方式
	 */
	public void setAuthType( final String type ) {
		authType = nval( getRequestParameter(type), authType );
	}

	/**
	 * 【TAG】メール送信時認証ポートをセットします
	 * 		(初期値:システム定数のMAIL_SEND_AUTH_PORT[={@og.value SystemData#MAIL_SEND_AUTH_PORT}])。
	 *
	 * @og.tag
	 * 「POP_BEFORE_SMTP」認証を行う場合に、POPサーバーに接続するポート番号を指定します。
	 * 指定しない場合は、POP3デフォルトポートを使用します。
	 * 初期値は、システム定数のMAIL_SEND_AUTH_PORT を使用します。
	 *
	 * (初期値:システム定数のMAIL_SEND_AUTH_PORT[={@og.value SystemData#MAIL_SEND_AUTH_PORT}])。
	 * 
	 * @og.rev 5.8.1.1 (2014/11/14) メール送信時認証「POP_BEFORE_SMTP」追加
	 * 
	 * @param  port 認証ポート
	 */
	public void setAuthPort( final String port ) {
		authPort = nval( getRequestParameter(port), authPort );
	}

	/**
	 * 【TAG】メール送信認証ユーザをセットします
	 *		(初期値:システム定数のMAIL_SEND_AUTH_USER[={@og.value SystemData#MAIL_SEND_AUTH_USER}])。
	 *
	 * @og.tag
	 * 初期値は、システム定数のMAIL_SEND_AUTH_USER を使用します。
	 *
	 * (初期値:システム定数のMAIL_SEND_AUTH_USER[={@og.value SystemData#MAIL_SEND_AUTH_USER}])。
	 * 
	 * @og.rev 5.8.1.1 (2014/11/14) メール送信時認証「POP_BEFORE_SMTP」追加
	 * 
	 * @param  user 認証ユーザ
	 */
	public void setAuthUser( final String user ) {
		authUser = nval( getRequestParameter(user), authUser );
	}

	/**
	 * 【TAG】メール送信認証パスワードをセットします
	 * 		(初期値:システム定数のMAIL_SEND_AUTH_PASSWORD[={@og.value SystemData#MAIL_SEND_AUTH_PASSWORD}])。
	 *
	 * @og.tag
	 * 初期値は、システム定数のMAIL_SEND_AUTH_PASSWORD を使用します。
	 *
	 * (初期値:システム定数のMAIL_SEND_AUTH_PASSWORD[={@og.value SystemData#MAIL_SEND_AUTH_PASSWORD}])。
	 * 
	 * @og.rev 5.8.1.1 (2014/11/14) メール送信時認証「POP_BEFORE_SMTP」追加
	 * 
	 * @param  pass 認証パスワード
	 */
	public void setAuthPass( final String pass ) {
		authPass = nval( getRequestParameter(pass), authPass );
	}

	/**
	 * 【TAG】履歴に残すかどうかをセットします
	 * 		(初期値:システム定数のUSE_MAILSENDER_HISTORY[={@og.value SystemData#USE_MAILSENDER_HISTORY}])。
	 *
	 * @og.tag
	 * 初期値は、システム定数のUSE_MAILSENDER_HISTORY を使用します。
	 * trueを設定した場合、システムID、送信元アドレス、送信先アドレス、タイトル、本文について
	 * GE32,34に履歴として保存されます。
	 *
	 * (初期値:システム定数のUSE_MAILSENDER_HISTORY[={@og.value SystemData#USE_MAILSENDER_HISTORY}])。
	 * 
	 * @og.rev 5.9.2.3 (2015/11/27) 追加
	 * 
	 * @param  flag 履歴に残すかどうか [true:残す/false:残さない]
	 */
	public void setUseHistory( final String flag ) {
		useHistory = nval( getRequestParameter( flag ), useHistory );
	}

	/**
	 * 【TAG】SSL接続するかどうかをセットします
	 * 		(初期値:システム定数のMAIL_SEND_USE_SSL[={@og.value SystemData#MAIL_SEND_USE_SSL}])。
	 *
	 * @og.tag
	 * SSL接続する場合は、true を設定します。
	 * (初期値:システム定数のMAIL_SEND_USE_SSL[={@og.value SystemData#MAIL_SEND_USE_SSL}])。
	 * 
	 * @og.rev 6.3.8.0 (2015/09/11) SSL接続するかどうか
	 * 
	 * @param  isSSL SSL接続するかどうか [true:する/false:しない]
	 */
	public void setUseSSL( final String isSSL ) {
		useSSL = nval( getRequestParameter(isSSL), useSSL );
	}

//	/**
//	 * シリアライズ用のカスタムシリアライズ書き込みメソッド。
//	 *
//	 * @og.rev 4.0.0.0 (2006/09/31) 新規追加
//	 * @serialData 一部のオブジェクトは、シリアライズされません。
//	 *
//	 * @param	strm	ObjectOutputStreamオブジェクト
//	 * @throws IOException	入出力エラーが発生した場合
//	 */
//	private void writeObject( final ObjectOutputStream strm ) throws IOException {
//		strm.defaultWriteObject();
//	}

//	/**
//	 * シリアライズ用のカスタムシリアライズ読み込みメソッド
//	 *
//	 * ここでは、transient 宣言された内部変数の内、初期化が必要なフィールドのみ設定します。
//	 *
//	 * @og.rev 4.0.0.0 (2006/09/31) 新規追加
//	 * @serialData 一部のオブジェクトは、シリアライズされません。
//	 *
//	 * @param	strm	ObjectInputStreamオブジェクト
//	 * @see #release2()
//	 * @throws IOException	シリアライズに関する入出力エラーが発生した場合
//	 * @throws ClassNotFoundException	クラスを見つけることができなかった場合
//	 */
//	private void readObject( final ObjectInputStream strm ) throws IOException , ClassNotFoundException {
//		strm.defaultReadObject();
//	}

	/**
	 * 引数のアドレス配列を社員マスタ（GE35)で変換して返します。
	 * グループIDは利用しません。
	 * 
	 * @og.rev 5.6.9.3 (2013/10/25) 新規追加
	 * 
	 * @param	src	引数配列(可変長引数)
	 *
	 * @return	変換後アドレス配列
	 * @og.rtnNotNull
	 */
	public String[] getAddressArray( final String... src ){
		if( src == null || src.length == 0 ) { return src; }		// 6.1.1.0 (2015/01/17) 可変長引数でもnullは来る。

		String[] rtn= src.clone();

		for( int i=0; i<src.length; i++ ){
			String addr = src[i]; 							// 宛先ID
			final String[] userAddr = getUserAddr( addr );
			if( userAddr != null && userAddr.length > 0 ){
				// 6.4.1.1 (2016/01/16) PMD refactoring. Avoid if (x != y) ..; else ..;
				addr = userAddr[MailPattern.GE35_NAME] == null
							? userAddr[MailPattern.GE35_MAIL]
							: userAddr[MailPattern.GE35_NAME] + "<" + userAddr[MailPattern.GE35_MAIL] + ">";

//				if( userAddr[MailPattern.GE35_NAME] != null ){	// 宛先名
//					addr = userAddr[MailPattern.GE35_NAME] + "<" + userAddr[MailPattern.GE35_MAIL] + ">";
//				}
//				else{
//					addr = userAddr[MailPattern.GE35_MAIL];
//				}
				rtn[i] = addr;
			}
		}

		return rtn;
	}

	/**
	 * 社員マスタより名前、メールアドレスを取得します。
	 * 戻り値 rtn[0]:ユーザー名、 rtn[1]:ユーザーメールアドレス
	 *
	 * @og.rev 5.6.9.3 (2013/10/25) mailSenderでもGE35を扱う。
	 * @og.rev 6.4.1.1 (2016/01/16) selGE35 → SEL_GE35 refactoring
	 *
	 * @param   userId  ユーザーID
	 *
	 * @return	配列文字列(rtn[0]:ユーザー名、 rtn[1]:ユーザーメールアドレス)
	 */
	private String[] getUserAddr( final String userId ){
		String[] rtn = null;

		if( userId.contains( "@" ) ) {
			rtn = new String[2];
			rtn[0] = "";
			rtn[1] = userId;
		}
		else {
			final String[] ge35SelArgs = { userId };
//			final String[][] ge35Datas = DBUtil.dbExecute( MailPattern.selGE35,ge35SelArgs,getApplicationInfo(), DBID );
			final String[][] ge35Datas = DBUtil.dbExecute( MailPattern.SEL_GE35,ge35SelArgs,getApplicationInfo(), DBID );			// 6.4.1.1 (2016/01/16) selGE35 → SEL_GE35 refactoring
			if( ge35Datas.length > 0) {
				rtn = ge35Datas[0];
			}
			else {
				final String errMsg = "ユーザー情報取得できません。ユーザーID:" + userId ;
				throw new HybsSystemException( errMsg );
			}
		}
		return rtn;
	}

	/**
	 * このオブジェクトの文字列表現を返します。
	 * 基本的にデバッグ目的に使用します。
	 * 
	 * @og.rev 5.6.9.3 (2013/10/25) useDBの対応
	 *
	 * @return このクラスの文字列表現
	 * @og.rtnNotNull
	 */
	@Override
	public String toString() {
		return ToString.title( this.getClass().getName() )
				.println( "VERSION"		,VERSION	)
				.println( "host"		,host		)
				.println( "charset"		,charset	)
				.println( "from" 		,from 		)
				.println( "to"			,to			)
				.println( "cc"			,cc			)
				.println( "bcc"			,bcc		)
				.println( "replyTo"		,replyTo	)
				.println( "subject"		,subject	)
				.println( "filename" 	,filename 	)
				.println( "fileURL" 	,fileURL 	)
				.println( "useLDAP"		,useLDAP	)
				.println( "ldapKey"		,ldapKey	)
				.println( "ldapVals"	,ldapVals	)
				.println( "useDB"		,useDB		) // 5.6.9.3 (2013/10/25)
				.println( "useHistory"	,useHistory	) // 5.9.2.3 (2015/11/27)
				.println( "Other..."	,getAttributes().getAttribute() )
				.fixForm().toString() ;
	}
}
