/*********************************************************************
* All Rights reserved,Copyright (c) K-Opticom
**********************************************************************
*＜プログラム内容＞
*   システム名      ：eo顧客基幹システム
*	モジュール名		：JCCReceiveMailUtil
*	ソースファイル名	：JCCReceiveMailUtil.java
*	作成者				：富士通　
*	作成日				：2011年06月13日
*＜機能概要＞
*　メール受信部品です。
*＜修正履歴＞
*	バージョン	修正日		修正者		修正内容
*	v1.00.00	2011/06/13   富士通		新規作成
*   v5.00.00    2013/11/05   FJ         【OM-2013-0004003】
*   v5.00.01    2013/11/11   FJ         メール取得件数上限設定
*   v5.00.02    2013/12/04   FJ         【OM-2013-0003348】
*   v5.00.03    2013/12/18   FJ         添付メール受信修正
*   v13.00.00   2015/04/30   FJ)岡田    【OM-2015-0000837】添付ファイル名の取得、ファイル名取得NGの場合はスキップ
*   v60.00.00   2022/09/06   FJ)原      【OM-2022-0000540】画像ありメール受信時、メール本文が一部欠損
*********************************************************************/
package eo.common.util;

import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Properties;

import javax.mail.Address;
import javax.mail.AuthenticationFailedException;
import javax.mail.Folder;
import javax.mail.FolderNotFoundException;
import javax.mail.Header;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.NoSuchProviderException;
import javax.mail.Part;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeUtility;

import com.fujitsu.futurity.model.common.JCMAPLConstMgr;

/**
 * <B>クラス名： </B>メール受信部品<BR>
 * 
 * <B>処理概要： </B><BR>
 * JavaMail(1.4)を用いてPOP3によるメールの受信を行う。<BR>
 * メールサーバに格納されている未読メールを一括受信する。<BR>
 * 添付ファイル対応。<BR>
 * 
 * <B>前提条件： </B><BR>
 * JavaMail（Javaの標準拡張API）を使用する。<BR>
 * クラスパスに"mail.jar"および"activation.jar"を設定すること。<BR>
 * MIME形式のメールのみ対応する。<BR>
 * MIME標準に準拠しないメールは正しくメールを取得できない可能性があるので注意すること。<BR>
 * 
 * <B>補足事項： </B><BR>
 * JavaMailのサービスプロバイダはSunが標準で提供しているクラスを使用する。<BR>
 * 
 * @author 富士通
 */
public class JCCReceiveMailUtil
{
	
	/** メールストア。未接続の場合はnull。 */
	private Store store = null;
	/** メールフォルダ。未接続の場合はnull。*/
	private Folder folder = null;
	
