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