    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.fukurou.mail;
    017
    018import org.opengion.fukurou.util.StringUtil ;
    019import org.opengion.fukurou.util.HybsEntry ;
    020import org.opengion.fukurou.util.Argument ;
    021import org.opengion.fukurou.util.FileUtil ;                                                     // 6.4.5.2 (2016/05/06)
    022import static org.opengion.fukurou.system.HybsConst.CR;                         // 6.3.8.0 (2015/09/11)
    023
    024import java.util.Map;
    025import java.util.LinkedHashMap;
    026
    027import java.util.logging.Logger;
    028import java.util.logging.Level;
    029
    030/**
    031 * MailTransfer は、SMTPプロトコルによるメール送信プログラムです。
    032 *
    033 * 引数には、host,from,to,cc,bcc,replyTo,subject,message,charset,file,debug,help が指定できます。
    034 * 引数のプロパテイのキー部は、大文字・小文字が厳格に適用されますので、正確に記述願います。
    035 *
    036 * Usage: java org.opengion.fukurou.fukurou.mail.MailTransfer
    037 *        -host=メールサーバー(必須)
    038 *        -from=送信元アドレス(必須)
    039 *        -to=送信先アドレスをCSV形式で並べる(必須)
    040 *        -port=送信サーバーのポートを指定(初期値:-1)
    041 *        -useSSL=SSL接続するかどうか[true:する/false:しない]を指定(初期値:false:しない)
    042 *        -auth=認証方式(POP_BEFORE_SMTP , SMTP_AUTH のみ対応)
    043 *        -authPort=認証ポート(初期値:-1)
    044 *        -user=メールを取得するログインユーザー
    045 *        -passwd=メールを取得するログインパスワード
    046 *        -cc=関係者アドレスをCSV形式で並べる
    047 *        -bcc=隠し送信先アドレスをCSV形式で並べる
    048 *        -replyTo=返信先アドレスをCSV形式で並べる
    049 *        -subject=タイトル
    050 *        -message=本文を格納しているファイルのアドレス
    051 *        -msgEncode=本文を格納しているファイルの文字コード(初期値:java.nio.charset.Charset#defaultCharset())
    052 *        -charset=メール送信時のキャラクタセット [ISO-2022-JP / Windows-31J]
    053 *        -fileXX=添付ファイルのファイルパス( XX は複数登録時の添え字 )
    054 *        -debug=メイラーのデバッグモードを指定します。[false / true]
    055 *        -help=使用方法を出力して、終了します。
    056 *        -{&#064;XXXX}=YYYY  メッセージ本文の {&#064;XXXX} 文字列を、YYYY 文字列に変換します。
    057 *            {&#064;ARG.XXX} 予約文字変換 上記引数を割り当てます。
    058 *            {&#064;DATE.XXX} 予約文字変換 SimpleDateFormat 形式の文字を変換します。(日付、時刻等)
    059 *            {&#064;ENV.XXX}  予約文字変換 システムプロパティーの文字を変換します。(java -Dkey=value オプション)
    060 *
    061 * E-Mail で日本語を送信する場合、ISO-2022-JP(JISコード)化して、7bit で
    062 * エンコードして送信する必要がありますが、Windows系の特殊文字や、unicodeと
    063 * 文字のマッピングが異なる文字などが、文字化けします。
    064 * 対応方法としては、
    065 * １．Windows-31J + 8bit 送信
    066 * ２．ISO-2022-JP に独自変換 + 7bit 送信
    067 * の方法があります。
    068 * 今回、この２つの方法について、charset で指定できます。
    069 * 初期値は、ISO-2022-JP です。
    070 *
    071 * ※ 6.2.4.1 (2015/05/22) SMTP_AUTH 対応
    072 *
    073 * ※ 6.3.8.0 (2015/09/11)
    074 *    useSSL属性=true に設定すると、protocolに、smtps を使用します。
    075 *
    076 * @version  4.0
    077 * @author   Kazuhiko Hasegawa
    078 * @since    JDK5.0,
    079 */
    080public class MailTransfer {
    081        // 6.3.9.1 (2015/11/27) The Logger variable declaration does not contain the static and final modifiers(PMD)
    082        private static final Logger LOGGER = Logger.getLogger( MailTransfer.class.getName() );                                                  // 6.8.1.0 (2017/07/14) ｸﾗｽ名を動的作成に変更
    083
    084        /** メール送信時のデフォルトキャラクタセット 「={@value}」  */
    085        public static final String CHARSET = "ISO-2022-JP" ;
    086
    087        /** メイラーの初期デバッグモード 「={@value}」  */
    088        public static final boolean DEBUG_MODE = false ;
    089
    090        private Argument argment;                                                                       // 6.3.8.0 (2015/09/11)
    091
    092        /** staticイニシャライザ後、読み取り専用にするので、ConcurrentHashMap を使用しません。 */
    093        private static final Map<String,String> MUST_PROPARTY   ;       // 必須パラメータ                                      // 6.4.1.1 (2016/01/16) mustProparty   → MUST_PROPARTY   refactoring
    094        /** staticイニシャライザ後、読み取り専用にするので、ConcurrentHashMap を使用しません。 */
    095        private static final Map<String,String> USABLE_PROPARTY ;       // 整合性チェックパラメータ                 // 6.4.1.1 (2016/01/16) usableProparty → USABLE_PROPARTY refactoring
    096
    097        static {
    098                MUST_PROPARTY = new LinkedHashMap<>();
    099                MUST_PROPARTY.put( "host",      "メールサーバー(必須)" );
    100                MUST_PROPARTY.put( "from",      "送信元アドレス(必須)" );
    101                MUST_PROPARTY.put( "to",                "送信先アドレスをCSV形式で並べる(必須)" );
    102
    103                USABLE_PROPARTY = new LinkedHashMap<>();
    104                USABLE_PROPARTY.put( "port"             , "送信サーバーのポート" );                                       // 6.0.3.0 (2014/11/13) SMTP認証
    105                USABLE_PROPARTY.put( "useSSL"           , "SSL接続するかどうかを指定(初期値:false:しない)" );                    // 6.3.8.0 (2015/09/11)
    106                USABLE_PROPARTY.put( "useStarttls"      , "STARTTLS接続するかどうかを指定(初期値:false:しない)" );               // 5.9.29.2 (2018/02/16)
    107                USABLE_PROPARTY.put( "auth"             , "認証方式(POP_BEFORE_SMTP , SMTP_AUTHのみ対応)" );                    // 6.2.4.1 (2015/05/22)
    108                USABLE_PROPARTY.put( "authPort" , "認証ポート" );                                                            // 6.0.3.0 (2014/11/13) SMTP認証
    109                USABLE_PROPARTY.put( "user"             , "認証ユーザー" );                                                   // 6.0.3.0 (2014/11/13) SMTP認証
    110                USABLE_PROPARTY.put( "passwd"   , "認証パスワード" );                                                  // 6.0.3.0 (2014/11/13) SMTP認証
    111                USABLE_PROPARTY.put( "cc"               , "関係者アドレスをCSV形式で並べる" );
    112                USABLE_PROPARTY.put( "bcc"              , "隠し送信先アドレスをCSV形式で並べる" );
    113                USABLE_PROPARTY.put( "replyTo"  , "返信先アドレスをCSV形式で並べる" );
    114                USABLE_PROPARTY.put( "subject"  , "タイトル" );
    115                USABLE_PROPARTY.put( "message"  , "本文を格納しているファイルのアドレス" );
    116                USABLE_PROPARTY.put( "msgEncode"        , "本文を格納しているファイルの文字コード [Windows-31J / UTF-8]" );
    117                USABLE_PROPARTY.put( "charset"  , "メール送信時のキャラクタセット [ISO-2022-JP / Windows-31J]" );
    118                USABLE_PROPARTY.put( "file"             , "添付ファイルのファイルパス( XX は複数登録時の添え字 )" );
    119                USABLE_PROPARTY.put( "{@"               , "{@XXXX}=YYYY  メッセージ本文の {@XXXX} 文字列を、YYYY 文字列に変換します。" );
    120                USABLE_PROPARTY.put( "{@ARG."   , "{@ARG.XXX} 予約文字変換 上記引数を割り当てます。" );
    121                USABLE_PROPARTY.put( "{@DATE."  , "{@DATE.XXX} 予約文字変換 SimpleDateFormat 形式の文字を変換します。(日付、時刻等)" );
    122                USABLE_PROPARTY.put( "{@ENV."   , "{@ENV.XXX} 予約文字変換 システムプロパティーの文字を変換します。(java -Dkey=value オプション)" );
    123                USABLE_PROPARTY.put( "debug"            , "メイラーのデバッグモードを指定します。[false / true]" );
    124                USABLE_PROPARTY.put( "help"             , "使用方法を出力して、終了します。" );
    125        }
    126
    127        /**
    128         * トランスファーを開始します。
    129         *
    130         * @og.rev 4.3.3.5 (2008/11/08) Argument オブジェクトへの引数を util → mail に訂正します。
    131         * @og.rev 6.0.3.0 (2014/11/13) SMTP認証
    132         * @og.rev 6.3.8.0 (2015/09/11) SSL接続するかどうかを指定するパラメータを追加します。
    133         * @og.rev 6.3.8.0 (2015/09/11) message で指定されたファイルの
    134         * @og.rev 6.4.5.1 (2016/04/28) FileStringのコンストラクター変更
    135         * @og.rev 6.4.5.2 (2016/05/06) fukurou.util.FileString から、fukurou.util.FileUtil に移動。
    136         * @og.rev 5.9.29.2 (2018/02/16) STARTTLS対応(ｷｰﾜｰﾄﾞをVer5 にあわせます)
    137         *
    138         * @param       args    引数配列(可変長引数)
    139         */
    140        public void start( final String... args ) {
    141
    142                // パラメータの解析、取得
    143                LOGGER.fine( "パラメータの解析、取得" );
    144                argment = new Argument( "org.opengion.fukurou.mail.MailTransfer" );             // 4.3.3.5 (2008/11/08)
    145                argment.setMustProparty( MUST_PROPARTY );
    146                argment.setUsableProparty( USABLE_PROPARTY );
    147
    148                argment.setArgument( args );
    149
    150                // help パラメータが true に指定された場合の処理。
    151                if( argment.getProparty( "help",false ) ) {
    152                        System.out.println( argment.toString() );
    153                        return;
    154                }
    155
    156                final String host               = argment.getProparty( "host" );
    157                final String chset              = argment.getProparty( "charset", CHARSET );
    158
    159                final boolean useSSL            = argment.getProparty( "useSSL"                 ,false );               // 6.3.8.0 (2015/09/11) SSL接続
    160                final boolean useStarttls       = argment.getProparty( "useStarttls"    ,false );               // 5.9.29.2 (2018/02/16)
    161
    162                final String port               = argment.getProparty( "port" );                                // 6.0.3.0 (2014/11/13) SMTP認証
    163                final String auth               = argment.getProparty( "auth" );                                // 6.0.3.0 (2014/11/13) SMTP認証
    164                final String authPort   = argment.getProparty( "authPort" );                    // 6.0.3.0 (2014/11/13) SMTP認証
    165                final String user               = argment.getProparty( "user" );                                // 6.0.3.0 (2014/11/13) SMTP認証
    166                final String passwd             = argment.getProparty( "passwd" );                              // 6.0.3.0 (2014/11/13) SMTP認証
    167
    168//              final MailTX mail = new MailTX( host,chset,port,auth,authPort,user,passwd,useSSL );                             // 6.3.8.0 (2015/09/11) SSL接続
    169                final MailTX mail = new MailTX( host,chset,port,auth,authPort,user,passwd,useStarttls,useSSL ); // 6.3.8.0 (2015/09/11) SSL接続
    170                LOGGER.fine( "org.opengion.fukurou.mail.MailTX の設定" );
    171
    172                mail.setFrom(                                                   argment.getProparty( "from" ) );
    173                mail.setTo(              StringUtil.csv2Array(  argment.getProparty( "to" ) ) );
    174                mail.setCc(              StringUtil.csv2Array(  argment.getProparty( "cc" ) ) );
    175                mail.setBcc(     StringUtil.csv2Array(  argment.getProparty( "bcc" ) ) );
    176                mail.setReplyTo( StringUtil.csv2Array(  argment.getProparty( "replyTo" ) ) );
    177                mail.setSubject(                                                argment.getProparty( "subject" ) );
    178                mail.setDebug(                                                  argment.getProparty( "debug", DEBUG_MODE ) );
    179
    180                // message は、本文を格納しているファイル名が指定されています。
    181                final String msgFile   = argment.getProparty( "message" ) ;
    182                LOGGER.fine( "本文を格納しているファイルの取得。message=" + msgFile );
    183                if( msgFile != null ) {
    184                        final String msgEncode = argment.getProparty( "msgEncode" ) ;
    185                        // 6.4.5.1 (2016/04/28) FileStringのコンストラクター変更
    186                        String message = FileUtil.getValue( msgFile , msgEncode );      // 6.4.5.2 (2016/05/06)
    187
    188                        // {@XXX} 変換は、Argument クラスの機能を使う。
    189                        message = argment.changeParam( message );
    190                        mail.setMessage( message );
    191                }
    192
    193                // 添付ファイルは、fileXX 形式で、複数指定されています。
    194                LOGGER.fine( "添付ファイルを取り込みます。" );
    195                final HybsEntry[] entry = argment.getEntrys( "file" );
    196                String[] files = new String[entry.length];
    197                for( int i=0; i<files.length; i++ ) {
    198                        files[i] = entry[i].getValue() ;
    199                }
    200                mail.setFilename( files );
    201
    202                // 送信
    203                LOGGER.fine( "送信処理を行います。" );
    204                mail.sendmail();
    205        }
    206
    207        /**
    208         * main メソッドです。
    209         *
    210         * @param       args    引数配列
    211         */
    212        public static void main ( final String[] args ) {
    213                final MailTransfer transfer = new MailTransfer();
    214                try {
    215                        LOGGER.info( "メール送信処理を開始します  ---------------------------------------------" );
    216                        transfer.start( args );
    217                        LOGGER.info( "正常に終了しました。" );
    218                }
    219                catch( final Throwable th ) {
    220                        final String errMsg = "メール送信中に例外が発生しました。 "
    221                                                        + CR + transfer.argment
    222                                                        + CR + th.getMessage() ;
    223                        LOGGER.log( Level.SEVERE,errMsg, th );
    224                }
    225        }
    226}