	/**
	 * <B>メソッド名： </B>メール受信<BR>
	 * 
	 * <B>処理概要： </B><BR>
	 * 引数で指定されたサーバに接続し、格納されている全てのメールを受信する。<BR>
	 * 既にサーバと接続中であった場合は、例外を投げてエラーとする。<BR>
	 * このメソッドの呼び出し後もサーバとの接続は維持される。<BR>
	 * 処理終了時は必ずcommitまたはrollbackを呼び出して切断すること。<BR>
	 * 削除フラグを設定したメールの削除は、サーバ切断時(commit呼び出し時)に行われる。<BR>
	 * 
	 * @param param メール受信条件。HashMapに以下のキーで値を設定する。
	 *   "MAIL_PROTOCOL"      メール受信プロトコル。"pop3"のみ対応。null時は"pop3"。
	 *   "SERVER_HOST"   メールサーバのホスト名またはIPアドレス。必須。
	 *   "SERVER_PORT"   メールサーバのポート番号。必須。
	 *   "MAIL_ACCOUNT"  メールサーバの認証アカウント。必須。
	 *   "MAIL_PASSWORD"      メールサーバの認証パスワード。必須。
	 *   "MAIL_FOLDER"        メールサーバの受信フォルダ。null時は"INBOX"。
	 *   "DIR_TEMP_FILE_TMP"  添付ファイルを格納するディレクトリパス
	 * @return メール受信結果。HashMapに以下のキーで値を格納して返す。
	 *   "RETURN_CD"        終了コード(Integer)。以下の値を返す。
	 *     0  :正常
	 *     101：プロトコル指定エラー
	 *     102：サーバホスト指定エラー
	 *     103：サーバポート指定エラー
	 *     104：アカウント指定エラー
	 *     105：パスワード指定エラー
	 *     106：添付ファイル格納先ディレクトリ指定エラー
	 *     201：コネクション時接続エラー
	 *     202：メールボックスのフォルダ取得時エラー
	 *     203：メッセージ取得時エラー
	 *   "ERR_INFO"          メール受信時にエラーが発生した場合のエラー情報
	 *   "RECEIVE_MAIL"        受信メール一覧を格納したArrayList。ArrayListの要素はメール単位のHashMap。各HashMapの内容は以下。
	 *     "MLAD_FROM"         送信元メールアドレス(String[])。存在しない場合null。
	 *     "MLAD_FROM_DSP_NM"  送信元メールアドレス表示名(String[])。存在しない場合null。
	 *     "MLAD_TO"           送信先メールアドレス(String[])。存在しない場合null。
	 *     "MLAD_TO_DSP_NM"    送信先メールアドレス表示名(String[])。存在しない場合null。
	 *     "MLAD_CC"           CCメールアドレス(String[])。存在しない場合null。
	 *     "MLAD_CC_DSP_NM"    CCメールアドレス表示名(String[])。存在しない場合null。
	 *     "MLAD_BCC"          BCCメールアドレス(String[])。存在しない場合null。
	 *     "MLAD_BCC_DSP_NM"   BCCメールアドレス表示名(String[])。存在しない場合null。
	 *     "DATE"              ヘッダ情報に設定されている日付（Date）。
	 *     "MAIL_HEADER"       全てのヘッダを格納したHashMap。ヘッダ名をキーとして値を格納。
	 *     "MAIL_TITLE"        件名(String)。存在しない場合null。
	 *     "MAIL_TEXT"         本文(String)。
	 *     "TEMP_FILE"         受信した添付ファイルのファイル名と絶対ファイルパスを格納（HashMap<String, String>）
	 *                         (ファイル名は重複する場合があるため、受信した順番に「連番 + "_"」を付与する。
	 *     "MAIL_SIZE"         メールのサイズ（byte）
	 *     "MESSAGE_ID"        メッセージID
	 * @throws FolderNotFoundException  対象フォルダ不明。
	 * @throws NoSuchProviderException  プロバイダ取得失敗。プロトコル指定やクラスパス指定の誤りなど。
	 * @throws AuthenticationFailedException  認証失敗。
	 * @throws MessagingException  その他の例外。接続操作、フォルダ操作、メール操作の失敗。
	 */
	public HashMap<String, Object> receiveMail(HashMap<String, Object> param)
	{
		// 入力パラメータから受信条件を取得
		String mailProtocol    = (String)param.get("MAIL_PROTOCOL");
		String serverHost      = (String)param.get("SERVER_HOST");
		String serverPort      = (String)param.get("SERVER_PORT");
		String mailAccount     = (String)param.get("MAIL_ACCOUNT");
		String mailPassword    = (String)param.get("MAIL_PASSWORD");
		String mailFolder      = (String)param.get("MAIL_FOLDER");
		String tempFileDirPath = (String)param.get("DIR_TEMP_FILE_TMP");// 添付ファイル格納先ディレクトリ
		
		// 結果返却用 HashMap
		HashMap<String, Object> ret = new HashMap<String, Object>();
		
		// エラーリスト
		ArrayList<String> errList = new ArrayList<String>();
		ArrayList<Exception> exceptionList = new ArrayList<Exception>();
		
		// 復帰値
		int iErrFlg = 0;
		
		// 入力パラメータの検査
		if(mailProtocol != null && !"pop3".equalsIgnoreCase(mailProtocol))
		{ // 現在nullまたは"pop3"のみ許可
			iErrFlg = 101;
		}
		else if(serverHost == null || "".equals(serverHost))
		{
			iErrFlg = 102;
		}
		else if(serverPort == null || "".equals(serverPort))
		{
			iErrFlg = 103;
		}
		else if(mailAccount == null || "".equals(mailAccount))
		{
			iErrFlg = 104;
		}
		else if(mailPassword == null || "".equals(mailPassword))
		{
			iErrFlg = 105;
		}
		else if(tempFileDirPath == null || "".equals(tempFileDirPath))
		{
			iErrFlg = 106;
		}
		else
		{
			// メール受信の実行
			try
			{
				ArrayList<Object> mailStore = new ArrayList<Object>();
				
				// 2013/11/11 v5.00.01 メール読み込み最大件数取得
				int maxLength = Integer.parseInt(JCMAPLConstMgr.getString("CC_MAX_RECEIVE_MAIL"));
				
				if(store != null)
				{
					// サーバと接続中の場合
					throw new JCCFrameworkException("JCCReceiveMailUtil：既にメールサーバと接続中");
				}
				// サーバと未接続の場合
				Session session = Session.getInstance(new Properties(), null);
				if(mailProtocol == null)
				{
					// プロトコルがnullだった場合は"pop3"
					mailProtocol = "pop3";
				}
				
				// メールストアオブジェクトの接続
				store = session.getStore(mailProtocol);
				store.connect(serverHost, Integer.parseInt(serverPort), mailAccount, mailPassword); //ここでエラーとなった場合は、「201」を返す
				try
				{
					if(mailFolder == null)
					{
						// フォルダ指定がnullの場合は"INBOX"
						mailFolder = "INBOX";
					}
					// フォルダのオープン（参照・更新モード）
					folder = store.getFolder(mailFolder); // ここでエラーとなった場合は、「202」を返す。
					folder.open(Folder.READ_WRITE);
					try
					{
						// 全メッセージオブジェクトをフォルダから取得
						Message[] messages = folder.getMessages();

						// 2013/12/04 v5.00.02 サーバにある受信メール件数を戻り値に設定
						ret.put("ALL_RECEIVE_MAIL_COUNT", messages.length);

						// 全メール格納先(ArrayList)を作成
						mailStore = new ArrayList<Object>(messages.length); // この中でエラーとなった場合は、「203」を返す。
						// 全メッセージの取得
						for(int i = 0; i < messages.length; i++)
						{
							// 2011/11/28 メッセージ取得中に例外が発生した場合は「203」を設定して取得処理継続 start
							try
							{
								// 全メッセージを取得
								MimeMessage message = (MimeMessage)messages[i];
								// メッセージを取得
								HashMap<String, Object> mail = getMail(message, tempFileDirPath);
								// メッセージを格納
								mailStore.add(mail);
								// 削除フラグを設定
								message.setFlag(javax.mail.Flags.Flag.DELETED, true);

								// 2013/11/11 v5.00.01 読み込み最大件数に達していれば取得処理終了
								if (maxLength <= mailStore.size()) {
									break;
								}
							}
							catch(Exception e)
							{
								// 20130423 203のエラー情報はリストで返却 FST)Yanagihara start
								// メッセージ取得時エラー
								iErrFlg = 203;
								// リストにエラー情報を設定
								errList.add(e.toString() + " ( " + Integer.toString(i + 1) + "件目 / " + messages.length + "件中 )");
								exceptionList.add(e);
								ret.put("ERR_INFO", errList);
								ret.put("ERR_INFO_EXCEPTION", exceptionList);
								// 20130423 203のエラー情報はリストで返却 FST)Yanagihara end
							}
							// 2011/11/28 メッセージ取得中に例外が発生した場合は「203」を設定して取得処理継続 end
						}
					}
					catch(Exception e)
					{
						// 20130423 203のエラー情報はリストで返却 FST)Yanagihara start
						// メッセージ取得時エラー
						iErrFlg = 203;
						// リストにエラー情報を設定
						errList.add(e.toString());
						exceptionList.add(e);
						ret.put("ERR_INFO", errList);
						ret.put("ERR_INFO_EXCEPTION", exceptionList);
						// 20130423 203のエラー情報はリストで返却 FST)Yanagihara end
					}
					// メッセージ情報を設定
					ret.put("RECEIVE_MAIL", mailStore);
				}
				catch(Exception e)
				{
					try
					{
						store.close();
					}
					catch(MessagingException ex)
					{
					} // closeでの例外は無視（根本例外を優先）
					store = null;
					// メールボックスのフォルダ取得時エラー
					iErrFlg = 202;
					ret.put("ERR_INFO", e.toString().replace("\r\n", "").replace("\n", "").replace("\r", ""));
					ret.put("ERR_INFO_EXCEPTION", e);
				}
			}
			catch (Exception e)
			{
				// コネクション時接続エラー
				iErrFlg = 201;
				ret.put("ERR_INFO", e.toString().replace("\r\n", "").replace("\n", "").replace("\r", ""));
				ret.put("ERR_INFO_EXCEPTION", e);
			}
		}
		
		ret.put("RETURN_CD", new Integer(iErrFlg));
		return ret;
	}
	
