    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.system.OgRuntimeException ;         // 6.4.2.0 (2016/01/29)
    019import org.opengion.fukurou.system.LogWriter;
    020import static org.opengion.fukurou.system.HybsConst.CR;                         // 6.1.0.0 (2014/12/26) refactoring
    021
    022import java.io.UnsupportedEncodingException;
    023import java.util.Properties;
    024import java.util.Date;
    025
    026import javax.activation.FileDataSource;
    027import javax.activation.DataHandler;
    028import javax.mail.internet.InternetAddress;
    029import javax.mail.internet.AddressException;
    030import javax.mail.internet.MimeMessage;
    031import javax.mail.internet.MimeMultipart;
    032import javax.mail.internet.MimeBodyPart;
    033import javax.mail.internet.MimeUtility;
    034import javax.mail.Authenticator;                                                                        // 6.2.4.1 (2015/05/22) SMTP_AUTH 対応
    035import javax.mail.PasswordAuthentication;                                                       // 6.2.4.1 (2015/05/22) SMTP_AUTH 対応
    036import javax.mail.Store;
    037import javax.mail.Transport;
    038import javax.mail.Session;
    039import javax.mail.Message;
    040import javax.mail.MessagingException;
    041import javax.mail.IllegalWriteException;
    042
    043/**
    044 * MailTX は、SMTPプロトコルによるメール送信プログラムです。
    045 *
    046 * E-Mail で日本語を送信する場合、ISO-2022-JP(JISコード)化して、7bit で
    047 * エンコードして送信する必要がありますが、Windows系の特殊文字や、unicodeと
    048 * 文字のマッピングが異なる文字などが、文字化けします。
    049 * 対応方法としては、
    050 * １．Windows-31J + 8bit 送信
    051 * ２．ISO-2022-JP に独自変換 + 7bit 送信
    052 * の方法があります。
    053 * 今回、この２つの方法について、対応いたしました。
    054 *
    055 * ※ 6.3.8.0 (2015/09/11)
    056 *    useSSL属性=true に設定すると、protocolに、smtps を使用します。
    057 *
    058 * @version  4.0
    059 * @author   Kazuhiko Hasegawa
    060 * @since    JDK5.0,
    061 */
    062public class MailTX {
    063        private static final String AUTH_PBS   = "POP_BEFORE_SMTP";             // 5.4.3.2
    064        private static final String AUTH_SMTPA = "SMTP_AUTH";                   // 6.2.4.1 (2015/05/22) SMTP_AUTH 対応
    065
    066        /** メーラーの名称  {@value} */
    067        public static final String MAILER = "openGion Mail Ver 6.0";
    068
    069        private final String    charset  ;      // Windwos-31J , MS932 , UTF-8 , ISO-2022-JP
    070        private String[]                filename ;
    071        private String                  message  ;
    072        private Session                 session  ;
    073        private MimeMultipart   mmPart   ;
    074        private MimeMessage             mimeMsg  ;
    075        private MailCharset             mcSet    ;
    076
    077        /**
    078         * メールサーバーとデフォルト文字エンコーディングを指定して、オブジェクトを構築します。
    079         *
    080         * デフォルト文字エンコーディングは、ISO-2022-JP です。
    081         *
    082         * @param       host    メールサーバー
    083         * @throws      IllegalArgumentException 引数が null の場合。
    084         */
    085        public MailTX( final String host ) {
    086                this( host,"ISO-2022-JP" );
    087        }
    088
    089        /**
    090         * メールサーバーとデフォルト文字エンコーディングを指定して、オブジェクトを構築します。
    091         *
    092         * 文字エンコーディングには、Windwos-31J , MS932 , UTF-8 , ISO-2022-JP を指定できます。
    093         *
    094         * @og.rev 5.4.3.2 (2012/01/06) 認証対応のため
    095         * @og.rev 5.8.1.1 (2014/11/14) 認証ポート追加
    096         * @og.rev 6.3.8.0 (2015/09/11) SSL接続するかどうかを指定するパラメータを追加します。
    097         *
    098         * @param       host    メールサーバー
    099         * @param       charset 文字エンコーディング
    100         * @throws      IllegalArgumentException 引数が null の場合。
    101         */
    102        public MailTX( final String host , final String charset ) {
    103//              this( host,charset,null,null,null,null,null,false );
    104                this( host,charset,null,null,null,null,null,false,false );              // TSL,SSL
    105        }
    106
    107        /**
    108         * メールサーバーと文字エンコーディングを指定して、オブジェクトを構築します。
    109         * 認証を行う場合は認証方法を指定します。
    110         *
    111         * 文字エンコーディングには、Windwos-31J , MS932 , ISO-2022-JP を指定できます。
    112         *
    113         * @og.rev 5.1.9.0 (2010/08/01) mail.smtp.localhostの設定追加
    114         * @og.rev 5.4.3.2 (2012/01/06) 認証対応(POP Before SMTP)。引数３つ追加(将来的にはAuthentication対応？)
    115         * @og.rev 5.8.1.1 (2014/11/14) 認証ポート追加
    116         * @og.rev 6.2.4.1 (2015/05/22) SMTP_AUTH 対応
    117         * @og.rev 6.3.8.0 (2015/09/11) SSL接続するかどうかを指定するパラメータを追加します。
    118         * @og.rev 5.9.29.2 (2018/02/16) STARTTLS対応(ｷｰﾜｰﾄﾞをVer5 にあわせます)
    119         * @og.rev 5.10.20.1 (2020/03/03) 添付ファイル名文字化け対策
    120         *
    121         * @param       host            メールサーバー
    122         * @param       charset         文字エンコーディング
    123         * @param       smtpPort        SMTPポート
    124         * @param       authType        認証方法(POP_BEFORE_SMTP , SMTP_AUTH)
    125         * @param       authPort        認証ポート
    126         * @param       authUser        認証ユーザ
    127         * @param       authPass        認証パスワード
    128         * @param       useStarttls 暗号化通信設定（STARTTLS) 5.9.29.2
    129         * @param       useSSL          SSL接続するかどうか
    130         * @throws      IllegalArgumentException 引数が null の場合。
    131         */
    132        public MailTX( final String host , final String charset, final String smtpPort
    133//                              ,final String authType, final String authPort, final String authUser, final String authPass, final boolean useSSL) {
    134                                ,final String authType, final String authPort, final String authUser, final String authPass, final boolean useStarttls, final boolean useSSL ) {
    135                if( host == null ) {
    136                        final String errMsg = "host に null はセット出来ません。";
    137                        throw new IllegalArgumentException( errMsg );
    138                }
    139
    140                if( charset == null ) {
    141                        final String errMsg = "charset に null はセット出来ません。";
    142                        throw new IllegalArgumentException( errMsg );
    143                }
    144
    145                this.charset = charset;
    146
    147                mcSet = MailCharsetFactory.newInstance( charset );
    148
    149                // 5.10.20.1 (2020/03/03) 添付ファイル名文字化け対策(暫定)
    150                System.setProperty("mail.mime.splitlongparameters", "false");
    151                System.setProperty("mail.mime.encodeparameters", "false" );
    152
    153                final Properties prop = new Properties();
    154                prop.setProperty("mail.mime.charset"                    , charset );
    155                prop.setProperty("mail.mime.decodetext.strict"  , "false" );
    156                prop.setProperty("mail.mime.address.strict"             , "false" );
    157                prop.setProperty("mail.smtp.host"                               , host );
    158                // 5.1.9.0 (2010/08/01) 設定追加
    159                prop.setProperty("mail.smtp.localhost"                  , host );
    160                prop.setProperty("mail.host"                                    , host );       // MEssage-ID の設定に利用
    161
    162                // 5.4.3.2 ポート追加
    163                if( smtpPort != null && smtpPort.length() > 0 ){
    164                        prop.setProperty("mail.smtp.port"                       , smtpPort);    // MEssage-ID の設定に利用
    165                }
    166
    167                // 6.2.4.1 (2015/05/22) SMTP_AUTH 対応
    168                Authenticator myAuth = null;
    169                if( AUTH_SMTPA.equals( authType ) ) {
    170                        prop.setProperty("mail.smtp.auth"                       , "true" );
    171                        prop.setProperty("mail.transport.protocol"      , "smtps" );    // 6.3.8.0 (2015/09/11)
    172                        // 6.3.9.0 (2015/11/06) 名前付き static 内部クラスにリファクタリング(findbugs)
    173        //              myAuth = new MyAuthenticator( authUser,authPass );
    174                        myAuth = new Authenticator() {                                  // 5.8.7.1 (2015/05/22) SMTP認証用クラス
    175                                /**
    176                                 * パスワード認証が必要な時には呼ばれる。
    177                                 *
    178                                 * @return      PasswordAuthenticationオブジェクト
    179                                 */
    180                                @Override
    181                                protected PasswordAuthentication getPasswordAuthentication() {
    182                                        return new PasswordAuthentication( authUser,authPass );
    183                                }
    184                        };
    185                }
    186
    187                // 6.3.8.0 (2015/09/11) SSL接続するかどうかを指定するパラメータを追加します。
    188                // 5.9.29.2 (2018/02/16) STARTTLS対応  (ｷｰﾜｰﾄﾞをVer5 にあわせます)
    189//              if( useSSL ) {
    190                if ( useStarttls || useSSL ) {
    191                        prop.setProperty("mail.smtp.starttls.enable"            , "true" );                                                     // 6.3.8.0 (2015/09/11)
    192                        prop.setProperty("mail.smtp.starttls.required"          , "true" );                                                     // 6.3.8.0 (2015/09/11)
    193                //      prop.setProperty("mail.smtp.socketFactory.class"        , "javax.net.ssl.SSLSocketFactory" );
    194                //      prop.setProperty("mail.smtp.socketFactory.fallback"     , "false" );
    195                //      prop.setProperty("mail.smtp.socketFactory.port"         , String.valueOf( smtpPort ) );         // 587
    196                //      prop.setProperty("mail.transport.protocol"                      , "smtps" );    // 6.3.8.0 (2015/09/11)
    197                }
    198
    199                // 6.9.1.0 (2018/02/26) STL/SSL 両対応
    200                if ( useSSL ) {
    201                        prop.setProperty("mail.smtp.socketFactory.class"        , "javax.net.ssl.SSLSocketFactory" );
    202                        prop.setProperty("mail.smtp.socketFactory.fallback"     , "false" );
    203                        prop.setProperty("mail.smtp.socketFactory.port"         , String.valueOf( smtpPort ) );         // 465
    204                        prop.setProperty("mail.transport.protocol"                      , "smtps" );    // 6.3.8.0 (2015/09/11)
    205                }
    206
    207                session = Session.getInstance( prop, myAuth );          // 6.2.4.1 (2015/05/22) SMTP_AUTH 対応
    208
    209                // POP before SMTP認証処理 5.4.3.2
    210                if( AUTH_PBS.equals( authType ) ){
    211                        try{
    212                                // 5.8.1.1 (2014/11/14) 認証ポート追加
    213                                final int aPort = authPort == null || authPort.isEmpty() || authPass == null || authPass.isEmpty() ? -1 : Integer.parseInt(authPort) ;
    214                                final Store store = session.getStore("pop3");
    215                                store.connect( host,aPort,authUser,authPass );  // 5.8.1.1 (2014/11/14) 認証ポート追加
    216                                store.close();
    217                        }
    218                        catch( final MessagingException ex ) {
    219                                final String errMsg = "POP3 Auth Exception: "+ host + "/" + authUser;
    220                                throw new OgRuntimeException( errMsg,ex );
    221                        }
    222                }
    223
    224                mimeMsg = new MimeMessage( session );
    225        }
    226
    227        /**
    228         * メールを送信します。
    229         *
    230         */
    231        public void sendmail() {
    232                try {
    233                        mimeMsg.setSentDate( new Date() );
    234
    235                        if( filename == null || filename.length == 0 ) {
    236                                mcSet.setTextContent( mimeMsg,message );
    237                        }
    238                        else {
    239                                mmPart = new MimeMultipart();
    240                                mimeMsg.setContent( mmPart );
    241                                // テキスト本体の登録
    242                                addMmpText( message );
    243
    244                                // 添付ファイルの登録
    245                                for( int i=0; i<filename.length; i++ ) {
    246                                        addMmpFile( filename[i] );
    247                                }
    248                        }
    249
    250                        mimeMsg.setHeader("X-Mailer", MAILER );
    251                        mimeMsg.setHeader("Content-Transfer-Encoding", mcSet.getBit() );
    252                        Transport.send( mimeMsg );
    253                }
    254                catch( final AddressException ex ) {
    255                        final String errMsg = "Address Exception: " + ex.getMessage() ;
    256                        throw new OgRuntimeException( errMsg,ex );
    257                }
    258                catch( final MessagingException mex ) {
    259                        final String errMsg = "MessagingException: " + mex.getMessage() ;
    260                        throw new OgRuntimeException( errMsg,mex );
    261                }
    262        }
    263
    264        /**
    265         * MimeMessageをリセットします。
    266         *
    267         * sendmail() でメールを送信後、セッションを閉じずに別のメールを送信する場合、
    268         * リセットしてから、各種パラメータを再設定してください。
    269         * その場合は、すべてのパラメータが初期化されていますので、もう一度
    270         * 設定しなおす必要があります。
    271         *
    272         */
    273        public void reset() {
    274                mimeMsg = new MimeMessage(session);
    275        }
    276
    277        /**
    278         * 送信元(ＦＲＯＭ)アドレスをセットします。
    279         *
    280         * @param   from 送信元(ＦＲＯＭ)アドレス
    281         */
    282        public void setFrom( final String from ) {
    283                try {
    284                        if( from != null ) {
    285                                mimeMsg.setFrom( getAddress( from ) );
    286                        }
    287                } catch( final AddressException ex ) {
    288                        final String errMsg = "Address Exception: " + ex.getMessage() ;
    289                        throw new OgRuntimeException( errMsg,ex );
    290                } catch( final MessagingException mex ) {
    291                        final String errMsg = "MessagingException: " + mex.getMessage() ;
    292                        throw new OgRuntimeException( errMsg,mex );
    293                }
    294        }
    295
    296        /**
    297         * 送信先(ＴＯ)アドレス配列をセットします。
    298         *
    299         * @param   to 送信先(ＴＯ)アドレス配列(可変長引数)
    300         */
    301        public void setTo( final String... to ) {
    302                try {
    303                        if( to != null && to.length > 0 ) {             // 6.1.1.0 (2015/01/17) 可変長引数でもnullは来る。
    304                                mimeMsg.setRecipients( Message.RecipientType.TO, getAddress( to ) );
    305                        }
    306                } catch( final AddressException ex ) {
    307                        final String errMsg = "Address Exception: " + ex.getMessage() ;
    308                        throw new OgRuntimeException( errMsg,ex );
    309                } catch( final MessagingException mex ) {
    310                        final String errMsg = "MessagingException: " + mex.getMessage() ;
    311                        throw new OgRuntimeException( errMsg,mex );
    312                }
    313        }
    314
    315        /**
    316         * 送信先(ＣＣ)アドレス配列をセットします。
    317         *
    318         * @param   cc 送信先(ＣＣ)アドレス配列(可変長引数)
    319         */
    320        public void setCc( final String... cc ) {
    321                try {
    322                        if( cc != null && cc.length > 0 ) {             // 6.1.1.0 (2015/01/17) 可変長引数でもnullは来る。
    323                                mimeMsg.setRecipients( Message.RecipientType.CC, getAddress( cc ) );
    324                        }
    325                } catch( final AddressException ex ) {
    326                        final String errMsg = "Address Exception: " + ex.getMessage() ;
    327                        throw new OgRuntimeException( errMsg,ex );
    328                } catch( final MessagingException mex ) {
    329                        final String errMsg = "MessagingException: " + mex.getMessage() ;
    330                        throw new OgRuntimeException( errMsg,mex );
    331                }
    332        }
    333
    334        /**
    335         * 送信先(ＢＣＣ)アドレス配列をセットします。
    336         *
    337         * @param   bcc 送信先(ＢＣＣ)アドレス配列(可変長引数)
    338         */
    339        public void setBcc( final String... bcc ) {
    340                try {
    341                        if( bcc != null && bcc.length > 0 ) {           // 6.1.1.0 (2015/01/17) 可変長引数でもnullは来る。
    342                                mimeMsg.setRecipients( Message.RecipientType.BCC, getAddress( bcc ) );
    343                        }
    344                } catch( final AddressException ex ) {
    345                        final String errMsg = "Address Exception: " + ex.getMessage() ;
    346                        throw new OgRuntimeException( errMsg,ex );
    347                } catch( final MessagingException mex ) {
    348                        final String errMsg = "MessagingException: " + mex.getMessage() ;
    349                        throw new OgRuntimeException( errMsg,mex );
    350                }
    351        }
    352
    353        /**
    354         * 送信先(ＴＯ)アドレス配列をクリアします。
    355         * @og.rev 4.3.6.0 (2009/04/01) 新規追加
    356         *
    357         */
    358        public void clearTo() {
    359                try {
    360                        mimeMsg.setRecipients( Message.RecipientType.TO, (InternetAddress[])null );
    361                } catch( final IllegalWriteException ex ) {
    362                        final String errMsg = "Address Exception: " + ex.getMessage() ;
    363                        throw new OgRuntimeException( errMsg,ex );
    364                } catch( final IllegalStateException ex ) {
    365                        final String errMsg = "Address Exception: " + ex.getMessage() ;
    366                        throw new OgRuntimeException( errMsg,ex );
    367                } catch( final MessagingException mex ) {
    368                        final String errMsg = "MessagingException: " + mex.getMessage() ;
    369                        throw new OgRuntimeException( errMsg,mex );
    370                }
    371        }
    372
    373        /**
    374         * 送信先(CC)アドレス配列をクリアします。
    375         *
    376         * @og.rev 4.3.6.0 (2009/04/01) 新規追加
    377         */
    378        public void clearCc() {
    379                try {
    380                        mimeMsg.setRecipients( Message.RecipientType.CC, (InternetAddress[])null );
    381                } catch( final IllegalWriteException ex ) {
    382                        final String errMsg = "Address Exception: " + ex.getMessage() ;
    383                        throw new OgRuntimeException( errMsg,ex );
    384                } catch( final IllegalStateException ex ) {
    385                        final String errMsg = "Address Exception: " + ex.getMessage() ;
    386                        throw new OgRuntimeException( errMsg,ex );
    387                } catch( final MessagingException mex ) {
    388                        final String errMsg = "MessagingException: " + mex.getMessage() ;
    389                        throw new OgRuntimeException( errMsg,mex );
    390                }
    391        }
    392
    393        /**
    394         * 送信先(BCC)アドレス配列をクリアします。
    395         * @og.rev 4.3.6.0 (2009/04/01) 新規追加
    396         *
    397         */
    398        public void clearBcc() {
    399                try {
    400                        mimeMsg.setRecipients( Message.RecipientType.BCC, (InternetAddress[])null );
    401                } catch( final IllegalWriteException ex ) {
    402                        final String errMsg = "Address Exception: " + ex.getMessage() ;
    403                        throw new OgRuntimeException( errMsg,ex );
    404                } catch( final IllegalStateException ex ) {
    405                        final String errMsg = "Address Exception: " + ex.getMessage() ;
    406                        throw new OgRuntimeException( errMsg,ex );
    407                } catch( final MessagingException mex ) {
    408                        final String errMsg = "MessagingException: " + mex.getMessage() ;
    409                        throw new OgRuntimeException( errMsg,mex );
    410                }
    411        }
    412
    413        /**
    414         * 返信元(replyTo)アドレス配列をセットします。
    415         *
    416         * @param   replyTo 返信元(replyTo)アドレス配列(可変長引数)
    417         */
    418        public void setReplyTo( final String... replyTo ) {
    419                try {
    420                        if( replyTo != null && replyTo.length > 0 ) {           // 6.1.1.0 (2015/01/17) 可変長引数でもnullは来る。
    421                                mimeMsg.setReplyTo( getAddress( replyTo ) );
    422                        }
    423                } catch( final AddressException ex ) {
    424                        final String errMsg = "Address Exception: " + ex.getMessage() ;
    425                        throw new OgRuntimeException( errMsg,ex );
    426                } catch( final MessagingException mex ) {
    427                        final String errMsg = "MessagingException: " + mex.getMessage() ;
    428                        throw new OgRuntimeException( errMsg,mex );
    429                }
    430        }
    431
    432        /**
    433         * タイトルをセットします。
    434         *
    435         * @param   subject タイトル
    436         */
    437        public void setSubject( final String subject ) {
    438                // Servlet からの読み込みは、iso8859_1 でエンコードされた文字が
    439                // セットされるので、ユニコードに変更しておかないと文字化けする。
    440                // JRun 3.0 では、問題なかったが、tomcat3.1 では問題がある。
    441                try {
    442                        if( subject != null ) {
    443                                mimeMsg.setSubject( mcSet.encodeWord( subject ) );
    444                        }
    445                } catch( final AddressException ex ) {
    446                        final String errMsg = "Address Exception: " + ex.getMessage() ;
    447                        throw new OgRuntimeException( errMsg,ex );
    448                } catch( final MessagingException mex ) {
    449                        final String errMsg = "MessagingException: " + mex.getMessage() ;
    450                        throw new OgRuntimeException( errMsg,mex );
    451                }
    452        }
    453
    454        /**
    455         * 添付ファイル名配列をセットします。
    456         *
    457         * @param   fname 添付ファイル名配列(可変長引数)
    458         */
    459        public void setFilename( final String... fname ) {
    460                if( fname != null && fname.length > 0 ) {               // 6.1.1.0 (2015/01/17) 可変長引数でもnullは来る。
    461                        final int size = fname.length;
    462                        filename = new String[size];
    463                        System.arraycopy( fname,0,filename,0,size );
    464                }
    465        }
    466
    467        /**
    468         * メッセージ(本文)をセットします。
    469         *
    470         * @param   msg メッセージ(本文)
    471         */
    472        public void setMessage( final String msg ) {
    473                // なぜか、メッセージの最後は、<CR><LF>をセットしておく。
    474
    475                if( msg == null ) { message = CR; }
    476                else {              message = msg + CR; }
    477        }
    478
    479        /**
    480         * デバッグ情報の表示を行うかどうかをセットします。
    481         *
    482         * @param   debug 表示有無[true/false]
    483         */
    484        public void setDebug( final boolean debug ) {
    485            session.setDebug( debug );
    486        }
    487
    488        /**
    489         * 指定されたファイルをマルチパートに追加します。
    490         *
    491         * @param   fileStr マルチパートするファイル名
    492         */
    493        private void addMmpFile( final String fileStr ) {
    494                try {
    495                        final MimeBodyPart mbp = new MimeBodyPart();
    496                        final FileDataSource fds = new FileDataSource(fileStr);
    497                        mbp.setDataHandler(new DataHandler(fds));
    498                        mbp.setFileName(MimeUtility.encodeText(fds.getName(), charset, "B"));
    499                        mbp.setHeader("Content-Transfer-Encoding", "base64");
    500                        mmPart.addBodyPart(mbp);
    501                }
    502                catch( final UnsupportedEncodingException ex ) {
    503                        final String errMsg = "Multipart UnsupportedEncodingException: " + ex.getMessage() ;
    504                        throw new OgRuntimeException( errMsg,ex );
    505                }
    506                catch( final MessagingException mex ) {
    507                        final String errMsg = "MessagingException: " + mex.getMessage() ;
    508                        throw new OgRuntimeException( errMsg,mex );
    509                }
    510        }
    511
    512        /**
    513         * 指定された文字列をマルチパートに追加します。
    514         *
    515         * @param   textStr マルチパートする文字列
    516         */
    517        private void addMmpText( final String textStr ) {
    518                try {
    519                        final MimeBodyPart mbp = new MimeBodyPart();
    520                        mbp.setText(textStr, charset);
    521                        mbp.setHeader("Content-Transfer-Encoding", mcSet.getBit());
    522                        mmPart.addBodyPart(mbp, 0);
    523                }
    524                catch( final MessagingException mex ) {
    525                        final String errMsg = "MessagingException: " + mex.getMessage() ;
    526                        throw new OgRuntimeException( errMsg,mex );
    527                }
    528        }
    529
    530        /**
    531         * 文字エンコードを考慮した InternetAddress を作成します。
    532         *
    533         * @param   adrs オリジナルのアドレス文字列
    534         *
    535         * @return  文字エンコードを考慮した InternetAddress
    536         */
    537        private InternetAddress getAddress( final String adrs ) {
    538                final InternetAddress rtnAdrs ;
    539                final int sep = adrs.indexOf( '<' );
    540                if( sep >= 0 ) {
    541                        final String address  = adrs.substring( sep+1,adrs.indexOf( '>' ) ).trim();
    542                        final String personal = adrs.substring( 0,sep ).trim();
    543
    544                        rtnAdrs = mcSet.getAddress( address,personal );
    545                }
    546                else {
    547                        try {
    548                                rtnAdrs = new InternetAddress( adrs );
    549                        }
    550                        catch( final AddressException ex ) {
    551                                final String errMsg = "指定のアドレスをセットできません。"
    552                                                                        + "adrs=" + adrs + " , msg=" + ex.getMessage() ;
    553                                throw new OgRuntimeException( errMsg,ex );
    554                        }
    555                }
    556
    557                return rtnAdrs ;
    558        }
    559
    560        /**
    561         * 文字エンコードを考慮した InternetAddress を作成します。
    562         * これは、アドレス文字配列から、InternetAddress 配列を作成する、
    563         * コンビニエンスメソッドです。
    564         * 処理そのものは、#getAddress( String ) をループしているだけです。
    565         *
    566         * @param   adrs アドレス文字配列(可変長引数)
    567         *
    568         * @return  文字エンコード後のInternetAddress配列
    569         * @see     #getAddress( String )
    570         */
    571        private InternetAddress[] getAddress( final String... adrs ) {
    572                InternetAddress[] rtnAdrs = new InternetAddress[adrs.length];
    573                for( int i=0; i<adrs.length; i++ ) {
    574                        rtnAdrs[i] = getAddress( adrs[i] );
    575                }
    576
    577                return rtnAdrs ;
    578        }
    579
    580//      /**
    581//       * javax.mail.Authenticator クラスの名前付き static 内部クラス
    582//       *
    583//       * SMTP認証用クラスとして使用します。6.2.4.1 (2015/05/22)
    584//       *
    585//       * 名前付き static 内部クラスにリファクタリングします(findbugs)。
    586//       *
    587//       * @og.rev 6.3.9.0 (2015/11/06) 新規追加
    588//       * @og.rev 6.3.9.1 (2015/11/27) 修飾子を、なし → private に変更。
    589//       *
    590//       * @return  Authenticatorオブジェクト
    591//       * @see     javax.mail.Authenticator
    592//       */
    593//      private static final class MyAuthenticator extends Authenticator {
    594//              private final String authUser ;                         // 6.3.9.1 (2015/11/27) 修飾子を、なし → private に変更。
    595//              private final String authPass ;                         // 6.3.9.1 (2015/11/27) 修飾子を、なし → private に変更。
    596//
    597//              /**
    598//               * ユーザ,パスワードを指定したコンストラクター。
    599//               *
    600//               * @og.rev 6.3.9.0 (2015/11/06) 新規追加
    601//               * @og.rev 6.4.1.1 (2016/01/16) PMD refactoring. It is a good practice to call super() in a constructor
    602//               *
    603//               * @param       authUser        認証ユーザ
    604//               * @param       authPass        認証パスワード
    605//               */
    606//              public MyAuthenticator( final String authUser, final String authPass ) {
    607//                      super();
    608//                      this.authUser = authUser;
    609//                      this.authPass = authPass;
    610//              }
    611//
    612//              /**
    613//               * パスワード認証が必要な時に呼ばれます。
    614//               *
    615//               * @og.rev 6.3.9.0 (2015/11/06) 新規追加
    616//               *
    617//               * @return      PasswordAuthenticationオブジェクト
    618//               */
    619//              @Override
    620//              protected PasswordAuthentication getPasswordAuthentication() {
    621//                      return new PasswordAuthentication( authUser,authPass );
    622//              }
    623//      }
    624
    625        /**
    626         * コマンドから実行できる、テスト用の main メソッドです。
    627         *
    628         * Usage: java org.opengion.fukurou.mail.MailTX &lt;from&gt; &lt;to&gt; &lt;host&gt; [&lt;file&gt; ....]
    629         * で、複数の添付ファイルを送付することができます。
    630         *
    631         * @og.rev 6.3.6.0 (2015/08/16) System.arraycopy が使える箇所は、置き換えます。
    632         *
    633         * @param       args    コマンド引数配列
    634         */
    635        public static void main( final String[] args ) {
    636                if( args.length < 3 ) {
    637                        LogWriter.log("Usage: java org.opengion.fukurou.mail.MailTX <from> <to> <host> [<file> ....]");
    638                        return ;
    639                }
    640
    641                final String host  = args[2] ;
    642                final String chset = "ISO-2022-JP" ;
    643
    644                final MailTX sender = new MailTX( host,chset );
    645
    646                sender.setFrom( args[0] );
    647                final String[] to = { args[1] };
    648                sender.setTo( to );
    649
    650                if( args.length > 3 ) {
    651                        final String[] filename = new String[args.length-3];
    652                        // 6.3.6.0 (2015/08/16) System.arraycopy が使える箇所は、置き換えます。
    653                        System.arraycopy( args,3,filename,0,filename.length );          // 6.3.6.0 (2015/08/16)
    654                        sender.setFilename( filename );
    655                }
    656
    657                sender.setSubject( "メール送信テスト" );
    658                final String msg = "これはテストメールです。" + CR
    659                                                +       "うまく受信できましたか?" + CR;
    660                sender.setMessage( msg );
    661
    662                sender.sendmail();
    663        }
    664}