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     */
016    package org.opengion.fukurou.mail;
017    
018    import org.opengion.fukurou.util.Closer ;
019    
020    import javax.mail.MessagingException;
021    import javax.mail.Part;
022    import javax.mail.BodyPart;
023    import javax.mail.Multipart;
024    import java.io.File;
025    import java.io.InputStream;
026    import java.io.FileOutputStream;
027    import java.io.IOException;
028    import java.util.List;
029    import java.util.ArrayList;
030    import java.util.Set;
031    import java.util.HashSet;
032    
033    /**
034     * メール添付ファイル処ç�?‚¯ラス
035     *
036     * こã?クラスは、添付ファイルをå?ç�?�™るためã?クラスですã?
037     * 添付ファイルは、ã?ルチパートに含まれてã�?‚‹為、å?帰çš?�«探すå¿?¦�がありますã?
038     *
039     * @version  4.0
040     * @author   Kazuhiko Hasegawa
041     * @since    JDK5.0,
042     */
043    public class MailAttachFiles {
044            private final List<Part> files ;
045            private final String[] names ;
046    
047            /**
048             * ãƒ?ƒ•ォルトコンストラクター
049             *
050             * å†?ƒ¨変数の初期化を行いますã?
051             *
052             * @param       part    Partオブジェクãƒ?
053             */
054            public MailAttachFiles( final Part part ) {
055                    files = new ArrayList<Part>();
056                    names = makeNames( part );
057            }
058    
059            /**
060             * 添付ファイルの名称を文字å?配å?として求めますã?
061             *
062             * @return 添付ファイルの名称を文字å?配å?
063             */
064            public String[] getNames() {
065                    String[] rtn = null ;
066    
067                    if( names != null ) { rtn = names.clone(); }
068    
069                    return rtn ;
070            }
071    
072            /**
073             * 添付ファイルの名称を文字å?配å?として求めますã?
074             *
075             * こã?処ç�??中で、添付ファイルを持つ Part を見つけてå†?ƒ¨配å?(List)に登録しますã?
076             * ファイル名が未æŒ?®šã?場合ã?ã€?noNameFile" + i + ".tmp" とã�?�†ファイル名をつけますã?
077             * i は、添付ファイルの連番ですã?
078             * またã?同ä¸?·»付ファイル名が存在する場合ã?ã€??に添付ファイルの連番を付加してã€?
079             * ファイル名としてユニã?ク化しますã?
080             *
081             * @og.rev 4.3.3.5 (2008/11/08) 日本語添付ファイルがå?ç�?�§きるように修正
082             *
083             * @param part Partオブジェクãƒ?
084             *
085             * @return 添付ファイルの名称を文字å?配å?
086             */
087            private String[] makeNames( final Part part ) {
088                    final String[] nms;
089                    try {
090                            Set<String> set = new HashSet<String>();
091    
092                            fileSearch( part );
093                            nms = new String[files.size()];
094                            for( int i=0; i<nms.length; i++ ) {
095            //                      String name = ((Part)files.get(i)).getFileName();
096                                    String name = (files.get(i)).getFileName();
097                                    if( name == null ) {    // message かã?ファイル名未æŒ?®šã?ケース
098                                            nms[i] = "noNameFile" + i + ".tmp" ;
099                                    }
100    //                              else {
101    //                                      // encode-word の =? の前にはスペã?スがå¿?¦�ã?
102    //                                      StringBuilder buf = new StringBuilder( name );
103    //                                      int pos = buf.indexOf( "?==?" );                // ãƒ?‚³ードã?終äº?�¨開始が連結してã�?‚‹ç®?‰€
104    //                                      // 先é?でなくã?かつ開始記号が含まれてã�?‚‹ã€?
105    //                                      while( pos > 0 ) {
106    //                                              buf.insert( pos+2," " );
107    //                                              pos = buf.indexOf( "?==?",pos+4 );
108    //                                      }
109    //                              }
110                                    // 4.3.3.5 (2008/11/08) 日本語添付ファイルがå?ç�?�§きるように修正
111                                    else {
112                                            nms[i] = MailMessage.mimeDecode( name );
113                                    }
114    
115                                    // 重è¤?ƒ�ェãƒ?‚¯
116                                    if( !set.add( nms[i] ) ) {
117                                            nms[i] = i + "_" + nms[i] ;             // 重è¤?™‚に名称変更しますã?
118                                    }
119                            }
120                    }
121                    catch( MessagingException ex ) {
122                            String errMsg = "メãƒ?‚»ージæƒ??のハンドリングに失敗しましたã€?
123                                                    + ex.getMessage();                              // 5.1.8.0 (2010/07/01) errMsg 修正
124                            throw new RuntimeException( errMsg,ex );
125                    }
126    //              catch( UnsupportedEncodingException ex ) {
127    //                      String errMsg = "ãƒ?‚­スト情報のãƒ?‚³ードに失敗しましたã€? ;
128    //                      throw new RuntimeException( errMsg,ex );
129    //              }
130                    catch( IOException ex ) {
131                            String errMsg = "ãƒ?‚­スト情報の取り出しに失敗しましたã€?
132                                                    + ex.getMessage();                              // 5.1.8.0 (2010/07/01) errMsg 修正
133                            throw new RuntimeException( errMsg,ex );
134                    }
135                    return nms;
136            }
137    
138            /**
139             * 添付ファイルが存在するかどã�?�‹をサーチしますã?
140             *
141             * 添付ファイルは、ã?ルチパートでæŒ?®šされると、å?帰çš?�«検索するå¿?¦�が
142             * 出てきますã?こã?メソãƒ?ƒ‰では、å?帰çš?�«ファイルかどã�?�‹を検索しã?
143             * ファイルであれば、å?部変数(List)に追åŠ?add)してã�?��ますã?
144             *
145             * @param part Partオブジェクãƒ?
146             *
147             * @return 再帰検索終äº?true
148             * @throws MessagingException javax.mail 関連のエラーが発生したとã�?
149             * @throws IOException 入出力エラーが発生したとã�?
150             *
151             */
152            private boolean fileSearch( final Part part ) throws MessagingException ,IOException {
153                    if( part.isMimeType( "multipart/*" ) ) {
154                            Multipart mpt = (Multipart)part.getContent();
155    
156                            int count = mpt.getCount();
157                            for(int i = 0; i < count; i++) {
158                                    BodyPart bpt = mpt.getBodyPart(i);
159                                    fileSearch( bpt );
160                            }
161                    }
162                    else {
163                            if( part.isMimeType( "message/*" )      ||
164                                    part.getFileName() != null              ||
165                                    Part.INLINE.equalsIgnoreCase( part.getDisposition() ) ) {
166                                            files.add( part );
167                            }
168                    }
169                    return true;
170            }
171    
172            /**
173             * 添付ファイルを指定ã?フォルãƒ?�«セーブしますã?
174             *
175             * å†?ƒ¨変数List の 添付ファイルを持つ Part につã�?�¦、ファイルを抜出しã?
176             * æŒ?®šã?ãƒ?‚£レクトリに保存してã�?��ますã?
177             * ファイル名ã?、基本çš?�«添付ファイル名そのもã?ですがã€?
178             * 同ä¸?��称の添付ファイルがè¤?•°登録されてã�?‚‹場合ã?、その重è¤?ƒ•ァイルの番号ã‚?
179             * 頭につけã?番号 + "_" + 添付ファイルå�?として、ユニã?ク化しますã?
180             *
181             * ※ ãƒ?‚£レクトリの作æ?に失敗したå?合ã?RuntimeException ã�?throw されますã?
182             *
183             * @param       dir     セーブするディレクトリ。null の場合ã?、セーブしなã�??
184             * @param       newNm   セーブするファイルå�?null の場合ã?ã€?�ž重è¤?Œ–された添付ファイルå�?
185             * @param       fno     添付ファイルの番号
186             */
187            public void saveFileName( final String dir, final String newNm, final int fno ) {
188                    if( dir == null ) { return ; }          // ファイルをセーブしなã�??
189    
190                    File fileDir = new File( dir );
191                    if( !fileDir.exists() ) {
192                            boolean isOk = fileDir.mkdirs();
193                            if( ! isOk ) {
194                                    String errMsg = "ãƒ?‚£レクトリの作æ?に失敗しましたã€?" + dir + "]";
195                                    throw new RuntimeException( errMsg );
196                            }
197                    }
198    
199                    String newName = ( newNm != null ) ? newNm : names[fno] ;
200    
201                    InputStream      input  = null;
202                    FileOutputStream output = null;
203    
204                    try {
205                            Part prt = files.get( fno );
206                            input = prt.getInputStream();
207                            output = new FileOutputStream( new File( fileDir,newName ) );
208                            byte[] buf = new byte[1024];
209                            int len;
210                            while( (len = input.read(buf)) != -1 ) {
211                                    output.write( buf,0,len );
212                            }
213                    }
214                    catch( MessagingException ex ) {
215                            String errMsg = "メãƒ?‚»ージオブジェクトã?操作中にエラーが発生しましたã€?
216                                                    + "dir=[" + dir + "], file=[" + newName + "], No=[" + fno + "]"
217                                                    + ex.getMessage();                      // 5.1.8.0 (2010/07/01) errMsg 修正
218                            throw new RuntimeException( errMsg,ex );
219                    }
220                    catch( IOException ex ) {
221                            String errMsg = "添付ファイルの取り扱ã�?¸­にエラーが発生しましたã€?
222                                                    + "dir=[" + dir + "], file=[" + newName + "], No=[" + fno + "]"
223                                                    + ex.getMessage();                      // 5.1.8.0 (2010/07/01) errMsg 修正
224                            throw new RuntimeException( errMsg,ex );
225                    }
226                    finally {
227                            Closer.ioClose( output );
228                            Closer.ioClose( input  );
229                    }
230            }
231    }