	/**
	 * <B>メソッド名： </B>メール取得<BR>
	 * 
	 * <B>処理概要： </B><BR>
	 * MimeMessageからメールの内容を取得して所定のキーでHashMapに格納する。<BR>
	 * 
	 * @param message  受信メール。
	 * @param tempFileDirPath 添付ファイルディレクトリパス
	 * @return 取得メール。詳細はreceiveMailの復帰値「メール」参照。
	 * @throws MessagingException  メール操作の失敗。
	 * @throws Exception 異常発生。
	 */
	private HashMap<String, Object> getMail(MimeMessage message, String tempFileDirPath) throws Exception
	{
		// メール格納先(HashMap)を作成
		HashMap<String, Object> mail = new HashMap<String, Object>();
		// 送信元アドレスを取得
		Address[] addressFrom = message.getFrom();
		if(addressFrom != null)
		{
			getAddresses(addressFrom, "MLAD_FROM", mail);
		}
		// 送信先アドレス（ＴＯ）を取得
		Address[] addressTo   = message.getRecipients(javax.mail.Message.RecipientType.TO);
		if(addressTo != null)
		{
			getAddresses(addressTo, "MLAD_TO", mail);
		}

		// 送信先アドレス（ＣＣ）を取得
		Address[] addressCC = message.getRecipients(javax.mail.Message.RecipientType.CC);
		// 2013/11/05 対象アドレスが存在する場合のみ設定
		if(addressCC != null && addressCC.length > 0)
		{
			getAddresses(addressCC, "MLAD_CC", mail);
		}

		// 送信先アドレス（ＢＣＣ）を取得
		Address[] addressBCC = message.getRecipients(javax.mail.Message.RecipientType.BCC);
		// 2013/11/05 対象アドレスが存在する場合のみ設定
		if(addressBCC != null && addressCC.length > 0)
		{
			getAddresses(addressBCC, "MLAD_BCC", mail);
		}
		
		// 日時を取得
		Date sendDate = message.getSentDate();
		mail.put("DATE", sendDate);
		
		// 全てのヘッダを取得
		HashMap<String , String> headers = getAllHeaders(message);
		mail.put("MAIL_HEADER", headers);
		
		String headersStr = getAllHeadersStr(message);
		mail.put("MAIL_HEADER_STR", headersStr);
		
		// 件名を取得
		String subject = message.getSubject();
		mail.put("MAIL_TITLE", subject);
		
		// 本文および添付ファイルを取得
		textAndTempFiles(message, tempFileDirPath, mail);
		
		// メールサイズ サイズが取得できない場合は-1が設定される
		int mailSize = message.getSize();
		mail.put("MAIL_SIZE", mailSize);
		
		// メッセージID
		String messageId = message.getMessageID();
		mail.put("MESSAGE_ID", messageId);
		
		return mail;
	}
	
