/*********************************************************************
* All Rights reserved,Copyright (c) K-Opticom
**********************************************************************
*＜プログラム内容＞
*   システム名      ：eo顧客基幹システム
*   モジュール名    ：JCCSendMailUtil
*   ソースファイル名：JCCSendMailUtil.java
*   作成者          ：富士通
*   日付            ：2011年05月06日
*＜機能概要＞
*   JavaMailを用いてSMTPによるメールの送信を行う部品です。
*＜修正履歴＞
*   バージョン  修正日       修正者      修正内容
*   v1.00.00    2011/05/01   EK909308    新規作成
*   v1.00.01    2011/08/08   EK909308    ISO-2022-JPとUnicodeの文字コードマッピングの相違を吸収
*   v9.00.00    2014/07/07   FJ          送信メールヘッダ作成時に前回設定値を引き継がせない
*   v18.00.00   2015/10/21   FJ)寺園     ANK-2631-00-00 ワンストップ案件（ＳＴＥＰ１）
*
**********************************************************************/
package eo.common.util;


import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Properties;
import java.util.Set;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.Address;
import javax.mail.BodyPart;
import javax.mail.Header;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.SendFailedException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.internet.MimeUtility;
import javax.mail.util.ByteArrayDataSource;

/**
 * クラス名：メール送信部品
 *
 * 処理概要：JavaMail(1.4)を用いてSMTPによるメールの送信を行う。
 *
 * 前提条件：JavaMail（Javaの標準拡張API）を使用する。
 * 			 クラスパスに"mail.jar"および"activation.jar"を設定すること。
 *
 * 補足事項：sendMailメソッドを呼び出すことでメールを送信する。
 * 			 JavaMailのサービスプロバイダはSunが標準で提供しているクラスを使用する。
 * 
 * @author 富士通
 */
public class JCCSendMailUtil
{
	/** エラーコード一覧 */
	public static final String ERR_NON = "";
	public static final String ERR_101 = "送信元アドレスFROMが未設定です。";
	public static final String ERR_102 = "送信先アドレスTOが未設定です。";
	public static final String ERR_103 = "件名がnullです。";
	public static final String ERR_104 = "本文がnullです。";
	public static final String ERR_105 = "ホスト名が未設定です。";
	public static final String ERR_106 = "ポート番号が未設定です。";
	public static final String ERR_107 = "文字コードが未設定かまたは未サポートです。";
	public static final String ERR_108 = "添付ファイルをファイルオブジェクトとして取得できません。";
	public static final String ERR_UNKNOWN = "メール送信情報の未想定エラー。";
	
	
	/** v1.00.01 SJIS - Unicode変換テーブル */
	private static final char[][] SJIS_TO_UNI = 
	{
		{ 0x2015, 0x2014 },
		{ 0x2225, 0x2016 },
		{ 0xff0d, 0x2212 },
		{ 0xff5e, 0x301c },
		{ 0xffe0, 0x00a2 },
		{ 0xffe1, 0x00a3 },
		{ 0xffe2, 0x00ac }
	};
	
