001package org.opengion.plugin.cloud; 002 003 // import java.io.IOException; // 5.9.26.0 (2017/11/02) SendGridApiを利用して、メール送信を行う 004import java.text.SimpleDateFormat; 005 // import java.util.ArrayList; 006import java.util.Calendar; 007import java.util.Date; 008// import java.util.HashMap; 009import java.util.List; 010// import java.util.Map; 011import java.util.concurrent.ConcurrentMap; // 5.9.26.0 (2017/11/02) Ver6 012 013import org.opengion.fukurou.system.DateSet; // 5.9.26.0 (2017/11/02) 014import org.opengion.fukurou.db.DBUtil; 015 // import org.opengion.hayabusa.common.HybsSystem; 016 // import org.opengion.hayabusa.common.HybsSystemException; // 5.9.26.0 (2017/11/02) SendGridApi 017import org.opengion.hayabusa.mail.MailManager_DB; 018// import org.opengion.hayabusa.mail.MailPattern; 019 020 // 5.9.26.0 (2017/11/02) とりあえず、拡張jar は入れていません。 021 // つまり、動きません。 022 // import com.fasterxml.jackson.core.JsonProcessingException; 023 // import com.fasterxml.jackson.databind.ObjectMapper; 024 // import com.sendgrid.Method; 025 // import com.sendgrid.Request; 026 // import com.sendgrid.SendGrid; 027 028/** 029 * パッチによるメール送信の実装クラスです。 030 * 送信デーモンはパラメータテーブル(GE30)を監視して、新規のデータが登録されたら、 031 * そのデータをパラメータとしてメール合成処理メソッドに渡して合成を行って送信します。 032 * 最後に、処理結果を受取って、パラメータテーブルの状況フラグを送信済/送信エラーに更新します。 033 * エラーが発生した場合、エラーテーブルにエラーメッセージを書き込みます。 034 * 035 * hayabusa.mailの標準クラスを継承して作成しています。 036 * 基本的な動作は同じですが、メール送信にSMTPではなくsendGridのAPIを利用します。 037 * MAIL_SENDGRID_APIKEYをシステムリソースとして登録する必要があります。 038 * 039 * 一時的に利用できなくなる事を想定して、 040 * 一定時間の間(ハードコーディングで10分としている)はエラーが発生しても再送を試みるようにします。 041 * 042 * このクラスをコンパイルするためにはsendgrid-java-4.1.1.jar,java-http-client-4.1.0.jarが必要です。 043 * 実行にはhamcrest-core-1.1.jar,httpclient-4.5.2.jar,httpcore-4.4.4.jar,mockito-core-1.10.19.jar,objenesis-2.1.jar 044 * ,jackson-annotations-2.5.3.jar,jackson-core-2.5.3.jar,jackson-databind-2.5.3.jarが必要です。 045 * 046 * @og.group メールモジュール 047 * 048 * @og.rev 5.9.26.0 (2017/11/02) 新規作成 049 * @author T.OTA 050 * @since JDK1.7 051 * 052 */ 053public class MailManager_DB_SendGridAPI extends MailManager_DB { 054 // 6.8.5.0 (2018/01/09) PMD Variables that are final and static should be all capitals。selGE30DYSET → SQL_GE30 055 private static final String SQL_GE30 = "SELECT DYSET FROM GE30 WHERE UNIQ = ?"; // 2017/10/27 ADD 登録時刻の取得 056// // SendGridのAPIキー 057// private static final String SENDGRID_APIKEY = HybsSystem.sys("MAIL_SENDGRID_APIKEY"); 058// // メール送信先のtoリスト 059// private final List<String> toList = new ArrayList<String>(); 060// // メール送信先のccリスト 061// private final List<String> ccList = new ArrayList<String>(); 062// // メール送信先のbccリスト 063// private final List<String> bccList = new ArrayList<String>(); 064 065 /** 066 * デフォルトコンストラクター 067 * 068 * @og.rev 6.9.7.0 (2018/05/14) PMD Each class should declare at least one constructor 069 */ 070 public MailManager_DB_SendGridAPI() { super(); } // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。 071 072 /** 073 * バッチより呼出のメインメソッドです。 074 * パラメータテーブル(GE30)を監視します。 075 * 新規のデータが登録されたら、メール文を合成して送信を行います。 076 * エラーが発生した場合、エラーテーブルにエラーメッセージを書き込みます。 077 * 078 * @og.rev 6.8.5.0 (2018/01/09) PMD Variables that are final and static should be all capitals。selGE30DYSET → SQL_GE30 079 * 080 * @param systemId システムID 081 */ 082 @Override 083 public void sendDBMail( final String systemId ){ 084 // パラメータテーブルよりバッチでセットしたデータを取得します。 085 final String[][] ge30datas = DBUtil.dbExecute( SEL_GE30, new String[]{ systemId, DateSet.getDate( "yyyyMMddHHmmss" ) }, APP_INFO, DBID ); // 5.9.18.0 (2017/03/02) 086 087 // 2017/10/27 ADD SendGrid利用の追加対応 088 String timePre1Hour = ""; 089 // タイムスタンプの設定 090 timePre1Hour = getTimePre1Hour(); 091 092 final int ge30Len = ge30datas.length; 093 094 for( int i=0; i < ge30Len; i++ ) { 095 String fgj = SNED_OK; 096 try { 097 final ConcurrentMap<String, String> initParam = makeParamMap( systemId, ge30datas[i] ); // 5.9.26.0 (2017/11/02) Ver6 098 create( initParam ); 099 send(); // 合成されたメール文書、宛先で送信処理を行います。 100 errMsgList.addAll( getErrList() ); 101 } 102 catch( final RuntimeException rex ) { 103 fgj = SNED_NG; 104 errMsgList.add( "メール送信失敗しました。パラメータキー:" + ge30datas[i][GE30_UNIQ] + " " + rex.getMessage() ); 105 } 106 finally { 107 if(fgj != SNED_NG){ 108 commitParamTable( ge30datas[i][GE30_UNIQ], fgj ); 109 }else{ 110 // エラーレコードの登録日時を取得 111 final String[][] rec = DBUtil.dbExecute( SQL_GE30, new String[]{ge30datas[i][GE30_UNIQ]}, APP_INFO, DBID); 112 final String DYSET = rec[0][0]; 113 114 if(DYSET.compareTo(timePre1Hour) < 0){ 115 // 登録から一定時間以上のエラーをエラーに更新 116 commitParamTable( ge30datas[i][GE30_UNIQ], fgj ); 117 } 118 else { 119 // それ以外は再送を試みる 120 commitParamTable( ge30datas[i][GE30_UNIQ], "1" ); 121 } 122 } 123 124 if ( ! errMsgList.isEmpty() ) { 125 writeErrorTable( ge30datas[i][GE30_UNIQ], systemId, errMsgList ); 126 errMsgList.clear(); 127 } 128 } 129 } 130 } 131 132 /** 133 * 1時間前のタイムスタンプを取得。 134 * 135 * @return タイムスタンプ(1時間前) 136 */ 137 private String getTimePre1Hour(){ 138 final Date date = new Date(); 139 final Calendar call = Calendar.getInstance(); 140 final SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss"); 141 call.setTime(date); 142 // sendGridが一時的に使えなくなる場合を考慮 143 // 10分間は再送を試みる 144 call.add(Calendar.MINUTE, -10); 145 146 return sdf.format(call.getTime()); 147 } 148 149 // 5.9.26.0 (2017/11/02) とりあえず、拡張jar は入れていません。 150 // /** 151 // * SendGridApiを利用して、メール送信を行うメソッドです。 152 // * 153 // */ 154 // @Override 155 // public void send(){ 156 // // 宛先 157 // List<String> invalidAddrBuf = new ArrayList<String>(); 158 // setMailDst(invalidAddrBuf); 159 // 160 // try{ 161 // SendGrid sg = new SendGrid(SENDGRID_APIKEY); 162 // 163 // Request request = new Request(); 164 // request.setMethod(Method.POST); 165 // request.setEndpoint("mail/send"); 166 // 167 // // SengGrid向けJsonの設定 168 // request.setBody(makeJson()); 169 // 170 // // メール送信要求 171 // sg.api(request); 172 // 173 // // 送信結果を履歴テーブル、宛先テーブルにセットします。 174 // commitMailDB(); 175 // 176 // }catch(IOException e){ 177 // String errMsg = "送信時にエラー発生しました。" + e.getMessage(); 178 // throw new RuntimeException( errMsg,e ); 179 // } 180 // } 181 182// /** 183// * SendGrid向けのJsonを生成します。 184// * 185// * @og.rev 6.9.8.0 (2018/05/28) FindBugs:private メソッドは決して呼び出されない 186// * 187// * @return JSONデータ 188// */ 189// @SuppressWarnings(value={"rawtypes"}) 190// private String makeJson(){ 191// String rtnJson = ""; 192// final Map<Object,Object> jsonMap = new HashMap<Object, Object>(); 193// // 送信先の設定 194// final Map<String,List<Map<String,String>>> sendMap = new HashMap<String,List<Map<String,String>>>(); 195// sendMap.put("to", setSendList(toList)); 196// if(!ccList.isEmpty()){ 197// sendMap.put("cc", setSendList(ccList)); 198// } 199// if(!bccList.isEmpty()){ 200// sendMap.put("bcc", setSendList(bccList)); 201// } 202// jsonMap.put("personalizations", new Map[]{sendMap}); // 警告: [rawtypes] raw型が見つかりました: Map 203// // タイトル 204// jsonMap.put("subject",getTitle()); 205// // 送信元 206// jsonMap.put("from", setMap("email",getFromAddr())); 207// // 内容 208// final Map<String,String> contentMap = new HashMap<String,String>(); 209// contentMap.put("type","text/plain"); 210// contentMap.put("value",getContent()); 211// jsonMap.put("content", new Map[]{contentMap}); // 警告: [rawtypes] raw型が見つかりました: Map 212// 213// // 5.9.26.0 (2017/11/02) とりあえず、拡張jar は入れていません。 214///*********** 215// // ObjectMapper mapper = new ObjectMapper(); 216// // 217// // try{ 218// // rtnJson = mapper.writeValueAsString(jsonMap); 219// // }catch(JsonProcessingException e){ 220// // String errMsg = "JSONの生成に失敗しました。" + e; 221// // throw new HybsSystemException(errMsg); 222// // } 223//*************/ 224// return rtnJson; 225// } 226 227// /** 228// * Map格納用メソッド。 229// * 230// * @og.rev 6.9.8.0 (2018/05/28) FindBugs:private メソッドは決して呼び出されない 231// * 232// * @param val1 Mapにセットするキー 233// * @param val2 Mapにセットする値 234// * @return マップ 235// */ 236// private Map<Object,Object> setMap(final Object val1, final Object val2){ 237// final Map<Object,Object> rtnMap = new HashMap<Object,Object>(); 238// rtnMap.put(val1,val2); 239// return rtnMap; 240// } 241 242// /** 243// * メール送信先リストをJSON用リストに設定。 244// * 245// * @og.rev 6.9.8.0 (2018/05/28) FindBugs:private メソッドは決して呼び出されない 246// * 247// * @param list メール送信先リスト 248// * @return JSON用リスト 249// */ 250// private List<Map<String,String>> setSendList(final List<String> list){ 251// // toリスト 252// final List<Map<String,String>> rtnList = new ArrayList<Map<String,String>>(); 253// for(final String str: list){ 254// final Map<String,String> map = new HashMap<String,String>(); 255// map.put("email", str); 256// rtnList.add(map); 257// } 258// return rtnList; 259// } 260 261// /** 262// * 宛先マップを元に、送信オブジェクトに宛先をセットします。 263// * セットする際に、アカウントエラーとなっているアドレスを除外します。 264// * 宛先が存在しない場合、例外を投げます。 265// * 266// * 計算方法は親クラスのprivateメソッドを流用。 267// * 値はクラス変数のリストに格納するように変更しています。 268// * 269// * @og.rev 6.9.8.0 (2018/05/28) FindBugs:private メソッドは決して呼び出されない 270// * 271// * @param invalidAddr 宛先のリスト 272// */ 273// private void setMailDst( final List<String> invalidAddr ){ 274// 275// final Map<Integer, List<String>> tempMap = new HashMap<Integer, List<String>>(); 276// tempMap.put( Integer.valueOf( MailPattern.KBN_TO ), toList ); 277// tempMap.put( Integer.valueOf( MailPattern.KBN_CC ), ccList ); 278// tempMap.put( Integer.valueOf( MailPattern.KBN_BCC ), bccList ); 279// 280//// final ConcurrentMap<String, String[]> tmp = getMailDstMap(); 281// for( final String dstId : getMailDstMap().keySet()) { 282// String[] dstInfo = getMailDstMap().get( dstId ); 283// final Integer kbn = Integer.valueOf( dstInfo[MailPattern.IDX_DST_KBN] ); 284// if( !invalidAddr.contains( dstInfo[MailPattern.IDX_DST_ADDR] ) 285// && !FGJ_ADDR_ERR.equals( dstInfo[MailPattern.IDX_FGJ] )){ 286// dstInfo[MailPattern.IDX_FGJ] = FGJ_SEND_OVER; 287// 288// final String name = dstInfo[MailPattern.IDX_DST_NAME]; 289// if( name != null && name.length() > 0 ) { 290// tempMap.get( kbn ).add( dstInfo[MailPattern.IDX_DST_NAME] + "<"+ dstInfo[MailPattern.IDX_DST_ADDR] + ">" ); 291// } 292// else { 293// tempMap.get( kbn ).add( dstInfo[MailPattern.IDX_DST_ADDR] ); 294// } 295// } 296// else { 297// if( FGJ_SEND_OVER.equals( dstInfo[MailPattern.IDX_FGJ] ) ) { 298// dstInfo[MailPattern.IDX_FGJ] = FGJ_ACNT_ERR; 299// } 300// } 301// } 302// 303// // 宛先が全部無効の場合、例外を投げます 304// if( toList.isEmpty() && ccList.isEmpty() && bccList.isEmpty()){ 305// final String errMsg = "宛先のメールアドレスが有効ではありません。" 306// + "TO , CC , BCC のいづれにもアドレスが設定されていません。"; 307// throw new RuntimeException( errMsg ); 308// } 309// } 310 311 /** 312 * エラーテーブルにエラーメッセージを登録します。 313 * 親のprivateメソッドを流用。エラーメールの送信は行いません。 314 * 315 * @param paraKey パラメータキー(GE36.PARA_KEY) 316 * @param systemId システムID 317 * @param emList エラーメッセージリスト 318 * 319 */ 320 private void writeErrorTable( final String paraKey, final String systemId, final List<String> emList ){ 321 String[] insGE36Args = new String[6]; 322 insGE36Args[GE36_PARA_KEY] = paraKey; 323 insGE36Args[GE36_DYSET] = DateSet.getDate( "yyyyMMddHHmmss" ); 324 insGE36Args[GE36_USRSET] = "DAEMON"; 325 insGE36Args[GE36_PGUPD] = "DAEMON"; 326 insGE36Args[GE36_SYSTEM_ID] = systemId; 327 for( int i=0; i< emList.size(); i++ ){ 328 insGE36Args[GE36_ERRMSG] = trim( emList.get( i ), 4000); 329 DBUtil.dbExecute( INS_GE36, insGE36Args, APP_INFO, DBID ); 330 } 331 } 332}