	/**
	 * <B>メソッド名： </B>アドレス一覧取得<BR>
	 * 
	 * <B>処理概要： </B><BR>
	 * Address[]からメールアドレスの一覧の文字列表現（RFC822形式）を取得する。<BR>
	 * 
	 * @param addresses アドレス一覧。InternetAddressの配列であること。
	 * @param mladSkbtCd メールアドレス設定フィールドコード
	 * @param mail メール情報
	 * @return メールアドレス一覧。
	 */
	private void getAddresses(Address[] addresses, String mladSkbtCd, HashMap<String, Object> mail) throws JCCFrameworkException
	{
		// アドレスリスト
		ArrayList<String> addressList = new ArrayList<String>(addresses.length);
		// アドレス表示名リスト
		ArrayList<String> addressDspNmList = new ArrayList<String>(addresses.length);
		for(int i = 0; i < addresses.length; i++)
		{
			InternetAddress address = (InternetAddress)addresses[i];
			String addressStr = address.toUnicodeString().trim();
			String addDspNm = null;
			// アドレスに「<」が含まれている場合、アドレスとアドレス表示名を分離する。（例：伊男 太郎<aaa@bbb.co.jp>）
			if(addressStr.indexOf("<") > -1)
			{
				String[] splitStr = addressStr.split("<");
				// アドレス表示名を設定
				addDspNm = splitStr[0].trim();
				// アドレスを設定
				addressStr = splitStr[1].substring(0, splitStr[1].length() - 1).trim();
			}
			// 2013/11/05 Add Start 空文字列のアドレスは許可しない
			if (addressStr == null || addressStr.length() < 1) {
				throw new JCCFrameworkException("不正なフォーマットのメールアドレスです：target = " + mladSkbtCd + ", address = " + address.toUnicodeString());
			}
			// 2013/11/05 Add End

			// アドレスを設定
			addressList.add(addressStr);
			// アドレス表示名を設定
			addressDspNmList.add(addDspNm);
		}

		// 2013/11/05 Add Start アドレス0件は許可しない
		if (addressList.size() < 1) {
			throw new JCCFrameworkException("メールアドレスが存在しません：" + mladSkbtCd);
		}
		// 2013/11/05 Add End

		mail.put(mladSkbtCd, (String[])addressList.toArray(new String[addressList.size()]));
		mail.put(mladSkbtCd + "_DSP_NM", (String[])addressDspNmList.toArray(new String[addressDspNmList.size()]));
		
	}

	/**
	 * <B>メソッド名： </B>全ヘッダ取得<BR>
	 * 
	 * <B>処理概要： </B><BR>
	 * MimeMessageから全てのヘッダを取得してHashMapに格納する。<BR>
	 * 
	 * @param message  対象のメッセージ。
	 * @return 全ヘッダを格納したHashMap。
	 * @throws Exception 異常発生。
	 */
	private String getAllHeadersStr(MimeMessage message) throws Exception
	{
		StringBuffer headers = new StringBuffer();
		Enumeration<?> en = message.getAllHeaders();
		
		int i = 0;
		
		while(en.hasMoreElements())
		{
			Header header = (Header)en.nextElement();
			headers.append(header.getName());
			headers.append(":");
			headers.append(header.getValue());
			// キーと値を結合して改行コードを付与
			headers.append(System.getProperty("line.separator"));
			
			i++;
		}
		return headers.toString();
	}

	/**
	 * <B>メソッド名： </B>全ヘッダ取得<BR>
	 * 
	 * <B>処理概要： </B><BR>
	 * MimeMessageから全てのヘッダを取得してHashMapに格納する。<BR>
	 * 
	 * @param message  対象のメッセージ。
	 * @return 全ヘッダを格納したHashMap。
	 * @throws Exception 異常発生。
	 */
	private HashMap<String, String> getAllHeaders(MimeMessage message) throws Exception
	{
		HashMap<String, String> headers = new HashMap<String, String>();
		Enumeration<?> en = message.getAllHeaders();
		
		int i = 0;
		
		while(en.hasMoreElements())
		{
			Header header = (Header)en.nextElement();
			if(headers.containsKey(header.getName()))
			{
				headers.put(header.getName() + "_ADDNO" + i, header.getValue());
			}
			else
			{
				headers.put(header.getName(), header.getValue());
			}
			
			i++;
		}
		return headers;
	}
	