	/**
	 * メールを送信する。
	 *  
	 * @param mapArgs メール送信条件を格納したHashMap。
	 * @return 終了コード。詳細は以下参照。
	 * 
	 *     0 正常
	 *   101 送信元アドレスエラー
	 *   102 送信先アドレスＴＯエラー
	 *   103 件名エラー
	 *   104 本文エラー
	 *   105 サーバーホストエラー
	 *   106 サーバーポートエラー
	 *   107 メール文字コードエラー
	 *   108 ファイルオブジェクト取得エラー
	 * @throws Exception
	 */
	public static Integer sendMail(HashMap<String, Object> mapArgs) throws Exception
	{
		// 例外情報格納用領域
		String sendMessage = "";
		
		// システムプロパティ情報
		Properties props = null;
		// セッションオブジェクト
		Session session = null;
		// メッセージオブジェクト
		MimeMessage mimeMessage = null;
		
		// 入力パラメータをローカル変数に取得
		String strFrom			= (String)mapArgs.get("MLAD_FROM");
		String[] strTo			= (String[])mapArgs.get("MLAD_TO");
		String[] strCC			= (String[])mapArgs.get("MLAD_CC");
		String[] strBCC			= (String[])mapArgs.get("MLAD_BCC");
		String strReplyTo		= (String)mapArgs.get("MLAD_REPLY_TO");
		String strReturnPath	= (String)mapArgs.get("MLAD_RETURN_PATH");
		String strSubject		= (String)mapArgs.get("MAIL_TITLE");
		String strBody			= (String)mapArgs.get("MAIL_TEXT");
		String[] strTmpPath		= (String[])mapArgs.get("TEMP_FILE_PATH");
		String strHost			= (String)mapArgs.get("SMTP_HOST");
		String strPort			= (String)mapArgs.get("SMTP_PORT");
		String strCode			= (String)mapArgs.get("MAIL_MOJI_CD");
// ANK-2631-00-00 ADD START
		String mailSendStatFlg	= (String)mapArgs.get("MAIL_SEND_STAT_FLG");
// ANK-2631-00-00 ADD END
		HashMap<String, String> mapHeadIf	= new HashMap<String, String>();
		mapHeadIf = (HashMap)mapArgs.get("MAIL_HEADER_IF");
		HashMap<String, Object> mapAdrName	= new HashMap<String, Object>();
		mapAdrName = (HashMap)mapArgs.get("MLAD_NM");
		
		// 2012/02/03 添付ファイル名の重複を許容する対応 start
		//HashMap<String, Object> mapTempFileIf	= new HashMap<String, Object>();
		//mapTempFileIf = (HashMap)mapArgs.get("TEMP_FILE_IF");
		ArrayList<HashMap<String, Object>> eFileArray = new ArrayList<HashMap<String, Object>>();
		eFileArray = (ArrayList<HashMap<String, Object>>)mapArgs.get("TEMP_FILE_IF");
		// 2012/02/03 添付ファイル名の重複を許容する対応 end
		
		//--------------------------------------------------------------
		// 入力パラメータ検査
		//--------------------------------------------------------------
// ANK-2631-00-00 ADD START
		// メール送信ステータスフラグが"1"（完了）の場合は正常終了とする
		if(mailSendStatFlg != null && "1".equals(mailSendStatFlg))
		{
		// 正常終了
		return new Integer(0);
		}
// ANK-2631-00-00 ADD END
		
		// 送信元アドレスFROM検査
		strFrom = trimMailAddress(strFrom, true, true);
		if(strFrom == null || "".equals(strFrom)) 
		{
			return new Integer(101);
		}
		// 送信者名は改行の除去のみ行う(nullでもエラーにしない)
		String strFromName = null;
		if(mapAdrName != null)
		{
			if(mapAdrName.containsKey("MLAD_FROM_NM") == true)
			{
				HashMap<String, String> mapFromName = (HashMap<String, String>)mapAdrName.get("MLAD_FROM_NM");
				if(mapFromName.containsKey(strFrom) == true)
				{
					strFromName = mapFromName.get(strFrom);
					strFromName = JCCCheckMailHeaderUtil.checkMailHeader(strFromName);
				}
			}
		}
		// 送信先アドレスTO検査(空文と改行をトリミング)
		strTo = trimMailAddress(strTo, true, true);
		if(strTo == null || strTo.length == 0) 
		{
			// 送信先アドレスTOエラー
			return new Integer(102);
		}
		
		// CC,BCCは空文と改行のトリミングを行う(nullでもエラーにしない)
		strCC = trimMailAddress(strCC, true, true);
		strBCC = trimMailAddress(strBCC, true, true);
		
		// ReplyTo
		strReplyTo = trimMailAddress(strReplyTo, true, true);
		
		// 2012/03/01 エラーメール返信先の任意指定に対応 start
		if(null != mapHeadIf)
		{
			String tmpReturnPath = mapHeadIf.get("Return-Path");
			if(null != tmpReturnPath && !"".equals(tmpReturnPath))
			{
				strReturnPath = tmpReturnPath;
			}
		}
		// 2012/03/01 エラーメール返信先の任意指定に対応 end
		//ReturnPath
		strReturnPath = trimMailAddress(strReturnPath, true, true);
		
		// 件名検査(改行を除去)
		strSubject = JCCCheckMailHeaderUtil.checkMailHeader(strSubject);
		if(strSubject == null)
		{
			return new Integer(103);
		}
		
		// 本文検査(改行除去はしない)
		if(strBody == null)
		{
			return new Integer(104);
		}
		
		// ホスト名検査(改行除去はしない)
		if(strHost == null || "".equals(strHost))
		{
			return new Integer(105);
		}
		
		// ポート名検査(改行除去はしない)
		if(strPort == null || "".equals(strPort))
		{
			return new Integer(106);
		}
		
		// メール文字コード検査(改行除去はしない)
		if(strCode == null || "".equals(strCode))
		{
			return new Integer(107);
		}
		
		// 電子ファイルパス検査(読取可否検査)
		File fl = null;
		strTmpPath = trimMailAddress(strTmpPath, false, false);
		if(strTmpPath != null)
		{
			for(int i = 0; i < strTmpPath.length; i++)
			{
				fl = new File(strTmpPath[i]);
				if(fl.exists() == false || fl.isFile() == false || fl.canRead() == false)
				{
					return new Integer(108);
				}
			}
		}
		
		//--------------------------------------------------------------
		// メールメッセージオブジェクト作成
		//--------------------------------------------------------------
		try
		{
			// システムプロパティ情報の取得
			props = new Properties();
			// SMTPサーバーのアドレスを指定(ホスト名)
			props.put("mail.smtp.host", strHost);
			// ポート番号を指定
			props.put("mail.smtp.port", strPort);
			// RETURN-PATHの設定
			if(strReturnPath != null && !"".equals(strReturnPath))
			{
				props.put("mail.smtp.from", strReturnPath);
			}
			// セッションオブジェクトの生成
			session = Session.getInstance(props);
			// メッセージオブジェクトの生成
			mimeMessage = new MimeMessage(session);
			
			// 送信元の指定
			if(strFromName == null || "".equals(strFromName))
			{
				// 送信者名指定無しの場合
				mimeMessage.setFrom(new InternetAddress(strFrom));
			}
			else
			{
				// v1.00.01 ISO-2022-JPとUnicodeの文字コードマッピングの相違を吸収
				strFromName = toUnicode(strFromName, strCode);
				
				// 送信者名指定有りの場合
				mimeMessage.setFrom(new InternetAddress(strFrom, strFromName, strCode));
			}
			
			// 送信先(TO)の指定
			InternetAddress[] to = new InternetAddress[strTo.length];
			String strAddName = null;
			for(int i = 0; i < strTo.length; i++)
			{
				// トリミングの結果strToがnullになっている場合を考慮
				if(strTo[i] == null)
				{
					break;
				}
				// 送信先アドレスTOに紐付く送信者氏名の取得
				strAddName = null;
				if(mapAdrName != null)
				{
					if(mapAdrName.containsKey("MLAD_TO_NM") == true)
					{
						HashMap<String, String> mapToName = (HashMap<String, String>)mapAdrName.get("MLAD_TO_NM");
						if(mapToName.containsKey(strTo[i]) == true)
						{
							strAddName = mapToName.get(strTo[i]);
							strAddName = JCCCheckMailHeaderUtil.checkMailHeader(strAddName);
						}
					}
				}
				if(strAddName == null || "".equals(strAddName))
				{
					// 送信先氏名指定無しの場合
					to[i] = new InternetAddress(strTo[i]);
				}
				else
				{
					// v1.00.01 ISO-2022-JPとUnicodeの文字コードマッピングの相違を吸収
					strAddName = toUnicode(strAddName, strCode);
					
					// 送信先氏名指定有りの場合
					to[i] = new InternetAddress(strTo[i], strAddName, strCode);
				}
			}
			mimeMessage.setRecipients(Message.RecipientType.TO, to);
			
			// 送信先(CC)の指定
			if(strCC != null)
			{
				InternetAddress[] cc = new InternetAddress[strCC.length];
				for(int i = 0; i < strCC.length; i++) 
				{
					// トリミングの結果strCCがnullになっている場合を考慮
					if(strCC[i] == null)
					{
						break;
					}
					// 送信先アドレスCCに紐付く送信者氏名の取得
					strAddName = null;
					if(mapAdrName != null)
					{
						if(mapAdrName.containsKey("MLAD_CC_NM") == true)
						{
							HashMap<String, String> mapCcName = (HashMap<String, String>)mapAdrName.get("MLAD_CC_NM");
							if(mapCcName.containsKey(strCC[i]) == true)
							{
								strAddName = mapCcName.get(strCC[i]);
								strAddName = JCCCheckMailHeaderUtil.checkMailHeader(strAddName);
							}
						}
					}
					if(strAddName == null || "".equals(strAddName))
					{
						// 送信先氏名指定無しの場合
						cc[i] = new InternetAddress(strCC[i]);
					}
					else
					{
						// v1.00.01 ISO-2022-JPとUnicodeの文字コードマッピングの相違を吸収
						strAddName = toUnicode(strAddName, strCode);
						
						// 送信先氏名指定有りの場合
						cc[i] = new InternetAddress(strCC[i], strAddName, strCode);
					}					
				}
				mimeMessage.setRecipients(Message.RecipientType.CC, cc);
			}
			
			// 送信先(BCC)の指定
			if(strBCC != null)
			{
				InternetAddress[] bcc = new InternetAddress[strBCC.length];
				for(int i = 0; i < strBCC.length; i++) 
				{
					// トリミングの結果strBCCがnullになっている場合を考慮
					if(strBCC[i] == null)
					{
						break;
					}
					// 送信先アドレスBCCに紐付く送信者氏名の取得
					strAddName = null;
					if(mapAdrName != null)
					{
						if(mapAdrName.containsKey("MLAD_BCC_NM") == true)
						{
							HashMap<String, String> mapBccName = (HashMap<String, String>)mapAdrName.get("MLAD_BCC_NM");
							if(mapBccName.containsKey(strBCC[i]) == true)
							{
								strAddName = mapBccName.get(strBCC[i]);
								strAddName = JCCCheckMailHeaderUtil.checkMailHeader(strAddName);
							}
						}
					}
					if(strAddName == null || "".equals(strAddName))
					{
						// 送信先氏名指定無しの場合
						bcc[i] = new InternetAddress(strBCC[i]);
					}
					else
					{
						// v1.00.01 ISO-2022-JPとUnicodeの文字コードマッピングの相違を吸収
						strAddName = toUnicode(strAddName, strCode);
						
						// 送信先氏名指定有りの場合
						bcc[i] = new InternetAddress(strBCC[i], strAddName, strCode);
					}					
				}
				mimeMessage.setRecipients(Message.RecipientType.BCC, bcc);
			}
			
			// 送信先(ReplyTo)の指定
			if(strReplyTo != null && !"".equals(strReplyTo)) 
			{
				// ReplyTo紐付く送信者氏名の取得
				strAddName = null;
				if(mapAdrName != null)
				{
					if(mapAdrName.containsKey("MLAD_REPLY_NM") == true)
					{
						HashMap<String, String> mapReplyName = (HashMap<String, String>)mapAdrName.get("MLAD_REPLY_NM");
						if(mapReplyName.containsKey(strReplyTo) == true)
						{
							strAddName = mapReplyName.get(strReplyTo);
							strAddName = JCCCheckMailHeaderUtil.checkMailHeader(strAddName);
						}
					}
				}
				InternetAddress[] reply = new InternetAddress[1];
				if(strAddName == null || "".equals(strAddName))
				{
					// 送信先氏名指定無しの場合
					reply[0] = new InternetAddress(strReplyTo);
				}
				else
				{
					// v1.00.01 ISO-2022-JPとUnicodeの文字コードマッピングの相違を吸収
					strAddName = toUnicode(strAddName, strCode);
					
					// 送信先氏名指定有りの場合
					reply[0] = new InternetAddress(strReplyTo, strAddName, strCode);
				}
				mimeMessage.setReplyTo(reply);
			}
			
			// 件名の指定
			// v1.00.01 ISO-2022-JPとUnicodeの文字コードマッピングの相違を吸収
			strSubject = toUnicode(strSubject, strCode);
			
			mimeMessage.setSubject(strSubject, strCode);
			
			// JavaMailで本文の最後に?やw)w)が入ってしまう対応(ISO-2022-JPのバグ)
			StringBuffer sbBody = new StringBuffer(strBody);
			sbBody.append(" ");
			
			// 送信日時の指定
			mimeMessage.setSentDate(new Date());
			
			// その他の任意のヘッダーの指定
			if(mapHeadIf != null)
			{
				// 存在する全てのキーに紐づいたヘッダ情報をセット
				Set keySet = mapHeadIf.keySet();
				Iterator keyIte = keySet.iterator();
				while(keyIte.hasNext())
				{
					// ヘッダ情報の取得
					String key = (String)keyIte.next();
					String head = (String)mapHeadIf.get(key);
					// 改行コードの除去
					key = JCCCheckMailHeaderUtil.checkMailHeader(key);
					head = JCCCheckMailHeaderUtil.checkMailHeader(head);
					
					// v1.00.01 ISO-2022-JPとUnicodeの文字コードマッピングの相違を吸収
					head = toUnicode(head, strCode);

					// ヘッダ情報をセット
					mimeMessage.setHeader(key, MimeUtility.encodeWord(head, strCode, "B"));
				}
			}
			// MultiPartオブジェクトの実体化
			Multipart mPart = new MimeMultipart();
			
			// 本文の指定
			MimeBodyPart mbText = new MimeBodyPart();

			// v1.00.01 ISO-2022-JPとUnicodeの文字コードマッピングの相違を吸収
			//mbText.setText(sbBody.toString(), strCode);
			mbText.setText(toUnicode(sbBody.toString(), strCode), strCode);
			mPart.addBodyPart(mbText);
			
			// 添付ファイル(パス指定時)
			if(strTmpPath != null)
			{
				// 指定されたファイルパスの数分セット
				MimeBodyPart mbFile = null;
				FileDataSource fds = null;
				for(int i = 0; i < strTmpPath.length; i++)
				{
					mbFile = new MimeBodyPart();
					fds = new FileDataSource(strTmpPath[i]);
					mbFile.setDataHandler(new DataHandler(fds));
					mbFile.setFileName(MimeUtility.encodeWord(fds.getName()));
					mPart.addBodyPart(mbFile);
				}
			}
			// 添付ファイル(ファイル名とbyte配列をセットにしている場合)
			if(eFileArray != null)
			{
				// 2012/02/03 添付ファイル名の重複を許容する対応 start
				for(int ArrayCnt = 0; ArrayCnt < eFileArray.size(); ArrayCnt++)
				{
					MimeBodyPart mbFile = null;
					ByteArrayDataSource bds = null;
					// 存在する全てのキーに紐づいた添付ファイル情報をセット
					HashMap mapTempFileIf = eFileArray.get(ArrayCnt);
					Set keySet = mapTempFileIf.keySet();
					Iterator keyIte = keySet.iterator();
					while(keyIte.hasNext())
					{
						// ヘッダ情報の取得
						String fileName = (String)keyIte.next();
						byte[] file = (byte[])mapTempFileIf.get(fileName);
						mbFile = new MimeBodyPart();
						bds = new ByteArrayDataSource(file, "application/octet-stream");
						mbFile.setDataHandler(new DataHandler(bds));
						mbFile.setFileName(MimeUtility.encodeWord(fileName));
						mPart.addBodyPart(mbFile);
					}
				}
				// 2012/02/03 添付ファイル名の重複を許容する対応 end
			}
			
			
			// 本文と添付ファイルをメッセージオブジェクトにセット
			mimeMessage.setContent(mPart);
			
			// メールの送信
			Transport.send(mimeMessage);
		}
		catch(SendFailedException se)
		{
			// 送信情報を例外文字列に付加
			sendMessage = se.getMessage() + outputSendMailInfo(props, mimeMessage);
			throw new SendFailedException(sendMessage);
		}
		catch(MessagingException me)
		{
			// 送信情報を例外文字列に付加
			sendMessage = me.getMessage() + outputSendMailInfo(props, mimeMessage);
			throw new MessagingException(sendMessage);
		}
		catch(Exception e)
		{
			String msg = null;
			String chk = "UnsupportedEncodingException";
			msg = e.toString();
			if(msg.indexOf(chk) >= 0)
			{
				return new Integer(107);
			}
			else
			{
				throw e;
			}
		}
		// 正常終了
		return new Integer(0);
	}

