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 org.opengion.fukurou.system.DateSet;                                                     // 6.4.2.0 (2016/01/29)
020import org.opengion.fukurou.util.StringUtil;                                            // 5.9.1.3 (2015/10/30)
021import org.opengion.fukurou.db.DBUtil;
022import org.opengion.fukurou.db.ApplicationInfo;
023import org.opengion.fukurou.mail.MailTX;
024import static org.opengion.fukurou.util.StringUtil.nval;
025import static org.opengion.fukurou.system.HybsConst.BUFFER_MIDDLE;      // 6.1.0.0 (2014/12/26) refactoring
026
027import org.opengion.hayabusa.common.HybsSystem;
028
029import org.opengion.fukurou.db.ConnectionFactory;                                       // 5.9.26.0 (2017/11/02)
030import org.opengion.fukurou.db.Transaction;                                                     // 5.9.26.0 (2017/11/02)
031import org.opengion.fukurou.db.TransactionReal;                                         // 5.9.26.0 (2017/11/02)
032import org.opengion.fukurou.db.DBFunctionName;                                          // 5.9.26.0 (2017/11/02)
033
034import java.util.List;
035import java.util.ArrayList;
036import java.util.HashMap;
037import java.util.Map;
038import java.util.concurrent.ConcurrentMap;                                                      // 6.4.3.3 (2016/03/04)
039import java.util.stream.Collectors;                                                                     // 6.4.1.1 (2016/01/16)
040
041import javax.mail.Address;
042import javax.mail.SendFailedException;
043import javax.mail.internet.InternetAddress;
044
045/**
046 * タグ mailSender2 及びバッチによる送信の共通処理部分を実装しています。
047 * 送信タグ mailSender2 もしくは送信デーモンからパラメータを受取ります。
048 * パラメータ中の定型文ID及びシステムIDで定型文マスタよりメールの定型文を取得して、
049 * パラメータ値とマージしてメール文を合成します。同時に、宛先にセットした社員ID、
050 * グループIDと定型文の宛先設定に基づき、社員マスタとグループマスタよりメールアドレス
051 * 情報を取得して送信を行います。
052 * エラーがなければ送信した内容を履歴テーブル、宛先テーブルに書き込みます。
053 * 最後に本処理の呼出元に送信結果、エラーメッセージを返します。
054 *
055 * @og.group メールモジュール
056 *
057 * @version  4.0
058 * @author   Sen.Li
059 * @since    JDK1.6
060 */
061public class DefaultMailManager {
062        // 5.2.0.0 (2010/09/01) Ver4互換モード対応
063        private static final String CONTENTS = HybsSystem.sysBool( "VER4_COMPATIBLE_MODE" ) ? "CONTENT" : "CONTENTS";
064
065        // 5.9.26.0 (2017/11/02) DB共通化のため、DBFunctionNameを使用して、シーケンスを取得するように変更
066
067        // 5.0.3.0 (2009/11/04) CONTENT ⇒ CONTENTS
068        // 5.2.0.0 (2010/09/01) Ver4互換モード対応
069        // 6.4.1.1 (2016/01/16) insGE32 → INS_GE32 , insGE34 → INS_GE34 refactoring
070        private static final String     INS_GE32                = "INSERT INTO GE32(YKNO,PARA_KEY,PTN_ID,FROM_ADDR,TITLE,"+CONTENTS+",ATTACH1,ATTACH2,ATTACH3,ATTACH4,ATTACH5,DYSET,USRSET,PGUPD,SYSTEM_ID,FGJ)"
071                                                                                        + " VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,'1')";
072        private static final String INS_GE34            = "INSERT INTO GE34(YKNO,DST_ID,GROUP_ID,DST_NAME,DST_ADDR,DST_KBN,FGJ,DYSET,USRSET,PGUPD)"
073                                                                                        + " VALUES(?,?,?,?,?,?,?,?,?,?)";
074        /** フラグ定数 {@value} */
075        protected static final String FGJ_SEND_WAIT     = "0";
076        /** フラグ定数 {@value} */
077        protected static final String FGJ_SEND_OVER     = "1";
078        /** フラグ定数 {@value} */
079        protected static final String FGJ_ADDR_ERR      = "7";
080        /** フラグ定数 {@value} */
081        protected static final String FGJ_ACNT_ERR      = "8";
082
083        // 内部データのカラム番号(履歴テーブル)
084        private static final int GE32_YKNO              = 0 ;
085        private static final int GE32_PARAKEY   = 1 ;
086        private static final int GE32_PTN_ID    = 2;
087        private static final int GE32_FROM_ADDR = 3;
088        private static final int GE32_TITLE     = 4;
089        private static final int GE32_CONTENTS  = 5;            // 5.0.3.0 (2009/11/04) CONTENT ⇒ CONTENTS
090        private static final int GE32_ATTACH1   = 6;
091        private static final int GE32_ATTACH2   = 7;
092        private static final int GE32_ATTACH3   = 8;
093        private static final int GE32_ATTACH4   = 9;
094        private static final int GE32_ATTACH5   = 10;
095        private static final int GE32_DYSET             = 11;
096        private static final int GE32_USRSET    = 12;
097        private static final int GE32_PGUPD     = 13;
098        private static final int GE32_SYSTEM_ID = 14;
099        // 内部データのカラム番号(履歴テーブル)
100        private static final int GE34_YKNO              = 0 ;
101        private static final int GE34_DST_ID    = 1 ;
102        private static final int GE34_GROUP_ID  = 2 ;
103        private static final int GE34_DST_NAME  = 3 ;
104        private static final int GE34_DST_ADDR  = 4 ;
105        private static final int GE34_DST_KBN   = 5 ;
106        private static final int GE34_FGJ               = 6 ;
107        private static final int GE34_DYSET             = 7 ;
108        private static final int GE34_USRSET    = 8 ;
109        private static final int GE34_PGUPD             = 9 ;
110 //     private static String           host            = HybsSystem.sys( "COMMON_MAIL_SERVER" );
111        private static String           charset         = HybsSystem.sys( "MAIL_DEFAULT_CHARSET" );
112 //     private static String           smtpPort        = HybsSystem.sys( "SMTP_PORT" );                                // 5.4.3.2 (2012/01/06)
113 //     private static String           auth            = HybsSystem.sys( "MAIL_SEND_AUTH" );                   // 5.4.3.2 (2012/01/06)
114 //     private static String           authUser        = HybsSystem.sys( "MAIL_SEND_AUTH_USER" );              // 5.4.3.2 (2012/01/06)
115 //     private static String           authPass        = HybsSystem.sys( "MAIL_SEND_AUTH_PASSWORD" );  // 5.4.3.2 (2012/01/06)
116        private boolean                         debugFlag       ;
117        private final List<String>      errAddrList = new ArrayList<>();
118        private static final int MAX_RETRY              = 3 ;   // メールアドレスエラー発生した場合、メール再送回数
119
120        // 5.6.6.0 (2013/07/05) host等の外部指定に対応
121        private String          host            = HybsSystem.sys( "COMMON_MAIL_SERVER" );               // 5.6.6.0 (2013/07/05)
122        private String          smtpPort        = HybsSystem.sys( "SMTP_PORT" );                                // 5.6.6.0 (2013/07/05)
123        private String          authType        = HybsSystem.sys( "MAIL_SEND_AUTH" );                   // 6.0.3.0 (2014/11/13) Ver6用キーワード変更
124        private String          authPort        = HybsSystem.sys( "MAIL_SEND_AUTH_PORT" );              // 5.8.1.1 (2014/11/14)
125        private String          authUser        = HybsSystem.sys( "MAIL_SEND_AUTH_USER" );              // 5.6.6.0 (2013/07/05)
126        private String          authPass        = HybsSystem.sys( "MAIL_SEND_AUTH_PASSWORD" );  // 5.6.6.0 (2013/07/05)
127        private boolean         useTLS          = HybsSystem.sysBool( "MAIL_SEND_USE_STARTTLS" );        // 5.9.29.2(2018/02/16) キーワードをVer5 にあわせます。
128
129        private final boolean   useSSL          = HybsSystem.sysBool( "MAIL_SEND_USE_SSL" );    // 6.3.8.0 (2015/09/11)
130
131        private String  mailTitle, mailContent, fromAddr;
132        private String[] attachFiles;
133        /** 6.4.3.1 (2016/02/12) 作成元のMapを、HashMap から ConcurrentHashMap に置き換え。  */
134        private ConcurrentMap<String, String[]> mailDstMap              ;               // 6.4.3.3 (2016/03/04)
135        /** 6.4.3.1 (2016/02/12) 作成元のMapを、HashMap から ConcurrentHashMap に置き換え。  */
136        // 6.4.3.3 (2016/03/04) ConcurrentHashMap を受け取ることを明確にするため、I/FをConcurrentMapに変更します。
137        private ConcurrentMap<String,String>    initParamMap    ;               // パラメータマップ
138        private MailTX                                                  mail                    ;
139
140        protected final String DBID = HybsSystem.sys( "RESOURCE_DBID" );                // 5.5.5.1 (2012/08/07) リソース系DBID 付け忘れ対応
141
142        /** コネクションにアプリケーション情報を追記するかどうか指定 */
143        private static final boolean USE_DB_APPLICATION_INFO  = HybsSystem.sysBool( "USE_DB_APPLICATION_INFO" ) ;
144
145        /** アプリケーション情報 */
146        // 6.4.1.1 (2016/01/16) DefaultMailManager.appInfo → DefaultMailManager.APP_INFO refactoring
147        protected static final ApplicationInfo APP_INFO;
148        static {
149                if( USE_DB_APPLICATION_INFO ) {
150                        APP_INFO = new ApplicationInfo();
151                        // ユーザーID,IPアドレス,ホスト名
152                        APP_INFO.setClientInfo( "MailModuel", HybsSystem.HOST_ADRS, HybsSystem.HOST_NAME );
153                        // 画面ID,操作,プログラムID
154                        APP_INFO.setModuleInfo( "MailModuel", "MailManager", "MailManager" );
155                }
156                else {
157                        APP_INFO = null;
158                }
159        }
160
161        /**
162         * デフォルトコンストラクター
163         *
164         * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor.
165         */
166        public DefaultMailManager() { super(); }                // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。
167
168        /**
169         * 呼出元よりパラメータマップを受取って、メールオブジェクト(mailObj)を作成します。
170         * メールオブジェクトは定型文ID及びシステムIDに基づいて定型文マスタからメールの定型文を取得して、
171         * パラメータ値とマージしてメール文の各項目を合成します。
172         * 宛先については、宛先にセットした社員ID、グループIDと定型文の宛先設定に基づき、社員マスタとグループマスタ
173         * よりメールアドレスを取得して宛先マップを作成します。
174         * まだ、添付ファイルのセット処理も行っています。
175         * 
176         * @og.rev 5.6.6.0 (2013/07/05) host等の外部設定対応
177         * @og.rev 6.0.3.0 (2014/11/13) Ver6用キーワード変更
178         * @og.rev 6.4.3.1 (2016/02/12) 作成元のMapを、HashMap から ConcurrentHashMap に置き換え。
179         * @og.rev 6.4.3.3 (2016/03/04) ConcurrentHashMap を受け取ることを明確にするため、I/FをConcurrentMapに変更します。
180         * @og.rev 5.9.15.1 (2016/12/09) エラーリストのクリア
181         * @og.rev 5.9.29.2 (2018/02/16) STARTTLS対応(キーワードをVer5 にあわせます)
182         *
183         * @param       params  パラメータのマップ
184         */
185        public void create( final ConcurrentMap<String, String> params ) {
186                initParamMap = params;                                                                                  // 6.4.3.1 (2016/02/12)
187                final MailPattern mailObj = new MailPattern( params );
188                fromAddr = mailObj.getFromAddr();
189                setAttachFiles( params.get( "ATTACH1" )
190                                          , params.get( "ATTACH2" )
191                                          , params.get( "ATTACH3" )
192                                          , params.get( "ATTACH4" )
193                                          , params.get( "ATTACH5" ) );                                          // 添付ファイルのセット
194                mailDstMap      = mailObj.getDstMap();                                                          // 6.4.3.1 (2016/02/12)
195                mailTitle       = mailObj.getTitle();
196                mailContent = mailObj.getContent();
197                errAddrList.clear();                                                                                    // 5.9.15.1 (2016/12/09)
198                errAddrList.addAll( mailObj.getErrList() );
199
200                // 5.6.6.0 (2013/07/05)
201                host            = nval( mailObj.getHost()               ,host           );
202                smtpPort        = nval( mailObj.getSmtpPort()   ,smtpPort       );
203                authType        = nval( mailObj.getAuthType()   ,authType       );              // 6.0.3.0 (2014/11/13) Ver6用キーワード変更
204                authPort        = nval( mailObj.getAuthPort()   ,authPort       );              // 5.8.1.1 (2014/11/14)
205                authUser        = nval( mailObj.getAuthUser()   ,authUser       );
206                authPass        = nval( mailObj.getAuthPass()   ,authPass       );
207//              useTLS          = mailObj.getUseTLS();                  // 5.9.29.2 (2018/02/13)
208                useTLS          = HybsSystem.sysBool( "MAIL_SEND_USE_STARTTLS" );        // 5.9.29.2(2018/02/16) キーワードをVer5 にあわせます。
209        }
210
211        /**
212         * メール送信を行うメソッドです。
213         * createメソッドより合成した内容で送信を行います。アドレスエラー発生時に、
214         * ユーザー設定(addrCheck)により再送/中止します。
215         * メールサーバーに送信して、例外"SendFailedException"をキャッチできたら、
216         * メールアカウントがエラーとなるのを分かります。そして、例外のオブジェクトから
217         * エラーとなっているアカウントを取得して宛先マップから除外して、残りのアドレスに再送できます。
218         * 送信後履歴テーブル(GE32)、宛先テーブル(GE34)に送信結果を書き込みます。
219         *
220         * @og.rev 5.4.3.2 (2012/01/06) 送信時認証対応
221         * @og.rev 6.0.3.0 (2014/11/13) Ver6用キーワード変更
222         * @og.rev 6.3.8.0 (2015/09/11) SSL接続するかどうかを指定するパラメータを追加します。
223         * @og.rev 5.9.29.2 (2018/02/16) STARTTLS対応(キーワードをVer5 にあわせます)
224         */
225        public void send() {
226                final List<String> invalidAddrBuf       = new ArrayList<>();
227                // mail = new MailTX( host, charset );
228//              mail = new MailTX( host, charset, smtpPort, authType, authPort,authUser, authPass , useSSL );                   // 6.3.8.0 (2015/09/11) SSL接続対応
229                mail = new MailTX( host, charset, smtpPort, authType, authPort,authUser, authPass, useTLS , useSSL );   // 5.9.29.2 (2019/02/16)
230                mail.setFrom( fromAddr );                       // 送信者アドレス
231                mail.setFilename( attachFiles );        // 添付ファイルをセットします。
232                mail.setSubject( mailTitle );           // メールタイトル
233                mail.setMessage( mailContent );         // メール本文
234                mail.setDebug( debugFlag );
235                setMailDst( invalidAddrBuf );           // 宛先をセットします。
236
237                // 6.4.1.1 (2016/01/16) PMD refactoring. Avoid instantiating new objects inside loops
238                // 実際は、エラー処理の中で作成しているだけなので、外に出す必要性は、薄い。
239                final StringBuilder errMsgBuf = new StringBuilder( BUFFER_MIDDLE );
240
241                // メール送信を行います。
242                int retryCount = MAX_RETRY;
243                while( retryCount > 0 ) {
244                        try {
245                                mail.sendmail();
246                        }
247                        catch( final RuntimeException rex ) {
248                                final Throwable cause = rex.getCause();
249                                if( cause instanceof SendFailedException ) {
250                                        final Address[] invAddress = ( (SendFailedException) cause ).getInvalidAddresses();
251                                        if( invAddress != null ) {
252                                                final int invCount = invAddress.length;
253                                                for( int i=0; i<invCount; i++ ) {
254                                                        invalidAddrBuf.add( ( (InternetAddress) invAddress[i] ).getAddress() );
255                                                }
256                                        }
257                                }
258                                else {
259                                        final String errMsg = "送信時にエラー発生しました。" + rex.getMessage();
260                                        throw new OgRuntimeException( errMsg,rex );
261                                }
262                        }
263
264                        if( invalidAddrBuf.isEmpty() ) {
265                                retryCount = -1;
266                        }
267                        else {
268                                // 6.4.1.1 (2016/01/16) PMD refactoring. Avoid instantiating new objects inside loops
269
270                                errMsgBuf.setLength(0);                         // new StringBuilder の代わり。
271                                final String errMsg = errMsgBuf.append( "アドレスエラー。ユーザーID:" )
272                                                                                                .append( getUserIds( invalidAddrBuf ) )
273                                                                                                .append( " アドレス:" )
274                                                                                                .append( invalidAddrBuf.stream().collect( Collectors.joining( "," ) ) )
275                                                                                                .toString();
276
277                                if( "true".equals( initParamMap.get( "ADDR_CHECK" ) ) ){
278                                        throw new OgRuntimeException( errMsg );
279                                }
280                                else {
281                                        // メールアカウントチェックしない場合、無効のメールアドレスを除いて再送します。
282                                        setMailDst( invalidAddrBuf );
283                                        retryCount--;
284                                        invalidAddrBuf.clear();
285                                        errAddrList.add( errMsg );
286                                }
287                        }
288                }
289                commitMailDB();         // 送信結果を履歴テーブル、宛先テーブルにセットします。
290        }
291
292        /**
293         * デバッグ情報の表示を行うかどうか[true/false]をセットします。
294         *
295         * @param   debug  [true:出力する/それ以外:しない]
296         */
297        public void setDebug( final boolean debug ) {
298                debugFlag = debug;
299        }
300
301        /**
302         * メール送信者アドレスをセットします。
303         *
304         * @param  from 送信者アドレス
305         */
306        public void setFromAddr( final String from ) {
307                fromAddr = from;
308        }
309
310        /**
311         * メールタイトルをセットします。
312         *
313         * @param  title メールタイトル
314         */
315        public void setTitle( final String title ) {
316                mailTitle = title;
317        }
318
319        /**
320         * メール本文をセットします。
321         *
322         * @param  content メール本文
323         */
324        public void setContent( final String content ) {
325                mailContent = content;
326        }
327
328        /**
329         * メール送信ホストをセットします。
330         * 初期値は、システム定数のCOMMON_MAIL_SERVER を使用します。
331         *
332         * (初期値:システム定数のCOMMON_MAIL_SERVER[={@og.value SystemData#COMMON_MAIL_SERVER}])。
333         * 
334         * @og.rev 5.6.6.0 (2013/07/05)
335         *
336         * @param  hostName 送信ホスト
337         */
338        public void setHost( final String hostName ) {
339                host = nval( hostName, host );
340        }
341
342        /**
343         * メール送信ポート番号をセットします。
344         * 初期値は、システム定数のSMTP_PORT を使用します。
345         *
346         * (初期値:システム定数のSMTP_PORT[={@og.value SystemData#SMTP_PORT}])。
347         * 
348         * @og.rev 5.6.6.0 (2013/07/05)
349         * 
350         * @param  port SMTPポート
351         */
352        public void setPort( final String port ) {
353                smtpPort = nval( port, smtpPort );
354        }
355
356        /**
357         * メール送信時認証有無をセットします。
358         * 認証を行う場合は「POP_BEFORE_SMTP」と指定して下さい。
359         * 認証時には認証ユーザと認証パスワードを設定する必要があります。
360         * 初期値は、システム定数のMAIL_SEND_AUTH を使用します。
361         *
362         * (初期値:システム定数のMAIL_SEND_AUTH[={@og.value SystemData#MAIL_SEND_AUTH}])。
363         * 
364         * @og.rev 6.0.3.0 (2014/11/13) Ver6用キーワード変更
365         * 
366         * @param  type 認証方式
367         */
368        public void setAuthType( final String type ) {
369                authType = nval( type, authType );
370        }
371
372        /**
373         * メール送信認証ユーザをセットします。
374         * 初期値は、システム定数のMAIL_SEND_AUTH_USER を使用します。
375         *
376         * (初期値:システム定数のMAIL_SEND_AUTH_USER[={@og.value SystemData#MAIL_SEND_AUTH_USER}])。
377         * 
378         * @og.rev 5.6.6.0 (2013/07/05)
379         * 
380         * @param  user 認証ユーザ
381         */
382        public void setAuthUser( final String user ) {
383                authUser = nval( user, authUser );
384        }
385
386        /**
387         * メール送信認証パスワードをセットします。
388         * 初期値は、システム定数のMAIL_SEND_AUTH_PASSWORD を使用します。
389         *
390         * (初期値:システム定数のMAIL_SEND_AUTH_PASSWORD[={@og.value SystemData#MAIL_SEND_AUTH_PASSWORD}])。
391         * 
392         * @og.rev 5.6.6.0 (2013/07/05)
393         * 
394         * @param  pass 認証パスワード
395         */
396        public void setAuthPass( final String pass ) {
397                authPass = nval( pass, authPass );
398        }
399
400        /**
401         * メール送信にSTARTTLSを利用するかのフラグをセットします。
402         * 初期値は、システム定数のMAIL_SEND_USE_STARTTLS を使用します。
403         *
404         * (初期値:システム定数のMAIL_SEND_AUTH_PASSWORD[={@og.value org.opengion.hayabusa.common.SystemData#MAIL_SEND_USE_STARTTLS}])。
405         *
406         * @og.rev 5.9.29.2 (2018/02/16) STARTTLS対応(キーワードをVer5 にあわせます)
407         *
408         * @param  flg TLSの利用有無
409         */
410        public void setUseTLS( final boolean flg ) {
411                useTLS = flg;
412        }
413
414        /**
415         * メール送信者アドレスを返します。
416         *
417         * @return      送信者アドレス
418         */
419        public String getFromAddr() {
420                return fromAddr;
421        }
422
423        /**
424         * メールタイトルを返します。
425         *
426         * @return      メールタイトル
427         */
428        public String getTitle() {
429                return mailTitle;
430        }
431
432        /**
433         * メール本文を返します。
434         *
435         * @return      メール本文
436         */
437        public String getContent() {
438                return mailContent;
439        }
440
441        /**
442         * 送信結果を履歴テーブル(GE32)と宛先テーブル(GE34)に登録します。
443         * 登録時に、桁数オーバーにならないように、テーブル定義の桁数を上限として、
444         * 登録前に各項目の桁数整理を行います。
445         *
446         * @og.rev 5.5.5.1 (2012/08/07) リソース系DBID 付け忘れ対策
447         * @og.rev 5.9.1.3 (2015/10/30) 4000文字カットをやめる
448         * @og.rev 6.3.9.0 (2015/11/06) Map.keySet() ではなく、Map.values() を使う様に変更。
449         * @og.rev 6.4.2.0 (2016/01/29) DateSet.getDate( String ) を利用するように修正します。
450         */
451        protected void commitMailDB(){
452                // 履歴テーブルの追加
453                String[] insGE32Args = new String[15];
454                final String ykno = getYkno();
455                insGE32Args[GE32_YKNO]          = ykno;
456                insGE32Args[GE32_PARAKEY]       = initParamMap.get( "PARAKEY" );
457                insGE32Args[GE32_PTN_ID]        = trim( initParamMap.get( "PTN_ID" ), 20 );
458                insGE32Args[GE32_FROM_ADDR] = trim( fromAddr, 100);
459                insGE32Args[GE32_TITLE]         = trim( mailTitle, 300);
460                insGE32Args[GE32_CONTENTS]      = mailContent;                                  // 5.9.1.3 (2015/10/30)
461                insGE32Args[GE32_ATTACH1]       = "";
462                insGE32Args[GE32_ATTACH2]       = "";
463                insGE32Args[GE32_ATTACH3]       = "";
464                insGE32Args[GE32_ATTACH4]       = "";
465                insGE32Args[GE32_ATTACH5]       = "";
466                if( attachFiles != null ) {
467                        final int attSize = attachFiles.length;
468                        for( int i=0; i<attSize; i++ ) {
469                                insGE32Args[6 + i] = trim( attachFiles[i], 256);
470                        }
471                }
472                insGE32Args[GE32_DYSET]  = DateSet.getDate( "yyyyMMddHHmmss" );                 // 6.4.2.0 (2016/01/29)
473                insGE32Args[GE32_USRSET] = initParamMap.get( "LOGIN_USERID" );
474                insGE32Args[GE32_PGUPD] = initParamMap.get( "PGID" );
475                insGE32Args[GE32_SYSTEM_ID] = initParamMap.get( "SYSTEM_ID" );
476                DBUtil.dbExecute( INS_GE32, insGE32Args, APP_INFO, DBID );      // 5.5.5.1 (2012/08/07)
477
478                // 宛先テーブル追加
479                String[] insGE34Args = new String[10];
480                insGE34Args[GE34_YKNO]= ykno;
481
482                // 6.3.9.0 (2015/11/06) Map.keySet() ではなく、Map.values() を使う様に変更。
483                for( final String[] dstInfo : mailDstMap.values() ) {
484                        insGE34Args[GE34_DST_ID]        = trim( dstInfo[MailPattern.IDX_DST_ID]  , 10 );
485                        insGE34Args[GE34_GROUP_ID]      = trim( dstInfo[MailPattern.IDX_GROUP_ID], 20 );
486                        insGE34Args[GE34_DST_NAME]      = trim( dstInfo[MailPattern.IDX_DST_NAME], 20 );
487                        insGE34Args[GE34_DST_ADDR]      = trim( dstInfo[MailPattern.IDX_DST_ADDR], 100 );
488                        insGE34Args[GE34_DST_KBN]       = dstInfo[MailPattern.IDX_DST_KBN];
489                        insGE34Args[GE34_FGJ]           = dstInfo[MailPattern.IDX_FGJ];
490                        insGE34Args[GE34_DYSET]         = DateSet.getDate( "yyyyMMddHHmmss" );                  // 6.4.2.0 (2016/01/29)
491                        insGE34Args[GE34_USRSET]        = initParamMap.get( "LOGIN_USERID" );
492                        insGE34Args[GE34_PGUPD]         = initParamMap.get( "PGID" );
493                        DBUtil.dbExecute( INS_GE34, insGE34Args, APP_INFO, DBID );              // 5.5.5.1 (2012/08/07)
494                }
495
496        }
497
498        /**
499         * パラメータマップをセットします。
500         *
501         * @og.rev 6.4.3.1 (2016/02/12) 作成元のMapを、HashMap から ConcurrentHashMap に置き換え。
502         * @og.rev 6.4.3.3 (2016/03/04) ConcurrentHashMap を受け取ることを明確にするため、I/FをConcurrentMapに変更します。
503         *
504         * @param       params  パラメータのマップ
505         */
506        protected void setInitParams( final ConcurrentMap<String, String> params ) {
507                initParamMap = params;
508        }
509
510        /**
511         * 添付ファイル配列をセットします。
512         *
513         * @param       attach1 添付ファイル名1
514         * @param       attach2 添付ファイル名2
515         * @param       attach3 添付ファイル名3
516         * @param       attach4 添付ファイル名4
517         * @param       attach5 添付ファイル名5
518         */
519        protected void setAttachFiles( final String attach1
520                                                                , final String attach2
521                                                                , final String attach3
522                                                                , final String attach4
523                                                                , final String attach5 ) {
524                final List<String> fileList = new ArrayList<>();
525                if( attach1 != null && attach1.length() != 0 ) { fileList.add( attach1 ); }
526                if( attach2 != null && attach2.length() != 0 ) { fileList.add( attach2 ); }
527                if( attach3 != null && attach3.length() != 0 ) { fileList.add( attach3 ); }
528                if( attach4 != null && attach4.length() != 0 ) { fileList.add( attach4 ); }
529                if( attach5 != null && attach5.length() != 0 ) { fileList.add( attach5 ); }
530                attachFiles = fileList.toArray( new String[fileList.size()] );
531        }
532
533        /**
534         * メール宛先マップをセットします。
535         *
536         * @og.rev 6.4.3.1 (2016/02/12) 作成元のMapを、HashMap から ConcurrentHashMap に置き換え。
537         * @og.rev 6.4.3.3 (2016/03/04) ConcurrentHashMap を受け取ることを明確にするため、I/FをConcurrentMapに変更します。
538         *
539         * @param   mailDst     メール宛先マップ
540         */
541        protected void setMailDstMap( final ConcurrentMap<String, String[]> mailDst ) {
542                mailDstMap = mailDst;
543        }
544
545        /**
546         * メール宛先マップをセットします。
547         *
548         * @og.rev 6.4.3.1 (2016/02/12) 作成元のMapを、HashMap から ConcurrentHashMap に置き換え。
549         * @og.rev 6.4.3.1 (2016/02/12) ConcurrentMap 系は、key,val ともに not null 制限です。
550         * @og.rev 6.4.3.3 (2016/03/04) ConcurrentHashMap を受け取ることを明確にするため、I/FをConcurrentMapに変更します。
551         *
552         * @return      メール宛先マップ
553         */
554        protected ConcurrentMap<String, String[]> getMailDstMap() {
555                return mailDstMap;
556        }
557
558        /**
559         * 指定の長さ以内の文字列を返します。
560         *
561         * @og.rev 5.9.1.3 (2015/10/30) 文字数ではなくByte数に変更
562         *
563         * @param       src             オリジナルの文字列
564         * @param       maxLen  指定の長さ
565         *
566         * @return      指定の長さに短縮された文字列
567         */
568        protected String trim( final String src, final int maxLen ) {
569                String rtn = src;
570                if( src != null && src.length() > maxLen ) {
571                        rtn = StringUtil.cut( src, maxLen );            // 5.9.1.3 (2015/10/30)
572                }
573                return rtn;
574        }
575
576        /**
577         * アドレスチェックのエラーリストを返します。
578         *
579         * @return      エラーリスト
580         */
581        protected List<String> getErrList(){
582                return errAddrList;
583        }
584
585        /**
586         * 宛先マップを元に、送信オブジェクトに宛先をセットします。
587         * セットする際に、アカウントエラーとなっているアドレスを除外します。
588         * 宛先が存在しない場合、例外を投げます。
589         *
590         * @og.rev 4.3.7.5 (2009/07/08) 送信先名称が設定されていない場合は、アドレスを<>で囲わない
591         * @og.rev 6.3.9.0 (2015/11/06) Map.keySet() ではなく、Map.values() を使う様に変更。
592         *
593         * @param invalidAddr 宛先のリスト
594         */
595        private void setMailDst( final List<String> invalidAddr ){
596                final ArrayList<String> toList = new ArrayList<>();
597                final ArrayList<String> ccList = new ArrayList<>();
598                final ArrayList<String> bccList = new ArrayList<>();
599
600                // これ、今見たけど、こんな使い方はどうかと思う。
601                final Map<Integer, ArrayList<String>> tempMap = new HashMap<>();
602                tempMap.put( Integer.valueOf( MailPattern.KBN_TO ),  toList );
603                tempMap.put( Integer.valueOf( MailPattern.KBN_CC ),  ccList );
604                tempMap.put( Integer.valueOf( MailPattern.KBN_BCC ), bccList );
605
606                // 6.3.9.0 (2015/11/06) Map.keySet() ではなく、Map.values() を使う様に変更。
607                for( final String[] dstInfo : mailDstMap.values() ) {
608                        final Integer kbn = Integer.valueOf( dstInfo[MailPattern.IDX_DST_KBN] );
609                        // 6.1.1.0 (2015/01/17) PMD Avoid if(x != y) ..; else ..;
610                        if( invalidAddr.contains( dstInfo[MailPattern.IDX_DST_ADDR] )
611                                        || FGJ_ADDR_ERR.equals( dstInfo[MailPattern.IDX_FGJ] )){
612                                if( FGJ_SEND_OVER.equals( dstInfo[MailPattern.IDX_FGJ] ) ) {
613                                        dstInfo[MailPattern.IDX_FGJ] = FGJ_ACNT_ERR;
614                                }
615                        }
616                        else {
617                                dstInfo[MailPattern.IDX_FGJ] = FGJ_SEND_OVER;
618
619                                // 4.3.7.5 (2009/07/08)
620                                final String name = dstInfo[MailPattern.IDX_DST_NAME];
621                                if( name != null && name.length() > 0 ) {
622                                        tempMap.get( kbn ).add( dstInfo[MailPattern.IDX_DST_NAME] +  "<"+ dstInfo[MailPattern.IDX_DST_ADDR] + ">" );
623                                }
624                                else {
625                                        tempMap.get( kbn ).add( dstInfo[MailPattern.IDX_DST_ADDR] );
626                                }
627                        }
628                }
629
630                mail.clearTo();         // 宛先(TO)をクリア
631                mail.clearCc();         // 宛先(CC)をクリア
632                mail.clearBcc();        // 宛先(BCC)をクリア
633                boolean haveValidAddr = false ;
634                if( ! toList.isEmpty() ) {      // toのセット
635                        haveValidAddr = true;
636                        final String[] to = toList.toArray( new String[toList.size()] );
637                        mail.setTo( to );
638                }
639                if( ! ccList.isEmpty() ) {      // ccのセット
640                        haveValidAddr = true;
641                        final String[] cc = ccList.toArray( new String[ccList.size()] );
642                        mail.setCc( cc );
643                }
644                if( ! bccList.isEmpty() ) {     // bccのセット
645                        haveValidAddr = true;
646                        final String[] bcc = bccList.toArray( new String[bccList.size()] );
647                        mail.setBcc( bcc );
648                }
649                if( !haveValidAddr ){           // 宛先全部無効の場合、例外を投げます。
650                        final String errMsg = "宛先のメールアドレスが有効ではありません。"
651                                                + "TO , CC , BCC のいづれにもアドレスが設定されていません。"; // 5.1.8.0 (2010/07/01) errMsg 修正
652                        throw new OgRuntimeException( errMsg );
653                }
654        }
655
656        /**
657         * 要求NOを採番します。
658         * この要求NOで履歴テーブル(GE32)と宛先テーブル(GE30)の関連付けを持たせます。
659         *
660         * @og.rev 5.5.5.1 (2012/08/07) リソース系DBID 付け忘れ対策
661         * @og.rev 5.9.26.0 (2017/11/02) DB共通化対応
662         *
663         * @return      要求NO
664         */
665        private String getYkno() {
666
667                // 5.9.26.0 (2017/11/02) DBFnctionNameを利用して、シーケンスを取得
668                String selYkno = "";
669                final Transaction tran = new TransactionReal( APP_INFO );
670                try{
671                        selYkno = String.valueOf(DBFunctionName.getDBName(ConnectionFactory.getDBName(DBID)).getSequence("GE32S02", tran));
672                }finally{
673                        tran.close();
674                }
675
676                return selYkno;
677        }
678
679        /**
680         * メールアドレスのリストよりユーザーIDを逆引きします。
681         *
682         * @og.rev 6.1.0.0 (2014/12/26) refactoring : メールアドレスのリスト件数を見てから、処理の実行を決めます。
683         * @og.rev 6.3.9.0 (2015/11/06) Map.keySet() ではなく、Map.entrySet() を使う様に変更。
684         * @og.rev 6.4.3.4 (2016/03/11) forループを、forEach メソッドに置き換えます。
685         *
686         * @param       addressList     メールアドレスのリスト(not null)
687         *
688         * @return      ユーザーID
689         * @og.rtnNotNull
690         */
691        private String getUserIds( final List<String> addressList ){
692                final int size = addressList.size() ;
693                if( size == 0 ) { return "" ; }
694
695                final Map<String,String> addressMap = new HashMap<>();
696                // 6.3.9.0 (2015/11/06) Map.keySet() ではなく、Map.entrySet() を使う様に変更。
697
698                // 6.4.3.4 (2016/03/11) forループを、forEach メソッドに置き換えます。
699                mailDstMap.forEach( (uid,inf) -> addressMap.put( inf[MailPattern.IDX_DST_ADDR], uid ) );
700
701                final StringBuilder idBuf = new StringBuilder( BUFFER_MIDDLE )
702                        .append( addressMap.get( addressList.get( 0 ) ) );              // 先に size == 0 判定は終わっている。
703                for( int i=1; i<size; i++ ) {
704                        idBuf.append( ',' ).append( addressMap.get( addressList.get( i ) ) );
705                }
706                return idBuf.toString();
707        }
708}