	/**
	 * <B>メソッド名： </B>本文および添付ファイル取得<BR>
	 * 
	 * <B>処理概要： </B><BR>
	 * messageから本文および添付ファイルを取得する。<BR>
	 * 添付ファイルの場合はキーをファイル名、値をファイルパスにする<BR>
	 * @param message  対象のメッセージ。
	 * @param tempFileDirPath添付ファイルパス
	 * @param mail メール情報
	 * @throws Exception 異常発生。
	 */
	private void textAndTempFiles(MimeMessage message, String tempFileDirPath, HashMap<String, Object> mail) throws Exception
	{
		boolean gethtmltext = false;
		
		HashMap<String, String> map = new HashMap<String, String>();
		
		int msg_cnt = 0;
		
		
		// テキストのみ送られた場合、Multipartでキャストできないため、Stringかどうかを判断する。
		if(getContent(message) instanceof String)
		{
			String conType = message.getContentType();
			
			mail.put("CONTENT_TYPE", conType);
			
			if(conType == null || conType.indexOf("charset") == -1)
			{
				String msg = new String(getContent(message).toString().getBytes(),"JISAutoDetect");
				mail.put("MAIL_TEXT", msg);
			}
			else
			{
				mail.put("MAIL_TEXT", getContent(message).toString());
			}
			return;
		}
		
		// Multipartの場合のみ処理を行う
		if(getContent(message) instanceof Multipart)
		{
			Multipart rcvMp = (Multipart)getContent(message);
			// 添付ファイル格納ディレクトリの作成
			
			for(int i = 0; i < rcvMp.getCount(); i++)
			{
				Part rcvBody = rcvMp.getBodyPart(i);

				// multipartの中にmultipart(HTML形式で添付ファイルと共に受信された場合)
				if(getContent(rcvBody) instanceof Multipart)
				{
					Multipart rcvMpMulti = (Multipart)getContent(rcvBody);
					
					for(int j = 0 ; j < rcvMpMulti.getCount(); j++){
						Part rcvBodyMulti =rcvMpMulti.getBodyPart(j);
						
						// multipartの中にmultipart(HTML形式で添付ファイルとインライン画像が共に受信された場合)
						if(getContent(rcvBodyMulti) instanceof Multipart)
						{
							Multipart rcvMpMulti_withinline = (Multipart)getContent(rcvBodyMulti);
							for(int k = 0 ; k < rcvMpMulti_withinline.getCount(); k++){
								Part rcvBodyMulti_withinline =rcvMpMulti_withinline.getBodyPart(k);
								
								if(rcvBodyMulti_withinline.isMimeType("text/html") && !gethtmltext)
								{
									String conType = rcvBodyMulti_withinline.getContentType();
									
									mail.put("CONTENT_TYPE", conType);
									
									if(conType == null || conType.indexOf("charset") == -1)
									{
										String msg = new String(getContent(rcvBodyMulti_withinline).toString().getBytes(),"JISAutoDetect");
										mail.put("MAIL_TEXT", msg);
									}
									else
									{
										mail.put("MAIL_TEXT", getContent(rcvBodyMulti_withinline).toString());
									}
								}
								else if(rcvBodyMulti_withinline.isMimeType("text/plain"))
								{
									String conType = rcvBodyMulti_withinline.getContentType();
									
									mail.put("CONTENT_TYPE", conType);
									
									if(conType == null || conType.indexOf("charset") == -1)
									{
										String msg = new String(getContent(rcvBodyMulti_withinline).toString().getBytes(),"JISAutoDetect");
										if(chkMailText(msg))
										{
											// OM-2022-0000540 MOD START
//											mail.put("MAIL_TEXT", msg);
											String mailText = (String) mail.get("MAIL_TEXT");
											if (mailText != null)
											{
												StringBuffer mailTexts = new StringBuffer();
												mailTexts.append(mailText);
												mailTexts.append(msg);
												mail.put("MAIL_TEXT", mailTexts.toString());
											}
											else
											{
												mail.put("MAIL_TEXT", msg);
											}
											// OM-2022-0000540 MOD END
											gethtmltext = true;
										}
									}
									else
									{
										String msg = getContent(rcvBodyMulti_withinline).toString();
										if(chkMailText(msg))
										{
											// OM-2022-0000540 MOD START
//											mail.put("MAIL_TEXT", msg);
											String mailText = (String) mail.get("MAIL_TEXT");
											if (mailText != null)
											{
												StringBuffer mailTexts = new StringBuffer();
												mailTexts.append(mailText);
												mailTexts.append(msg);
												mail.put("MAIL_TEXT", mailTexts.toString());
											}
											else
											{
												mail.put("MAIL_TEXT", msg);
											}
											// OM-2022-0000540 MOD END
											gethtmltext = true;
										}
									}
								}
							}
						}
						else if(rcvBodyMulti.isMimeType("text/html") && !gethtmltext)
						{
							String conType = rcvBodyMulti.getContentType();
							
							mail.put("CONTENT_TYPE", conType);
							
							if(conType == null || conType.indexOf("charset") == -1)
							{
								String msg = new String(getContent(rcvBodyMulti).toString().getBytes(),"JISAutoDetect");
								mail.put("MAIL_TEXT", msg);
							}
							else
							{
								mail.put("MAIL_TEXT", getContent(rcvBodyMulti).toString());
							}
						}
						else if(rcvBodyMulti.isMimeType("text/plain"))
						{
							String conType = rcvBodyMulti.getContentType();
							
							mail.put("CONTENT_TYPE", conType);
							
							if(conType == null || conType.indexOf("charset") == -1)
							{
								String msg = new String(getContent(rcvBodyMulti).toString().getBytes(),"JISAutoDetect");
								if(chkMailText(msg))
								{
									// OM-2022-0000540 MOD START
//									mail.put("MAIL_TEXT", msg);
									String mailText = (String) mail.get("MAIL_TEXT");
									if (mailText != null)
									{
										StringBuffer mailTexts = new StringBuffer();
										mailTexts.append(mailText);
										mailTexts.append(msg);
										mail.put("MAIL_TEXT", mailTexts.toString());
									}
									else
									{
										mail.put("MAIL_TEXT", msg);
									}
									// OM-2022-0000540 MOD END
									gethtmltext = true;
								}
							}
							else
							{
								String msg = getContent(rcvBodyMulti).toString();
								if(chkMailText(msg))
								{
									// OM-2022-0000540 MOD START
//									mail.put("MAIL_TEXT", msg);
									String mailText = (String) mail.get("MAIL_TEXT");
									if (mailText != null)
									{
										StringBuffer mailTexts = new StringBuffer();
										mailTexts.append(mailText);
										mailTexts.append(msg);
										mail.put("MAIL_TEXT", mailTexts.toString());
									}
									else
									{
										mail.put("MAIL_TEXT", msg);
									}
									// OM-2022-0000540 MOD END
									gethtmltext = true;
								}
							}
//							break;
						}
						// インライン画像ファイルを取得
						else if(rcvBodyMulti.getDataHandler().getDataSource().getName() != null)
						{
							InputStream input = null;
							OutputStream output = null;
							String rcvFileNm = null;
							String filePath = null;
							try
							{
								// ファイル名取得（同じファイル名が送られる場合を考慮して、ファイル名の頭に連番をつける）
								String fileNm = MimeUtility.decodeText(rcvBodyMulti.getDataHandler().getDataSource().getName());
								//v13.00.00 ADD START
								if(fileNm == null || "".equals(fileNm))
								{
									fileNm = "attachedFile";
								}
								//v13.00.00 ADD END
								rcvFileNm = i + "_" + fileNm;
								// ファイルのストリームを取得
								input = rcvBodyMulti.getDataHandler().getDataSource().getInputStream();
								
								// 添付ファイルの絶対パスの取得
								filePath = JCCFileUtil.createDirUid(tempFileDirPath);
								
								output = new FileOutputStream(filePath);
								int cnt = 0;
								while((cnt = input.read()) != -1)
								{
									output.write(cnt);
								}
							}
							catch(Exception e)
							{
								throw new JCCFrameworkException("添付ファイルの取得に失敗しました。：" + e);
							}
							finally
							{
								if(input != null)
								{
									input.close();
								}
								if(output != null)
								{
									output.close();
								}
							}
							map.put(rcvFileNm , filePath);
						}
					}
				}
				// text/plain形式の文字列を設定(ファイル名の有無で判別しないと.txtの添付ファイルがtext/plainとして表現される)
				else if(rcvBody.getDataHandler().getDataSource().getName() == null && !isAttachment(rcvBody))
				{
					if(rcvBody.isMimeType("text/html") && !gethtmltext)
					{
						String conType = rcvBody.getContentType();
						
						mail.put("CONTENT_TYPE", conType);
						
						if(conType == null || conType.indexOf("charset") == -1)
						{
							String msg = new String(getContent(rcvBody).toString().getBytes(),"JISAutoDetect");
							mail.put("MAIL_TEXT", msg);
						}
						else
						{
							mail.put("MAIL_TEXT", getContent(rcvBody).toString());
						}
					}
					else if(rcvBody.isMimeType("text/plain"))
					{
						String conType = rcvBody.getContentType();
						
						mail.put("CONTENT_TYPE", conType);
						
						if(conType == null || conType.indexOf("charset") == -1)
						{
							String msg = new String(getContent(rcvBody).toString().getBytes(),"JISAutoDetect");
							if(chkMailText(msg))
							{
								// OM-2022-0000540 MOD START
//								mail.put("MAIL_TEXT", msg);
								String mailText = (String) mail.get("MAIL_TEXT");
								if (mailText != null)
								{
									StringBuffer mailTexts = new StringBuffer();
									mailTexts.append(mailText);
									mailTexts.append(msg);
									mail.put("MAIL_TEXT", mailTexts.toString());
								}
								else
								{
									mail.put("MAIL_TEXT", msg);
								}
								// OM-2022-0000540 MOD END
								gethtmltext = true;
							}
						}
						else
						{
							String msg = getContent(rcvBody).toString();
							if(chkMailText(msg))
							{
								// OM-2022-0000540 MOD START
//								mail.put("MAIL_TEXT", msg);
								String mailText = (String) mail.get("MAIL_TEXT");
								if (mailText != null)
								{
									StringBuffer mailTexts = new StringBuffer();
									mailTexts.append(mailText);
									mailTexts.append(msg);
									mail.put("MAIL_TEXT", mailTexts.toString());
								}
								else
								{
									mail.put("MAIL_TEXT", msg);
								}
								// OM-2022-0000540 MOD END
								gethtmltext = true;
							}
						}
					}
//					else if(getContent(rcvBody) instanceof Message){
					else if(rcvBody.isMimeType("message/rfc822") || rcvBody.isMimeType("message/delivery-status")){
						
						InputStream input = null;
						OutputStream output = null;
						String rcvFileNm = null;
						String filePath = null;
						try
						{
							
							// ファイル名取得（同じファイル名が送られる場合を考慮して、ファイル名の頭に連番をつける）
							rcvFileNm = "message" + msg_cnt++ + ".eml";
							// ファイルのストリームを取得
							input = rcvBody.getDataHandler().getDataSource().getInputStream();
							
							// 添付ファイルの絶対パスの取得
							filePath = JCCFileUtil.createDirUid(tempFileDirPath);
							
							output = new FileOutputStream(filePath);
							int cnt = 0;
							while((cnt = input.read()) != -1)
							{
								output.write(cnt);
							}
						}
						catch(Exception e)
						{
							throw new JCCFrameworkException("添付ファイルの取得に失敗しました。：" + e);
						}
						finally
						{
							if(input != null)
							{
								input.close();
							}
							if(output != null)
							{
								output.close();
							}
						}
						map.put(rcvFileNm , filePath);
						
					}
				}
				else
				{
					// v5.00.03 2013/12/18 ファイル名取得方法変更
					// 添付ファイルを取得
					InputStream input = null;
					OutputStream output = null;
					String rcvFileNm = null;
					String filePath = null;
					try
					{

						// v5.00.03 2013/12/18 ファイル名取得方法変更（取得できない場合は仮名称設定）
						// ファイル名取得（同じファイル名が送られる場合を考慮して、ファイル名の頭に連番をつける）
						String fileNm = getAttachName(rcvBody);
						if (fileNm == null) {
							fileNm = "attachedFile";
						}
						rcvFileNm = i + "_" + MimeUtility.decodeText(fileNm);
						// ファイルのストリームを取得
						input = rcvBody.getDataHandler().getDataSource().getInputStream();
						
						// 添付ファイルの絶対パスの取得
						filePath = JCCFileUtil.createDirUid(tempFileDirPath);
						
						output = new FileOutputStream(filePath);
						int cnt = 0;
						while((cnt = input.read()) != -1)
						{
							output.write(cnt);
						}
					}
					catch(Exception e)
					{
						throw new JCCFrameworkException("添付ファイルの取得に失敗しました。：" + e);
					}
					finally
					{
						if(input != null)
						{
							input.close();
						}
						if(output != null)
						{
							output.close();
						}
					}
					map.put(rcvFileNm , filePath);
				}
			}
		}
		
		
		mail.put("TEMP_FILE", map);
	}
	