	/**
	 * メール送信パラメータエラーメッセージの取得メソッド
	 * @param Integer errNum エラー番号
	 * @return エラーメッセージ
	 */
	public static String getSendParamErrMsg(Integer errNum)
	{
		String retStr = ERR_NON;
		switch(errNum)
		{
			// メール送信成功
			case 0:
				retStr = ERR_NON;
				break;
			case 101:
				retStr = ERR_101;
				break;
			case 102:
				retStr = ERR_102;
				break;
			case 103:
				retStr = ERR_103;
				break;
			case 104:
				retStr = ERR_104;
				break;
			case 105:
				retStr = ERR_105;
				break;
			case 106:
				retStr = ERR_106;
				break;
			case 107:
				retStr = ERR_107;
				break;
			case 108:
				retStr = ERR_108;
				break;
			default:
				retStr = ERR_UNKNOWN;
				break;
		}
		return retStr;
	}
	
	/**
	 * 空白、空文配列、及び改行の除去メソッド
	 * @param String[] chkStr 検査をかける文字列の配列
	 * @param boolean chkCRLF 改行除去の有無(true指定で除去する)
	 * @param boolean chkSpac 空白除去の有無(true指定で除去する)
	 * @return String[] チェック後の文字列配列
	 */
	private static String[] trimMailAddress(String[] chkStr, boolean chkCRLF, boolean chkSpace)
	{
		int set = 0;
		
		// 入力パラメータがnullの場合はそのままnull復帰
		if(chkStr == null)
		{
			return null;
		}
		if(chkStr.length == 0)
		{
			return null;
		}
		String[] tmpStr = new String[chkStr.length];
		// 指定された配列の数だけループ
		for(int i = 0; i < chkStr.length; i++)
		{
			// 空文及びnull配列は除去する
			if(chkStr[i] != null && "".equals(chkStr[i]) == false)
			{
				System.arraycopy((String[])chkStr, i, (String[])tmpStr, set, 1);
				// 改行除去指定の場合は改行も除去する
				if(chkCRLF == true)
				{
					tmpStr[set] = JCCCheckMailHeaderUtil.checkMailHeader(tmpStr[set]);
				}
				// 空白除去指定の場合は空白も除去する
				if(chkSpace == true)
				{
					tmpStr[set] = tmpStr[set].replace(" ", "");
				}

				set++;
			}
		}
		if(tmpStr[0] == null)
		{
			return null;
		}
		// String配列の個数を調整(呼び元が.lengthメソッドでループカウンタに使用するため)
		String[] resultStr = new String[set];
		for(int i = 0; i < set; i++)
		{
			System.arraycopy(tmpStr, i, resultStr, i, 1);
		}
		return resultStr;
	}
	
