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