	/**
	 * <B>メソッド名： </B>コミット<BR>
	 * 
	 * <B>処理概要： </B><BR>
	 * サーバから切断する。<BR>
	 * 削除フラグを有効にする。<BR>
	 * サーバと接続中でない場合は何も処理しない。<BR>
	 * 
	 * @throws Exception 異常発生。
	 */
	public void commit() throws Exception
	{
		if(store != null)
		{
			// サーバと接続中の場合
			Exception exception = null;
			
			if(folder != null)
			{
				try
				{
					// フォルダを閉じる
					folder.close(true); // 削除フラグを有効にする
				}
				catch (Exception e)
				{
					exception = e;
				}
				folder = null;
			}
			
			try
			{
				// サーバから切断
				store.close();
			}
			catch (Exception e)
			{
				if(exception == null)
				{
					// 例外が未発生の場合は格納
					exception = e;
				}
			}
			store = null;
			
			if(exception != null)
			{
				// 例外が発生した場合は先に発生した例外を優先的に投げる
				throw new JCCFrameworkException("メールサーバーのコミット中にエラーが発生しました。" + exception); 
			}
		}
	}
	
	/**
	  * <B>メソッド名： </B>ロールバック<BR>
	  * 
	  * <B>処理概要： </B><BR>
	  * 削除フラグを有効にしない。<BR>
	  * サーバと接続中でない場合は何も処理しない。<BR>
	  * 
	  * @throws Exception 異常発生。
	  */
	public void rollback() throws Exception
	{
		
		// サーバと接続中の場合
		if(store != null)
		{
			
			Exception exception = null;
			
			if(folder != null)
			{
				try
				{
					// フォルダを閉じる
					folder.close(false); // 削除フラグを有効にしない
				}
				catch (Exception e)
				{
					exception = e;
				}
				folder = null;
			}
			
			try
			{
				// サーバから切断
				store.close();
			}
			catch (Exception e)
			{
				if(exception == null)
				{
					// 例外が未発生の場合は格納
					exception = e;
				}
			}
			store = null;
			
			if(exception != null)
			{
				// 例外が発生した場合は先に発生した例外を優先的に投げる
				throw new JCCFrameworkException("メールサーバーのロールバック中にエラーが発生しました。" + exception); 
			}
		}
	}
	
