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