    001/*
    002 * Copyright (c) 2009 The openGion Project.
    003 *
    004 * Licensed under the Apache License, Version 2.0 (the "License");
    005 * you may not use this file except in compliance with the License.
    006 * You may obtain a copy of the License at
    007 *
    008 *     http://www.apache.org/licenses/LICENSE-2.0
    009 *
    010 * Unless required by applicable law or agreed to in writing, software
    011 * distributed under the License is distributed on an "AS IS" BASIS,
    012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
    013 * either express or implied. See the License for the specific language
    014 * governing permissions and limitations under the License.
    015 */
    016package org.opengion.hayabusa.mail;
    017
    018import static org.opengion.fukurou.util.StringUtil.csv2ArrayOnly;
    019import static org.opengion.fukurou.util.StringUtil.nval;
    020
    021import java.util.ArrayList;
    022import java.util.List;
    023import java.util.Map;
    024import java.util.TreeMap;
    025
    026import javax.mail.internet.AddressException;
    027import javax.mail.internet.InternetAddress;
    028
    029import org.opengion.fukurou.db.DBUtil;
    030import org.opengion.fukurou.security.HybsCryptography;
    031import org.opengion.fukurou.util.StringUtil;
    032import org.opengion.fukurou.util.XHTMLTag;
    033import org.opengion.hayabusa.common.HybsSystem;
    034
    035/**
    036 * メール定型文及びそれも基づいて各項目の合成を行うクラスです。
    037 * コンストラクタには定型文ID及びシステムIDで定型文マスタよりメールの定型文を取得します。
    038 * メール各項目のゲッターでは、定型文の内容を元にパラメータ値とマージして各項目を合成します。
    039 * 宛先について、セットした社員ID、グループIDと定型文の宛先設定に基づき、社員マスタと
    040 * グループマスタよりメールアドレス情報を取得して宛先マップを作成します。
    041 *
    042 *
    043 * @og.rev 5.6.6.0 (2013/07/05) host指定対応。GE37必須です。
    044 *
    045 * @og.group メールモジュール
    046 *
    047 * @version  4.0
    048 * @author   Sen.Li
    049 * @since    JDK1.6
    050 */
    051public class MailPattern {
    052
    053        // 5.2.0.0 (2010/09/01) Ver4互換モード対応
    054        private static final String CONTENTS = HybsSystem.sysBool( "VER4_COMPATIBLE_MODE" ) ? "CONTENT" : "CONTENTS";
    055        private static final String ADDRESS = HybsSystem.sysBool( "VER4_COMPATIBLE_MODE" ) ? "MEMBER" : "ADDRESS";
    056        private static final String NAME_JA = HybsSystem.sysBool( "VER4_COMPATIBLE_MODE" ) ? "NAME" : "NAME_JA";
    057        private static final String KBNAME = HybsSystem.sysBool( "VER4_COMPATIBLE_MODE" ) ? "NM_KBN" : "KBNAME";
    058
    059        // 5.1.0.0 (2009/11/04) CONTENT ⇒ CONTENTS
    060        // 5.2.0.0 (2010/09/01) Ver4互換モード対応
    061//      private static final String selGE31     = "SELECT PTN_ID,FROM_ID,TO_ID,CC_ID,BCC_ID,TITLE,CONTENTS"
    062        private static final String selGE31     = "SELECT PTN_ID,FROM_ID,TO_ID,CC_ID,BCC_ID,TITLE,"+CONTENTS
    063                                                                                        + " ,JOKEN" // 5.6.6.0 (2013/07/05)
    064                                                                                        + " FROM GE31"
    065                                                                                        + " WHERE SYSTEM_ID =? AND PTN_ID=? AND FGJ='1'";
    066        // 5.1.0.0 (2009/11/04) MEMBER ⇒ ADDRESS , NM_KBN ⇒ KBNAME , NAME ⇒ NAME_JA
    067        // 5.2.0.0 (2010/09/01) Ver4互換モード対応
    068//      private static final String     selGE33         = "SELECT A.ADDRESS,A.NAME_JA,B.NAME_JA"
    069        private static final String     selGE33         = "SELECT A."+ADDRESS+",A."+NAME_JA+",B."+NAME_JA
    070                                                                                        + " FROM GE33 A,GE33 B"
    071                                                                                        + " WHERE A.FGJ='1' AND B.FGJ(+)='1' AND A.GROUP_ID=B.GROUP_ID(+)"
    072//                                                                                      + " AND A.KBNAME='1' AND B.KBNAME(+)='0' AND A.SYSTEM_ID=B.SYSTEM_ID(+)"
    073                                                                                        + " AND A."+KBNAME+"='1' AND B."+KBNAME+"(+)='0' AND A.SYSTEM_ID=B.SYSTEM_ID(+)"
    074                                                                                        + " AND A.SYSTEM_ID =? "
    075                                                                                        + " AND A.GROUP_ID =?";
    076        // 5.3.5.0 (2011/05/01) Ver4対応漏れ対応
    077        // 5.9.6.3 (2013/10/25) selGE35をpublic化
    078//      private static final String     selGE35         = "SELECT  NAME_JA,MAIL"
    079//      private static final String     selGE35         = "SELECT  "+NAME_JA+",MAIL"
    080        /**
    081         * GE35のメールアドレス検索文
    082         */
    083        public static final String      selGE35         = "SELECT  "+NAME_JA+",MAIL"
    084                                                                                        + " FROM GE35"
    085                                                                                        + " WHERE USERID=?";
    086
    087        // 5.6.6.0 (2013/07/05) 振り分け条件
    088        private static final String     selGE37         = "SELECT  HOST,PORT,AUTH,AUTHUSER,AUTHPASS"
    089                                                                                        + " FROM GE37"
    090                                                                                        + " WHERE SYSTEM_ID = ?"
    091                                                                                        + " AND JOKEN = ?"
    092                                                                                        + " AND FGJ ='1'";
    093
    094        // 内部データのカラム番号(定型文マスタテーブル)
    095        // 5.1.9.0 (2010/09/01) public ⇒ private へ変更
    096//      private static final int GE31_PTN_ID    = 0 ;           // 未使用
    097        private static final int GE31_FROM_ID   = 1 ;
    098        private static final int GE31_TO_ID             = 2 ;
    099        private static final int GE31_CC_ID             = 3 ;
    100        private static final int GE31_BCC_ID    = 4 ;
    101        private static final int GE31_TITLE             = 5 ;
    102        private static final int GE31_CONTENTS  = 6 ;           // 5.1.0.0 (2009/11/04) CONTENT ⇒ CONTENTS
    103        private static final int GE31_JOKEN             = 7 ;           // 5.6.6.0 (2013/07/05)
    104
    105        // 内部データのカラム番号(グループマスタ)
    106        private static final int GE33_ADDRESS   = 0 ;           // 5.1.0.0 (2009/11/04) MEMBER ⇒ ADDRESS
    107        private static final int GE33_MNAME             = 1 ;
    108        private static final int GE33_GNAME             = 2 ;
    109        // 内部データのカラム番号(社員マスタ)
    110        // 5.6.9.3 (2013/10/25) public化
    111//      private static final int GE35_NAME              = 0 ;
    112//      private static final int GE35_MAIL              = 1 ;
    113        /**
    114         * GE35のユーザ名称
    115         */
    116        public static final int GE35_NAME               = 0 ;
    117        /**
    118         * GE35のメールアドレス
    119         */
    120        public static final int GE35_MAIL               = 1 ;
    121
    122        // 内部データのカラム番号(送信ホストマスタ)
    123        private static final int GE37_HOST              = 0 ;
    124        private static final int GE37_PORT              = 1 ;
    125        private static final int GE37_AUTH              = 2 ;
    126        private static final int GE37_AUTHUSER  = 3 ;
    127        private static final int GE37_AUTHPASS  = 4 ;
    128
    129        // 内部データのカラム番号(宛先テーブル)
    130        /** カラム番号(宛先テーブル) {@value} */
    131        public static final int IDX_DST_ID      = 0 ;
    132        /** カラム番号(宛先テーブル) {@value} */
    133        public static final int IDX_GROUP_ID    = 1 ;
    134        /** カラム番号(宛先テーブル) {@value} */
    135        public static final int IDX_GROUP_NAME  = 2 ;
    136        /** カラム番号(宛先テーブル) {@value} */
    137        public static final int IDX_DST_NAME    = 3 ;
    138        /** カラム番号(宛先テーブル) {@value} */
    139        public static final int IDX_DST_ADDR    = 4 ;
    140        /** カラム番号(宛先テーブル) {@value} */
    141        public static final int IDX_DST_KBN     = 5 ;
    142        /** カラム番号(宛先テーブル) {@value} */
    143        public static final int IDX_FGJ                 = 6 ;
    144
    145        /** メール送信区分 {@value} */
    146        public static final int KBN_TO                  = 0 ;   // メール送信区分(TO)
    147        /** メール送信区分 {@value} */
    148        public static final int KBN_CC                  = 1 ;   // メール送信区分(CC)
    149        /** メール送信区分 {@value} */
    150        public static final int KBN_BCC                 = 2 ;   // メール送信区分(BCC)
    151
    152        private static final String PreFixGroup = "GP.";
    153        private final List<String> errAddrList            = new ArrayList<String>();
    154//      private Map<String, String> paramMap      = new HashMap<String, String>();
    155        private final Map<String, String> paramMap ;
    156        private String  fromId          = null;
    157        private final String    toId    ;
    158        private final String    ccId    ;
    159        private final String    bccId   ;
    160        private String[][]      title   = null;
    161        private String[][]      content = null;
    162        private Map<String, String[]> mailDstMap;
    163
    164        // 5.6.6.0 (2013/07/05)
    165        private String host     = HybsSystem.sys( "COMMON_MAIL_SERVER" );
    166        private String smtpPort = HybsSystem.sys( "SMTP_PORT" );
    167        private String auth             = HybsSystem.sys( "MAIL_SEND_AUTH" );
    168        private String authPort = HybsSystem.sys( "MAIL_SEND_AUTH_PORT" );              // 5.8.1.1 (2014/11/14)
    169        private String authUser = HybsSystem.sys( "MAIL_SEND_AUTH_USER" );
    170        private String authPass = HybsSystem.sys( "MAIL_SEND_AUTH_PASSWORD" );
    171        private boolean useTLS  = HybsSystem.sysBool( "MAIL_SEND_USE_STARTTLS" ); // 5.9.29.2 (2018/02/16)
    172
    173
    174        private final String DBID = HybsSystem.sys( "RESOURCE_DBID" );          // 5.5.5.1 (2012/08/07) リソース系DBID 付け忘れ対応
    175
    176        /**
    177         * メール定型文オブジェクトを作成するコンストラクタです。
    178         * 定型文マスタより取得したデータを各フィルードにセットします。
    179         *
    180         * @og.rev 5.5.5.1 (2012/08/07) リソース系DBID 付け忘れ対策
    181         * @og.rev 5.6.6.0 (2013/07/05) 振り分け対応
    182         *
    183         * @param       params  パラメータのマップ
    184         */
    185        public MailPattern( final Map<String, String> params ){
    186                paramMap = params;
    187                String sysId = params.get( "SYSTEM_ID" );
    188                String pid = params.get( "PTN_ID" );
    189                String[] selGE30Args = { sysId,pid };
    190//              String[][] ptn = DBUtil.dbExecute( selGE31, selGE30Args, AbstractMailManager.appInfo );
    191                String[][] ptn = DBUtil.dbExecute( selGE31, selGE30Args, AbstractMailManager.appInfo, DBID );           // 5.5.5.1 (2012/08/07)
    192                if( ptn == null || ptn.length <=0 ) {
    193                        String errMsg = "定型文取得できません。システムID：" + sysId + "定型文ID：" + pid ;
    194                        throw new RuntimeException( errMsg );
    195                }
    196                fromId  = ptn[0][GE31_FROM_ID];
    197                toId    = ptn[0][GE31_TO_ID];
    198                ccId    = ptn[0][GE31_CC_ID];
    199                bccId   = ptn[0][GE31_BCC_ID];
    200                String tit = ptn[0][GE31_TITLE];
    201                if( tit != null && tit.length() > 0 ) {
    202                        title = splitParam( tit );
    203                }
    204                String con = ptn[0][GE31_CONTENTS];                     // 5.1.0.0 (2009/11/04) CONTENT ⇒ CONTENTS
    205                if( con != null && con.length() > 0 ) {
    206                        content = splitParam( con );
    207                }
    208                // 5.6.6.0 (2013/07/05) 振り分け対応
    209                String joken = ptn[0][GE31_JOKEN];
    210                if( joken != null && joken.length() > 0 ) {
    211                        String[] selGE37Args = { sysId,joken };
    212                        String[][] jkn = DBUtil.dbExecute( selGE37, selGE37Args, AbstractMailManager.appInfo, DBID );
    213                        if( ptn == null || ptn.length <=0 ) {
    214                                String errMsg = "メールホストの振分先が取得できません。システムID：" + sysId + "振分条件：" + joken ;
    215                                throw new RuntimeException( errMsg );
    216                        }
    217                        host            = jkn[0][GE37_HOST];
    218                        smtpPort        = jkn[0][GE37_PORT];
    219                        auth            = jkn[0][GE37_AUTH];
    220                        authUser        = jkn[0][GE37_AUTHUSER];
    221                        authPass        = jkn[0][GE37_AUTHPASS];
    222                }
    223        }
    224
    225        /**
    226         * 定型文の送信者ID欄の設定値とパラメータ{&#064;FROM}を元に送信者アドレスを取得します。
    227         * 定型文には{&#064;FROM}とセットされている場合は、パラメータ｛&#064;FROM｝の値を元に、社員IDをセット
    228         * されている場合、直接そのIDを元に社員マスタから送信者アドレスを取得します。
    229         * 送信者アドレス取得できなければ例外を投げます。
    230         *
    231         * @og.rev 4.3.7.5 (2009/07/08) 送信元名称が設定されていない場合は、アドレスを&lt;&gt;で囲わない
    232         *
    233         * @return      送信者アドレス
    234         */
    235        public String getFromAddr(){
    236                // 定型文に{&#064;FROM}⇒ユーザーよりセットしたデータで置換える、ユーザーIDの場合はそのまま
    237                if( "{@FROM}".equals( fromId ) ) {
    238                        fromId = paramMap.get( "FROM" );
    239                }
    240                paramMap.put( "FROM_ID" , fromId );     // 送信者ID
    241
    242                String[] userInf = getUserInfo( fromId );
    243                String fromAddr = null;
    244                if( userInf != null && checkAddr ( fromId, userInf[1] ) ){      // 送信者メールアドレスチェック
    245                        paramMap.put( "FROM_NAME", userInf[0] );                                // 送信者名前
    246                        // 4.3.7.5 (2009/07/08)
    247                        if( userInf[0] != null && userInf[0].length() > 0 ) {
    248                                fromAddr = userInf[0] + "<" + userInf[1] + ">" ;
    249                        }
    250                        else {
    251                                fromAddr = userInf[1];
    252                        }
    253                        paramMap.put( "FROM_ADDR", fromAddr );                                  // 送信者メールアドレス
    254                }
    255                else {
    256                        String errMsg = "送信者ユーザー情報エラー。ユーザーID：" + fromId;
    257                        throw new RuntimeException( errMsg );
    258                }
    259
    260                return fromAddr;
    261        }
    262
    263        /**
    264         * マージ済のメールタイトルを返します。
    265         *
    266         * @return      メールタイトル
    267         *
    268         */
    269        public String getTitle(){
    270                return marge( title );
    271        }
    272
    273        /**
    274         * マージ済のメール本文を返します。
    275         *
    276         * @og.rev 5.1.0.0 (2009/11/04) HEADER ⇒ H_TXT , FOOTER ⇒ F_TXT カラム名変更
    277         *
    278         * @return      メール本文
    279         */
    280        public String getContent(){
    281                String header = paramMap.get( "HEADER" );               // 5.1.0.0 (2009/11/04) HEADER ⇒ H_TXT
    282                StringBuilder contentBuf = new StringBuilder();
    283                if ( header != null ) {
    284                        contentBuf.append( header ).append( '\n' );
    285                }
    286                contentBuf.append( marge( content ) ).append( '\n' );
    287                String fooder = paramMap.get( "FOOTER" );               // 5.1.0.0 (2009/11/04) FOOTER ⇒ F_TXT
    288                if ( fooder != null ) {
    289                        contentBuf.append( fooder );
    290                }
    291
    292                return contentBuf.toString();
    293        }
    294
    295        /**
    296         * 引数の文字列により、定数文字列の部分とパラメータの部分を分解します。
    297         * 例："A{&#064;PARAM1}B"⇒rtn[0][0]="A",rtn[0][1]="B",rtn[1][0]="PARAM1"
    298         *
    299         * @param       src             分解対象の文字列
    300         *
    301         * @return      定数文字列の部分とパラメータの部分を分解した配列
    302         */
    303        private String[][] splitParam( final String src ) {
    304                String[][] rtn = new String[2][];
    305                if( src == null ) { return new String[2][0]; }
    306
    307                ArrayList<String> listCons = new ArrayList<String>() ;
    308                ArrayList<String> listPara = new ArrayList<String>() ;
    309
    310                int start = 0;
    311                int index = src.indexOf( "{@" );
    312                while( index >= 0 ) {
    313                        listCons.add( src.substring( start, index ) );
    314                        int end = src.indexOf( '}',index );
    315                        if( end < 0 ) {
    316                                String errMsg = "{@ と } との対応関係がずれています。"
    317                                                        + "src=[" + src + "] : index=" + index ;
    318                                throw new RuntimeException( errMsg );
    319                        }
    320                        listPara.add( src.substring( index + 2, end ));
    321
    322                        start = end+1 ;
    323                        index = src.indexOf( "{@",start );
    324                }
    325                listCons.add ( src.substring( start ) );
    326
    327                rtn[0] = listCons.toArray( new String[listCons.size()] );
    328                rtn[1] = listPara.toArray( new String[listPara.size()] );
    329
    330                return rtn;
    331        }
    332
    333        /**
    334         * 送信先のアドレスをセットします。
    335         * 定型文に定義されている宛先(TO、CC、BCC)を引数として渡します。引数には{&#064;TO}、{&#064;CC}、{&#064;BCC}が含まれています。
    336         * {&#064;TO}、{&#064;CC}、{&#064;BCC}を初期設定の値で置換えて、実のメールアドレスマップを作成します。
    337         *
    338         * @return 宛先のマップ
    339         */
    340        public Map<String, String[]> getDstMap(){
    341                String[] toBuf = getDstArray( toId );
    342                String[] ccBuf = getDstArray( ccId );
    343                String[] bccBuf = getDstArray( bccId );
    344
    345                // 送信先(TO、CC、BCC)のマップを作成します。
    346                mailDstMap =  (TreeMap<String, String[]>)getDstAddrMap( bccBuf, KBN_BCC );
    347                mailDstMap.putAll( (TreeMap<String, String[]>) getDstAddrMap( ccBuf, KBN_CC ) );
    348                mailDstMap.putAll( (TreeMap<String, String[]>) getDstAddrMap( toBuf, KBN_TO ) );
    349                setDstWord();
    350
    351                return mailDstMap;
    352        }
    353
    354        /**
    355         * アドレスエラーのメッセージリストを返します。
    356         *
    357         * @return      メッセージリスト
    358         */
    359        public List<String> getErrList(){
    360                return errAddrList;
    361        }
    362
    363        /**
    364         * 送信先のアドレスをcsv形式から配列にセットします。
    365         * 引数は定型文マスタにセットしたものです。例：{&#064;TO},C12345,GP.IT
    366         * ｛&#064;TO｝、｛&#064;CC｝、｛&#064;BCC｝はパラメータテーブルにセットしたもので置き換えます。
    367         * 分解後の配列には、ユーザーID及びグループIDが混在します。
    368         *
    369         * @param       csvId   csv形式のアドレス
    370         *
    371         * @return      送信先のアドレスの配列
    372         */
    373        private String[] getDstArray( final String csvId ){
    374                String[] csvArr = csv2ArrayOnly( csvId );
    375                ArrayList<String> list = new ArrayList<String>();
    376
    377                String[] tmp;
    378                int size = csvArr.length;
    379                for( int i = 0; i < size; i++ ){
    380                        if( csvArr[i].startsWith( "{@" )){
    381                                tmp = csv2ArrayOnly( paramMap.get( csvArr[i].substring( 2, csvArr[i].length() - 1 ) ) );
    382                                int len = tmp.length;
    383                                for(int j=0;j<len;j++){
    384                                        list.add( tmp[j] );
    385                                }
    386                        }
    387                        else{
    388                                list.add( csvArr[i]);
    389                        }
    390                }
    391                return list.toArray( new String[list.size()] );
    392        }
    393
    394        /**
    395         * 送信先のアドレス・マップを作成します。
    396         *　引数 dstBuf にはユーザーIDとグループID混在する配列です。
    397         *　ユーザーIDの場合、社員マスタのビューから名前及びメールアドレスを取得してマップにセットします。
    398         *　グループIDの場合、グループマスタより、名前及びメールアドレスを取得してマップにセットします。
    399         *　重複のユーザーが存在する場合、最後にセットした方が採用されます。
    400         *
    401         * @og.rev 5.1.0.0 (2009/11/04) MEMBER ⇒ ADDRESS カラム名変更
    402         *
    403         * @param       dstBuf  ユーザーIDとグループID混在する配列
    404         * @param       kbn             送信区分[0:TO/1:CC/2:BCC]
    405         *
    406         * @return      送信先のアドレス・マップ
    407         */
    408        private Map<String, String[]> getDstAddrMap( final String[] dstBuf, final int kbn ){
    409                Map<String,String[]> dstMap= new TreeMap<String,String[]>();
    410                 // IDX_DST_ID ,IDX_GROUP_ID, IDX_GROUP_NAME ,IDX_DST_NAME ,IDX_DST_ADDR ,IDX_DST_KBN ,IDX_FGJ
    411                 String[] dstInit = { "", "", "", "", "", Integer.toString( kbn ), "7" };
    412
    413                 int len = dstBuf.length;
    414                 for( int i=0; i < len; i++ ){
    415                         if( dstBuf[i].startsWith( PreFixGroup ) ) { // グループIDの場合、グループマスタより、メンバーを取得します。
    416                                String[][] groupUsers = getGroupUsers( dstBuf[i].substring( PreFixGroup.length() ) );
    417                                if( groupUsers.length > 0 ) {
    418                                        int memberCnt = groupUsers.length;
    419                                        for( int j = 0; j < memberCnt; j++ ) { // グループメンバーの処理
    420                                                String[] grpMember = dstInit.clone();
    421                                                grpMember[IDX_GROUP_ID]   = dstBuf[i].substring( PreFixGroup.length() ); // グループID
    422                                                grpMember[IDX_GROUP_NAME] = groupUsers[j][GE33_GNAME];          // グループ名
    423                                                grpMember[IDX_DST_ID]     = groupUsers[j][GE33_ADDRESS];        // 宛先ID
    424                                                grpMember[IDX_DST_NAME]   = groupUsers[j][GE33_MNAME];          // 宛先名
    425                                                if( groupUsers[j][GE33_ADDRESS].contains( "@" ) ) {             // メールアドレスがセットされる場合
    426                                                        grpMember[IDX_DST_ADDR] = groupUsers[j][GE33_ADDRESS];  //　メールアドレス
    427                                                }
    428                                                else { // 社員IDがセットされた場合
    429                                                        String[] userAddr = getUserInfo( groupUsers[j][GE33_ADDRESS] );
    430                                                        if ( userAddr != null && userAddr.length > 0 ){
    431                                                                grpMember[IDX_DST_ADDR] = userAddr[GE35_MAIL];          //　メールアドレス
    432                                                        }
    433                                                }
    434                                                if ( checkAddr( grpMember[IDX_DST_ID], grpMember[IDX_DST_ADDR] ) ){ // アドレス構文チェック
    435                                                        grpMember[IDX_FGJ] = AbstractMailManager.FGJ_SEND_WAIT;      // 送信待
    436                                                }
    437                                                else {
    438                                                        grpMember[IDX_FGJ] = AbstractMailManager.FGJ_ADDR_ERR;       // アドレス取得エラー
    439                                                        errAddrList.add( "アドレス取得エラー。ユーザーID：" + grpMember[IDX_DST_ID] + " アドレス：" + grpMember[IDX_DST_ADDR] );
    440                                                }
    441                                                dstMap.put( groupUsers[j][GE33_ADDRESS], grpMember );
    442                                        }
    443                                }
    444                                else { // グループマスタよりメンバー取得できない場合
    445                                        String[] emptyGp = dstInit.clone();
    446                                        emptyGp[IDX_GROUP_ID] = dstBuf[i]; // グループID
    447                                        emptyGp[IDX_GROUP_NAME] = "*"; // グループID
    448                                        emptyGp[IDX_DST_ID] = "NO-MEMBER"; // 宛先ID
    449                                        dstMap.put( dstBuf[i], emptyGp );
    450                                }
    451                        }
    452                        else { // ユーザーIDの場合
    453                                String[] indMember = dstInit.clone();
    454                                indMember[IDX_DST_ID] = dstBuf[i];                                                      // 宛先ID
    455                                indMember[IDX_GROUP_ID] = "*";                                                          // グループID
    456                                indMember[IDX_GROUP_NAME] = "*";                                                        // グループID
    457                                String[] userAddr = getUserInfo( dstBuf[i] );
    458                                if ( userAddr != null && userAddr.length > 0 ){
    459                                        indMember[IDX_DST_NAME] = userAddr[GE35_NAME];                  // 宛先名
    460                                        indMember[IDX_DST_ADDR] = userAddr[GE35_MAIL];                  //　メールアドレス
    461                                        if ( checkAddr( indMember[IDX_DST_ID], userAddr[1] ) ) {
    462                                                indMember[IDX_FGJ] = AbstractMailManager.FGJ_SEND_WAIT;
    463                                        }
    464                                        else {
    465                                                indMember[IDX_FGJ] = AbstractMailManager.FGJ_ADDR_ERR;
    466                                                errAddrList.add( "アドレス取得エラー。ユーザーID：" + indMember[IDX_DST_ID] + " アドレス：" + indMember[IDX_DST_ADDR] );
    467                                        }
    468
    469                                }
    470                                else {
    471                                        indMember[IDX_FGJ] = AbstractMailManager.FGJ_ADDR_ERR; // 状況コード
    472                                }
    473                                dstMap.put( dstBuf[i], indMember );
    474                        }
    475                }
    476                 return dstMap;
    477        }
    478
    479        /**
    480         * グループマスタより、ユーザー情報を取得します。
    481         * 戻り値の配列には、ユーザーIDまたはメールアドレス、ユーザー名、グループ名が格納されています。
    482         *
    483         * @og.rev 5.5.5.1 (2012/08/07) リソース系DBID 付け忘れ対策
    484         *
    485         * @param       groupId グループID
    486         *
    487         * @return      ユーザー情報
    488         */
    489        private String[][] getGroupUsers( final String groupId ){
    490                String sysId = paramMap.get( "SYSTEM_ID" );
    491                String[] ge33SelArgs = { sysId,groupId };
    492//              String[][] ge33Datas = DBUtil.dbExecute( selGE33,ge33SelArgs,AbstractMailManager.appInfo );
    493                String[][] ge33Datas = DBUtil.dbExecute( selGE33,ge33SelArgs,AbstractMailManager.appInfo, DBID );               // 5.5.5.1 (2012/08/07)
    494
    495                if ( ge33Datas.length == 0 ) {
    496                        String errMsg = "グループ情報取得できません。グループID：" + groupId ;
    497                        if( "true".equals( paramMap.get( "ADDR_CHECK" ) ) ){
    498                                throw new RuntimeException( errMsg );
    499                        }
    500                        else {
    501                                errAddrList.add( errMsg );
    502                        }
    503                }
    504                return ge33Datas;
    505        }
    506
    507        /**
    508         * メール送信ホストを返します。
    509         * GE31のJOKEN(振り分け条件)を元に、GE37テーブルの HOST を取得します。
    510         * 振り分け条件が未設定の場合は、システム定数のCOMMON_MAIL_SERVER を使用します。
    511         *
    512         * (初期値:システム定数のCOMMON_MAIL_SERVER[={@og.value org.opengion.hayabusa.common.SystemData#COMMON_MAIL_SERVER}])。
    513         *
    514         * @og.rev 5.6.6.0 (2013/07/05)
    515         *
    516         * @return      メール送信ホスト
    517         */
    518        public String getHost(){
    519                return host;
    520        }
    521
    522        /**
    523         * メール送信ポート番号を返します
    524         * GE31のJOKEN(振り分け条件)を元に、GE37テーブルの PORT を取得します。
    525         * 振り分け条件が未設定の場合は、システム定数のSMTP_PORT を使用します。
    526         *
    527         * (初期値:システム定数のSMTP_PORT[={@og.value org.opengion.hayabusa.common.SystemData#SMTP_PORT}])。
    528         *
    529         * @og.rev 5.6.6.0 (2013/07/05)
    530         *
    531         * @return      メール送信ポート番号
    532         */
    533        public String getSmtpPort(){
    534                return smtpPort;
    535        }
    536
    537        /**
    538         * メール送信時認証有無を返します
    539         * GE31のJOKEN(振り分け条件)を元に、GE37テーブルの AUTH を取得します。
    540         * 振り分け条件が未設定の場合は、システム定数のMAIL_SEND_AUTH を使用します。
    541         *
    542         * (初期値:システム定数のMAIL_SEND_AUTH[={@og.value org.opengion.hayabusa.common.SystemData#MAIL_SEND_AUTH}])。
    543         *
    544         * @og.rev 5.6.6.0 (2013/07/05)
    545         *
    546         * @return      メール送信時認証有無
    547         */
    548        public String getAuth(){
    549                return auth;
    550        }
    551
    552        /**
    553         * メール送信認証ポートを返します。
    554         * 「POP_BEFORE_SMTP」認証を行う場合に、POPサーバーに接続するポート番号を返します。
    555         * GE37テーブルに指定するカラムはありません。
    556         * 初期値は、システム定数のMAIL_SEND_AUTH_PORT を使用します。
    557         *
    558         * (初期値:システム定数のMAIL_SEND_AUTH_PORT[={@og.value org.opengion.hayabusa.common.SystemData#MAIL_SEND_AUTH_PORT}])。
    559         *
    560         * @og.rev 5.8.1.1 (2014/11/14) メール送信時認証「POP_BEFORE_SMTP」追加
    561         *
    562         * @return      メール送信認証ポート
    563         */
    564        public String getAuthPort(){
    565                return authPort;
    566        }
    567
    568        /**
    569         * メール送信認証ユーザを返します
    570         * GE31のJOKEN(振り分け条件)を元に、GE37テーブルの AUTHUSER を取得します。
    571         * 振り分け条件が未設定の場合は、システム定数のMAIL_SEND_AUTH_USER を使用します。
    572         *
    573         * (初期値:システム定数のMAIL_SEND_AUTH_USER[={@og.value org.opengion.hayabusa.common.SystemData#MAIL_SEND_AUTH_USER}])。
    574         *
    575         * @og.rev 5.6.6.0 (2013/07/05)
    576         *
    577         * @return      メール送信認証ユーザ
    578         */
    579        public String getAuthUser(){
    580                return authUser;
    581        }
    582
    583        /**
    584         * メール送信認証パスワードを返します
    585         * GE31のJOKEN(振り分け条件)を元に、GE37テーブルの AUTHPASS を取得します。
    586         * 振り分け条件が未設定の場合は、システム定数のMAIL_SEND_AUTH_PASSWORD を使用します。
    587         *
    588         * (初期値:システム定数のMAIL_SEND_AUTH_PASSWORD[={@og.value org.opengion.hayabusa.common.SystemData#MAIL_SEND_AUTH_PASSWORD}])。
    589         *
    590         * @og.rev 5.6.6.0 (2013/07/05)
    591         *
    592         * @return      メール送信認証パスワード
    593         */
    594        public String getAuthPass(){
    595                return authPass;
    596        }
    597
    598        /**
    599         * メール送信時にSTARTTLSの暗号化を行うかを指定します。
    600         * 現在はシステム定数のMAIL_SEND_USE_STARTTLSをそのまま使用します。
    601         *
    602         * (初期値:システム定数のMAIL_SEND_AUTH_PASSWORD[={@og.value org.opengion.hayabusa.common.SystemData#MAIL_SEND_USE_STARTTLS}])。
    603         *
    604         * @og.rev 5.9.29.2 (2018/02/16)
    605         *
    606         * @return      メール送信時TLS利用有無
    607         */
    608        public boolean getUseTLS(){
    609                return useTLS;
    610        }
    611
    612        /**
    613         * アドレスの構文チェックを行います、合法の場合は'true'(取得できた)、違法の場合は'false'(有効アドレス取得できず)を返します。
    614         *
    615         * @param   userId  ユーザーID
    616         * @param   address アドレス
    617         *
    618         * @return  アドレスの構文チェック結果(true:取得/false:取得できず)
    619         */
    620        private boolean checkAddr( final String userId, final String address ) {
    621                boolean rtn = true;
    622                try {
    623                        new InternetAddress( address );
    624                }
    625                catch ( AddressException aep ) {
    626                        if ( "true".equals( paramMap.get( "ADDR_CHECK" ) ) ) {
    627                                String errMsg = "ユーザーメールアドレスエラー。ユーザーID：" + userId + " アドレス：" + address;
    628                                throw new RuntimeException( errMsg,aep );
    629                        }
    630                        rtn = false;
    631                }
    632                return rtn;
    633        }
    634
    635        /**
    636         * 引数の配列から文書を合成します。
    637         * src[0]に配列には定数文字列、src[1]にはパラメータ
    638         *
    639         * @param       src     引数の配列
    640         *
    641         * @return      合成された文章
    642         */
    643        private String marge( final String[][] src ){
    644                StringBuilder rtnBuf = new StringBuilder();
    645                String rtn;
    646                if ( src != null ){
    647                        int len = src[1].length;
    648                        for(int i=0; i< len; i++) {
    649                                rtnBuf.append( src[0][i] );
    650                                rtnBuf.append( paramMap.get( src[1][i] ) );
    651                        }
    652                        rtnBuf.append( src[0][len] );
    653                        rtn = rtnBuf.toString();
    654                }
    655                else {
    656                        rtn = null;
    657                }
    658
    659                return rtn;
    660        }
    661
    662        /**
    663         * メールでのみ有効な予約語関係の処理を行います。
    664         *
    665         * LINK.ParamXはURLチェックを付加したURLを作成するための予約語です。
    666         * {&#064;LINK.PARAMx [keyStr]} PARAMxをURLとして、URLチェックを付加したものを返します。
    667         *
    668         * @param key
    669         * @return 変換後文字列
    670         */
    671        private String getReservedValue( final String key ) {
    672                if( key == null ) { return ""; }
    673
    674                String rtn="" ;
    675                int adrs = key.indexOf( '.' );
    676                if( adrs > 0 ) {
    677                        String subKey = key.substring( adrs+1 );
    678
    679                        // Link.利用頻度が低いため、この中で処理してしまう
    680                        if( key.startsWith( "LINK." ) ) {
    681                                String[] vals = StringUtil.csv2Array( subKey,' ' );
    682                                String prm0 = vals[0] ;
    683                                String prm1 = (vals.length >= 2) ? vals[1] : null ;
    684
    685                                rtn = paramMap.get( prm0 );
    686
    687                                if( prm1 != null && prm1.startsWith( "@" ) ) {
    688                                        prm1 = paramMap.get( prm1.substring(1) );
    689                                }
    690
    691                                HybsCryptography criptCls = null;
    692                                if( prm1 != null && prm1.length() > 0 ){
    693                                        criptCls = new HybsCryptography( prm1 );
    694                                }
    695                                //ユーザ指定なし、30日間有効のURLを作成
    696                                rtn = XHTMLTag.addURLCheckKey( rtn, HybsSystem.URL_CHECK_KEY, "*", System.currentTimeMillis() + 1000*60*60*24*30, criptCls );
    697                        }
    698                }
    699                else {
    700                        rtn = paramMap.get(key);
    701                }
    702                return rtn;
    703        }
    704
    705        /**
    706         * 宛先(TO、CC、BCC)のID、名前、メールアドレスをパラメータマップにセットします。
    707         *
    708         */
    709        private void setDstWord() {
    710                StringBuilder to_id    = new StringBuilder();
    711                StringBuilder to_name  = new StringBuilder();
    712                StringBuilder to_addr  = new StringBuilder();
    713                StringBuilder cc_id    = new StringBuilder();
    714                StringBuilder cc_name  = new StringBuilder();
    715                StringBuilder cc_addr  = new StringBuilder();
    716                StringBuilder bcc_id   = new StringBuilder();
    717                StringBuilder bcc_name = new StringBuilder();
    718                StringBuilder bcc_addr = new StringBuilder();
    719                int kbn;
    720                for( String dstId : mailDstMap.keySet() ) {
    721                        kbn = Integer.parseInt( mailDstMap.get( dstId )[IDX_DST_KBN]);
    722                        switch( kbn ) {
    723                                case KBN_TO:
    724                                        to_id.append( ',' ).append( dstId );
    725                                        to_name.append( ',' ).append( mailDstMap.get( dstId )[IDX_DST_NAME] );
    726                                        to_addr.append( ',' ).append( mailDstMap.get( dstId )[IDX_DST_NAME] );
    727                                        to_addr.append( '<' ).append( mailDstMap.get( dstId )[IDX_DST_ADDR] ).append( ">" );
    728                                        break;
    729                                case KBN_CC:
    730                                        cc_id.append( ',' ).append( dstId );
    731                                        cc_name.append( ',' ).append( mailDstMap.get( dstId )[IDX_DST_NAME] );
    732                                        cc_addr.append( ',' ).append( mailDstMap.get( dstId )[IDX_DST_NAME] );
    733                                        cc_addr.append( '<' ).append( mailDstMap.get( dstId )[IDX_DST_ADDR] ).append( ">" );
    734                                        break;
    735                                case KBN_BCC:
    736                                        bcc_id.append( ',' ).append( dstId );
    737                                        bcc_name.append( ',' ).append( mailDstMap.get( dstId )[IDX_DST_NAME] );
    738                                        bcc_addr.append( ',' ).append( mailDstMap.get( dstId )[IDX_DST_NAME] );
    739                                        bcc_addr.append( '<' ).append( mailDstMap.get( dstId )[IDX_DST_ADDR] ).append( ">" );
    740                                        break;
    741                                default:
    742                                        String errMsg = "このアドレス区分がサポートされません。区分：" + kbn;
    743                                        throw new RuntimeException( errMsg );
    744                        }
    745                }
    746                // 予約語マップに追加します。
    747                paramMap.put( "TO_ID"   , ( to_id.length()    > 0 ) ? to_id.toString().substring( 1 ):"" );
    748                paramMap.put( "TO_NAME" , ( to_name.length()  > 0 ) ? to_name.toString().substring( 1 ):"" );
    749                paramMap.put( "TO_ADDR" , ( to_addr.length()  > 0 ) ? to_addr.toString().substring( 1 ):"" );
    750                paramMap.put( "CC_ID"   , ( cc_id.length()    > 0 ) ? cc_id.toString().substring( 1 ):"" );
    751                paramMap.put( "CC_NAME" , ( cc_name.length()  > 0 ) ? cc_name.toString().substring( 1 ):"" );
    752                paramMap.put( "CC_ADDR" , ( cc_addr.length()  > 0 ) ? cc_addr.toString().substring( 1 ):"" );
    753                paramMap.put( "BCC_ID"  , ( bcc_id.length()   > 0 ) ? bcc_id.toString().substring( 1 ):"" );
    754                paramMap.put( "BCC_NAME", ( bcc_name.length() > 0 ) ? bcc_name.toString().substring( 1 ):"" );
    755                paramMap.put( "BCC_ADDR", ( bcc_addr.length() > 0 ) ? bcc_addr.toString().substring( 1 ):"" );
    756        }
    757
    758        /**
    759         * 社員マスタより名前、メールアドレスを取得します。
    760         * 戻り値 rtn[0]:ユーザー名、 rtn[1]:ユーザーメールアドレス
    761         *
    762         * @og.rev 4.3.6.6 (2009/05/15) メールアドレスが直接指定された場合に対応
    763         * @og.rev 5.5.5.1 (2012/08/07) リソース系DBID 付け忘れ対策
    764         *
    765         * @param   userId  ユーザーID
    766         *
    767         * @return      配列文字列(rtn[0]:ユーザー名、 rtn[1]:ユーザーメールアドレス)
    768         */
    769        private String[] getUserInfo( final String userId ){
    770                String[] rtn = null;
    771
    772                if ( userId.contains( "@" ) ) {
    773                        rtn = new String[2];
    774                        rtn[0] = "";
    775                        rtn[1] = userId;
    776                }
    777                else {
    778                        String[] ge35SelArgs = { userId };
    779//                      String[][] ge35Datas = DBUtil.dbExecute( selGE35,ge35SelArgs,AbstractMailManager.appInfo );
    780                        String[][] ge35Datas = DBUtil.dbExecute( selGE35,ge35SelArgs,AbstractMailManager.appInfo, DBID );               // 5.5.5.1 (2012/08/07)
    781                        if ( ge35Datas.length > 0) {
    782                                rtn = ge35Datas[0];
    783                        }
    784                        else {
    785                                String errMsg = "ユーザー情報取得できません。ユーザーID：" + userId ;
    786                                if( "true".equals( paramMap.get( "ADDR_CHECK" ) ) ){
    787                                        throw new RuntimeException( errMsg );
    788                                }
    789                                else {
    790                                        errAddrList.add( errMsg );
    791                                }
    792                        }
    793                }
    794                return rtn;
    795        }
    796}