	 /**
	  * <B>メソッド名： </B>削除フラグ解除<BR>
	  * 
	  * <B>処理概要： </B><BR>
	  * 指定されたメッセージの削除フラグの解除を行う<BR>
	  * サーバと接続中でない場合は何も処理しない。<BR>
	  * @param messageId 解除したいメッセージID
	  * @throws MessagingException 異常発生。
	  */
	public void unlockFlg(String messageId) throws Exception
	{
		
		// メッセージIDチェック
		if (messageId == null) {
			throw new JCCFrameworkException("メッセージIDがnullです。");
		}
		
		try
		{
			// 全メッセージオブジェクトをフォルダから取得
			Message[] messages = folder.getMessages();
				
			// 全メッセージの取得
			for(int i = 0; i < messages.length; i++)
			{
				// メッセージを取得
				MimeMessage message = (MimeMessage)messages[i];
				if(messageId.equals(message.getMessageID()))
				{
					message.setFlag(javax.mail.Flags.Flag.DELETED, false);
					break;
				}
			}
		}
		catch(Exception e)
		{
			throw new JCCFrameworkException("受信メールの削除フラグ解除時にエラーが発生しました。" + e); 
		}
	}
	
	 /**
	  * <B>処理概要： </B><BR>
	  * CP932のメールを受信した際に例外をcatchしてMS932にエンコーディングする。<BR>
	  * @param MimeMessage
	  * @throws MessagingException,IOException
	  */
	private Object getContent(MimeMessage message) throws MessagingException,IOException
	{
		try
		{
			return message.getContent();
		}
		catch(UnsupportedEncodingException ue)
		{
			String conType = message.getContentType();
			if(conType != null && conType.toLowerCase().indexOf("cp932") != -1)
			{
				InputStream messageStream = message.getInputStream();
				ByteArrayOutputStream out = new ByteArrayOutputStream();
				int c;
				while((c = messageStream.read()) != -1)
				{
					out.write(c);
				}
				byte[] bytes = out.toByteArray();
				String string = new String(bytes,"MS932");
				return  string;
			}
			else
			{
				throw ue;
			}
		}
	}
	 /**
	  * <B>処理概要： </B><BR>
	  * CP932のメールを受信した際に例外をcatchしてMS932にエンコーディングする。<BR>
	  * @param Part
	  * @throws MessagingException,IOException
	  */
	private Object getContent(Part rcvBody) throws MessagingException,IOException
	{
		try
		{
			return rcvBody.getContent();
		}
		catch(UnsupportedEncodingException ue)
		{
			String conType = rcvBody.getContentType();
			if(conType != null && conType.toLowerCase().indexOf("cp932") != -1)
			{
				InputStream messageStream = rcvBody.getInputStream();
				ByteArrayOutputStream out = new ByteArrayOutputStream();
				int c;
				while((c = messageStream.read()) != -1)
				{
					out.write(c);
				}
				byte[] bytes = out.toByteArray();
				String string = new String(bytes,"MS932");
				return  string;
			}
			else
			{
				throw ue;
			}
		}
	}
	
