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 * 1.Windows-31J + 8bit 送信
051 * 2.ISO-2022-JP に独自変換 + 7bit 送信
052 * の方法があります。
053 * 今回、この2つの方法について、対応いたしました。
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)。引数3つ追加(将来的には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         * 送信元(FROM)アドレスをセットします。
279         *
280         * @param   from 送信元(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         * 送信先(TO)アドレス配列をセットします。
298         *
299         * @param   to 送信先(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         * 送信先(CC)アドレス配列をセットします。
317         *
318         * @param   cc 送信先(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         * 送信先(BCC)アドレス配列をセットします。
336         *
337         * @param   bcc 送信先(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         * 送信先(TO)アドレス配列をクリアします。
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}