	/**
	 * 空白、空文、改行の除去メソッド
	 * @param String chkStr 検査をかける文字列の配列
	 * @param boolean chkCRLF 改行除去の有無(true指定で除去する)
	 * @param boolean chkSpac 空白除去の有無(true指定で除去する)
	 * @return String チェック後の文字列配列
	 */
	private static String trimMailAddress(String chkStr, boolean chkCRLF, boolean chkSpace)
	{
		// 入力パラメータがnullの場合はそのままnull復帰
		if(chkStr == null)
		{
			return null;
		}
		String resultStr = chkStr;
		// 改行の除去
		if(chkCRLF == true)
		{
			resultStr = JCCCheckMailHeaderUtil.checkMailHeader(resultStr);
		}
		// 空白の除去
		if(chkSpace == true)
		{
			resultStr = resultStr.replace(" ", "");
		}
		return resultStr;
	}
	
	/**
	 * ISO-2022-JPで指定された文字のうち、Unicodeとのマッピング相違のある
	 * 文字コードをUnicodeに変換します。
	 * <br>
	 * @param arg0 Unicodeに変換したい文字列
	 * @param arg1 文字コード
	 * @return Unicodeに変換された文字列
	 */
	private static String toUnicode(String arg0, String arg1)
	{
		// null指定または空文字の場合はそのまま復帰
		if (null == arg0 || "".equals(arg0))
		{
			return arg0;
		}
		
		// 文字コードがISO-2022-JPの指定でない場合はそのまま復帰
		String strUp = arg1.toUpperCase();
		if("ISO-2022-JP".equals(strUp) == false)
		{
			return arg0;
		}
		char[] chars = arg0.toCharArray();

		for (int i = 0; i < chars.length; i++)
		{
			chars[i] = transUnicode(chars[i], SJIS_TO_UNI);
		}

		return new String(chars);
	}
	