	/**
	 * メール本文の内容チェック（空もしくは空白のみの場合：false）
	 * @param text
	 * @return boolean
	 */
	private boolean chkMailText(String text)
	{
		boolean bool = false;
		
		if(text == null || text.equals(""))
		{
			return bool;
		}
		
		String chktext = text.replaceAll(" ", "");
		chktext = chktext.replaceAll("　", "");
		chktext = chktext.replaceAll("\r", "");
		chktext = chktext.replaceAll("\n", "");
		
		if(chktext.length() > 0)
		{
			bool = true;
		}
		return bool;
	}

	// 2013/11/11 v5.00.01 Add Start
	/**
	 * セッション保持メソッド<br>
	 * メールフォルダにアクセスしてセッション保持し続ける<br>
	 * （isConnectコマンドでアクセスする）
	 * @return セッション保持失敗または成功
	 */
	public boolean keepAlive() {
		// 接続されていなければエラー
		if (store == null || folder == null) {
			return false;
		}

		// セッション保有しているかどうかを返す
		return store.isConnected();
	}
	// 2013/11/11 v5.00.01 Add End

	// 2013/12/18 v5.00.03 Add Start
	/**
	 * 添付ファイルかどうかを返す
	 * @param tgt チェック対象Part
	 * @return Content-Disposition に「attachment」の記述があるかどうか
	 * @throws MessagingException Part操作時エラー
	 */
	private boolean isAttachment(Part tgt) throws MessagingException {
		// Content-Dispositionなし
		if (tgt.getHeader("Content-Disposition") == null) {
			return false;
		}

		for (String conDis : tgt.getHeader("Content-Disposition")) {
			if (conDis.toLowerCase().indexOf("attachment") >= 0) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 添付ファイル名を取得して返す
	 * @param tgt 対象Part
	 * @return 対象ファイル名
	 * @throws MessagingException Part操作時エラー
	 */
	private String getAttachName(Part tgt) throws MessagingException {
		// Content-Disposition:filename=ファイル名
		// Content-Type:name=ファイル名
		// いずれかが取得できれば返す
		String name = tgt.getDataHandler().getDataSource().getName();
		if (name != null) {
			return name;
		}

		// Content-Location:ファイル名 が取得できれば返す
		if (tgt.getHeader("Content-Location") == null) {
			return null;
		}
		for (String conLoc : tgt.getHeader("Content-Location")) {
			if (conLoc.length() > 0) {
				return conLoc;
			}
		}
		return null;
	}
	// 2013/12/18 v5.00.03 Add End
}