	/**
	 * 指定された変換定義に従ってUnicodeの強制変換を行います。
	 * <br>
	 * @param c Unicode変換する文字
	 * @param convList Unicode変換定義
	 * @return Unicode変換された文字
	 */
	private static char transUnicode(char c, char[][] convList)
	{
		for (int i = 0; i < convList.length; i++)
		{
			char[] chars = convList[i];

			if (chars[0] == c)
			{
				return chars[1];
			}
		}

		return c;
	}
	
	/**
	 * メール送信情報を文字列で取得する
	 *  
	 * @param props
	 * @param mimeMessage
	 * @return 送信情報
	 * @throws Exception
	 */
	private static String outputSendMailInfo(Properties props, MimeMessage mimeMessage) throws Exception
	{
		// 結果格納用領域
		String crlf = System.getProperty("line.separator");
		String resultStr = crlf + "【メール送信情報】" + crlf;
		
		// ホスト名
		String rcvHost = (String)props.get("mail.smtp.host");
		resultStr = resultStr + "Host:<" + rcvHost + ">" + crlf;
		// ポート名
		String rcvPort = (String)props.get("mail.smtp.port");
		resultStr = resultStr + "Port:<" + rcvPort + ">" + crlf;
		// ReturnPath
		String rcvReturnAdr = (String)props.get("mail.smtp.from");
		resultStr = resultStr + "ReturnPath:<" + rcvReturnAdr + ">" + crlf + crlf;
		// ヘッダー
		Enumeration<Header> rcvAllHead = mimeMessage.getAllHeaders();
		Header rcvHead = null;
		String rcvHeadKey = null;
		String rcvHeadValue = null;
		boolean set = false;
		while(rcvAllHead.hasMoreElements())
		{
			rcvHead = rcvAllHead.nextElement();
			rcvHeadKey = rcvHead.getName();
			set = false;
			// 送信時刻
			if("Date".equals(rcvHeadKey))
			{
				String rcvSentTime = mimeMessage.getSentDate().toString();
				resultStr = resultStr + "Date:" + rcvSentTime + crlf;
			}
			// From
			else if("From".equals(rcvHeadKey))
			{
				// FROM
				Address[] rcvFromAdr = mimeMessage.getFrom();
				String rcvFrom = MimeUtility.decodeText(rcvFromAdr[0].toString());
				resultStr = resultStr + "From:" + rcvFrom + crlf;
			}
			// Reply-To
			else if("Reply-To".equals(rcvHeadKey))
			{
				Address[] rcvReplyAdr = mimeMessage.getReplyTo();
				String rcvReply = MimeUtility.decodeText(rcvReplyAdr[0].toString());
				resultStr = resultStr + "Reply-To:" + rcvReply + crlf;
			}
			// To
			else if("To".equals(rcvHeadKey))
			{
				Address[] rcvToAdr = mimeMessage.getRecipients(Message.RecipientType.TO);
				String[] rcvTo = new String[rcvToAdr.length];
				resultStr = resultStr + "To:";
				for(int i = 0; i < rcvTo.length; i++)
				{
					if(set == false)
					{
						set = true;
					}
					else
					{
						resultStr = resultStr + "; ";
					}
					rcvTo[i] = MimeUtility.decodeText(rcvToAdr[i].toString());
					resultStr = resultStr + rcvTo[i];
				}
				resultStr = resultStr + crlf;
			}
			// Cc
			else if("Cc".equals(rcvHeadKey))
			{
				Address[] rcvCcAdr = mimeMessage.getRecipients(Message.RecipientType.CC);
				String[] rcvCc = new String[rcvCcAdr.length];
				resultStr = resultStr + "Cc:";
				for(int i = 0; i < rcvCc.length; i++)
				{
					if(set == false)
					{
						set = true;
					}
					else
					{
						resultStr = resultStr + "; ";
					}
					rcvCc[i] = MimeUtility.decodeText(rcvCcAdr[i].toString());
					resultStr = resultStr + rcvCc[i];
				}
				resultStr = resultStr + crlf;
			}
			// Bcc
			else if("Bcc".equals(rcvHeadKey))
			{
				Address[] rcvBccAdr = mimeMessage.getRecipients(Message.RecipientType.BCC);
				String[] rcvBcc = new String[rcvBccAdr.length];
				resultStr = resultStr + "Bcc:";
				for(int i = 0; i < rcvBcc.length; i++)
				{
					if(set == false)
					{
						set = true;
					}
					else
					{
						resultStr = resultStr + "; ";
					}
					rcvBcc[i] = MimeUtility.decodeText(rcvBccAdr[i].toString());
					resultStr = resultStr + rcvBcc[i];
				}
				resultStr = resultStr + crlf;
			}
			// Subjectはループの外で付加
			else if("Subject".equals(rcvHeadKey))
			{
				;
			}
			// その他のヘッダー
			else
			{
				rcvHeadValue = rcvHead.getValue();
				resultStr = resultStr + rcvHeadKey + ":" + rcvHeadValue + crlf;
			}
		}
		// 件名
		String rcvTitle = mimeMessage.getSubject();
		resultStr = resultStr + crlf +  "Subject:" + rcvTitle + crlf + crlf;

		// 本文&添付ファイル
		Multipart rcvMp = null;
		try
		{
			rcvMp = (Multipart)mimeMessage.getContent();
		}
		catch(Exception e)
		{
			rcvMp = null;
		}
		if(rcvMp != null)
		{
			int cnt = rcvMp.getCount();
			BodyPart[] rcvBody = new MimeBodyPart[cnt];
			String rcvText = null;
			String rcvFile = null;
			for(int i = 0; i < cnt; i++)
			{
				rcvBody[i] = rcvMp.getBodyPart(i);
				if(rcvBody[i].getContent() instanceof String)
				{
					rcvText = (String)rcvBody[i].getContent();
					resultStr = resultStr + rcvText + crlf + crlf;
				}
				if(rcvBody[i].getDataHandler().getDataSource().getName() != null)
				{
					rcvFile = rcvBody[i].getDataHandler().getDataSource().getName();
					if(set == false)
					{
						resultStr = resultStr + "[attach File Name]" + crlf;
						set = true;
					}
					resultStr = resultStr + rcvFile + crlf;
				}
			}
		}
		return resultStr;
	}
}
