001/*
002 * Copyright (c) 2009 The openGion Project.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
013 * either express or implied. See the License for the specific language
014 * governing permissions and limitations under the License.
015 */
016package org.opengion.fukurou.mail;
017
018import org.opengion.fukurou.util.HybsEntry ;
019import org.opengion.fukurou.util.Argument ;
020import org.opengion.fukurou.util.LogWriter;
021
022import java.util.Map;
023import java.util.LinkedHashMap;
024
025import java.util.logging.Logger;
026import java.util.logging.Level;
027import javax.mail.MessagingException ;
028
029/**
030 * MailReceiver は、POP3プロトコルによるメール受信プログラムです。
031 *
032 * 引数には、host,user,passwd,headerList,mailSaveDir,fileSaveDir,filter,help が指定できます。
033 * メールは、メッセージID名をファイル名として、セーブします。
034 * 添付ファイルは、元のファイル名で、指定のディレクトリに出力される為、複数のメールを
035 * 同時に抜く場合は、uniq 属性を付与してください。その場合は、メッセージID+連番+元のファイル名
036 * で、ファイルをセーブします。添付ファイルには、同名のファイルを複数添付することが
037 * できるため、保存時には、添付ファイルの番号を連番としてファイル名に、付与します。
038 *
039 * 引数のプロパテイのキー部は、大文字・小文字が厳格に適用されますので、正確に記述願います。
040 *
041 * Usage: java org.opengion.fukurou.fukurou.mail.MailReceiver
042 *        -host=メールサーバー(必須)
043 *        -user=メールを取得するログインユーザー(必須)
044 *        -passwd=メールを取得するログインパスワード(必須)
045 *        -protocol=受信サーバーのプロトコル[imap/pop3]を指定(初期値:pop3)
046 *        -port=受信サーバーのポートを指定(初期値:-1)
047 *        -mailSaveDir=受信メールをセーブするディレクトリ。指定がない場合は、標準出力へ出力する。
048 *        -fileSaveDir=添付ファイルをセーブするディレクトリ。指定がない場合は抜き出さない。
049 *        -useMsgId=添付ファイルをセーブするディレクトリに、MesssageIdフォルダを個別に割り当てるかどうか(初期値:false)
050 *        -maxRowCount=受信メールの最大取り込み件数(初期値:100)(0:[無制限])
051 *        -match_Subject=受信メールのSubjectを選択する条件
052 *        -match_Body=受信メールのBodyを選択する条件
053 *        -match_From=受信メールのFromを選択する条件
054 *        -match_XXXX=受信メールのヘッダー部のキーXXXXを選択する条件
055 *        -delete=検索後、メールをサーバーから削除するかどうかを、true/falseで指定(初期値:false)
056 *        -help=使用方法を出力して、終了します。
057 *
058 * @version  0.9.0  2000/11/13
059 * @author   Kazuhiko Hasegawa
060 * @since    JDK5.0,
061 */
062public class MailReceiver {
063        private static Logger logger = Logger.getLogger( "org.opengion.fukurou.fukurou.mail.MailReceiver" );            // 4.3.3.5 (2008/11/08)
064
065        private static final String CR = System.getProperty("line.separator");
066
067        /** 受信メールの最大取り込み件数を指定します。 {@value}  */
068        public static final int MAX_ROW_COUNT = 100 ;
069
070        /** 検索後、メールをサーバーから削除するかどうかを、true/falseで指定します。 {@value}  */
071        public static final boolean DELETE_MESSAGE = false ;
072
073        /** メールサーバーのデフォルトプロトコル {@value}  */
074        public static final String PROTOCOL = "pop3" ;
075
076        /** メールサーバーのデフォルトポート番号 {@value}  */
077        public static final int PORT = -1 ;
078
079        private Argument argment = null;
080
081        private static final Map<String,String> mustProparty   ;
082        private static final Map<String,String> usableProparty ;
083
084        static {
085                mustProparty = new LinkedHashMap<String,String>();
086                mustProparty.put( "host",       "メールサーバー(必須)" );
087                mustProparty.put( "user",       "メールを取得するログインユーザー(必須)" );
088                mustProparty.put( "passwd",     "メールを取得するログインパスワード(必須)" );
089
090                usableProparty = new LinkedHashMap<String,String>();
091                usableProparty.put( "protocol", "受信サーバーのプロトコル(imap,pop3)を指定(初期値:pop3)" );
092                usableProparty.put( "port",             "受信サーバーのポートを指定(初期値:-1)" );
093                usableProparty.put( "mailSaveDir",      "受信メールをセーブするディレクトリ。" +
094                                                                        CR + "指定がない場合は、標準出力へ出力する。" );
095                usableProparty.put( "fileSaveDir",      "添付ファイルをセーブするディレクトリ。" +
096                                                                        CR + "指定がない場合は抜き出さない。" );
097                usableProparty.put( "useMsgId", "添付ファイルをセーブするディレクトリに、" +
098                                                                        CR + "MesssageIdフォルダを個別に割り当てるかどうか。" );
099                usableProparty.put( "maxRowCount",      "受信メールの最大取り込み件数(初期値:100)(0:[無制限])" );
100                usableProparty.put( "match_Subject", "受信メールのSubjectを選択する条件" );
101                usableProparty.put( "match_Body",       "受信メールのBodyを選択する条件" );
102                usableProparty.put( "match_From",       "受信メールのFromを選択する条件" );
103                usableProparty.put( "match_",           "受信メールのヘッダー部のキーXXXXを選択する条件" );
104                usableProparty.put( "delete",           "検索後、メールをサーバーから削除するかどうかを、" +
105                                                                        CR + "true/falseで指定(初期値:false)" );
106                usableProparty.put( "help",                     "使用方法を出力して、終了します。" );
107        }
108
109        /**
110         * レシーバーを開始します。
111         *
112         * @og.rev 4.3.3.5 (2008/11/08) Argument オブジェクトへの引数を util → mail に訂正します。
113         *
114         * @param   args 引数配列
115         * @throws MessagingException なんらかのエラーが発生した場合。
116         */
117        public void start( final String[] args ) throws MessagingException {
118
119                // パラメータの解析、取得
120                logger.fine( "パラメータの解析、取得" );
121                argment = new Argument( "org.opengion.fukurou.fukurou.mail.MailReceiver" );             // 4.3.3.5 (2008/11/08)
122                argment.setMustProparty( mustProparty );
123                argment.setUsableProparty( usableProparty );
124
125                argment.setArgument( args );
126
127                // help パラメータが true に指定された場合の処理。
128                if( argment.getProparty( "help",false ) ) {
129                        System.out.println( argment.toString() );
130                        return;
131                }
132
133                // 処理に必要な各種パラメータを取得しておきます。
134                logger.fine( "処理に必要な各種パラメータを取得します。" );
135                MailRX recive = new MailRX();
136
137                recive.setHost(                 argment.getProparty( "host" ) ) ;
138                recive.setUser(                 argment.getProparty( "user" ) ) ;
139                recive.setPasswd(               argment.getProparty( "passwd" ) ) ;
140                recive.setProtocol(             argment.getProparty( "protocol",PROTOCOL ) ) ;
141                recive.setPort(                 argment.getProparty( "port",PORT ) ) ;
142                recive.setDelete(               argment.getProparty( "delete",DELETE_MESSAGE ) ) ;
143                recive.setMaxRowCount(  argment.getProparty( "maxRowCount",MAX_ROW_COUNT ) ) ;
144
145                // 指定の条件にマッチしたメッセージのみ抜き出す為の、SearchTerm オブジェクトの作成
146                logger.fine( "指定の条件にマッチしたメッセージのみ抜き出す条件を設定します。" );
147                HybsEntry[] matchs = argment.getEntrys( "match_" );
148                for( int i=0; i<matchs.length; i++ ) {
149                        recive.addMatchTerm( matchs[i] ) ;
150                }
151
152                // リスナーを設定して、受信メールを一件ずつ処理します。
153                logger.fine( "リスナーを設定して、受信メールを一件ずつ処理します。" );
154                String mailSaveDir = argment.getProparty( "mailSaveDir" );
155                String fileSaveDir = argment.getProparty( "fileSaveDir" );
156                boolean useMsgId   = argment.getProparty( "useMsgId",false );
157
158                MailReceiveListener listener = new ReceiveListener( mailSaveDir,fileSaveDir,useMsgId ) ;
159                recive.setMailReceiveListener( listener );
160
161                recive.start();
162        }
163
164        /**
165         * メール受信プログラムで使用する MailReceiveListener の実装内部クラスです。
166         *
167         * @version  0.9.0  2000/11/13
168         * @author   Kazuhiko Hasegawa
169         * @since    JDK5.0,
170         */
171        private static class ReceiveListener implements MailReceiveListener {
172                private final String  mailSaveDir ;
173                private final String  fileSaveDir ;
174                private final boolean useMsgId ;
175                private int   counter = 0;
176
177                /**
178                 * コンストラクター
179                 *
180                 * @param       mailSaveDir     メールをセーブする場合の保存フォルダ名
181                 * @param       fileSaveDir     メールの添付ファイルをセーブする場合の保存フォルダ名
182                 * @param       useMsgId        添付ファイルをセーブする場合に、メッセージIDを使用するかどうか
183                 */
184                public ReceiveListener( final String mailSaveDir,final String fileSaveDir,final boolean useMsgId ) {
185                        this.mailSaveDir = mailSaveDir;
186                        this.fileSaveDir = fileSaveDir;
187                        this.useMsgId    = useMsgId;
188                }
189
190                /**
191                 * 受信処理を行います。
192                 *
193                 * @param   message MailMessage
194                 * @return      結果(true:正常/false:異常)
195                 */
196                public boolean receive( final MailMessage message ) {
197                        String msg = "[" + counter++ + "]" + message.getMessageID() + " 受信中" ;
198                        System.out.println( msg );
199
200                        if( mailSaveDir != null ) {
201                                message.saveMessage( mailSaveDir );
202                        }
203                        else {
204                                System.out.println( message.getSubject() );
205                                System.out.println( message.getContent() );
206                        }
207
208                        if( fileSaveDir != null ) {
209                                message.saveAttachFiles( fileSaveDir,useMsgId );
210                        }
211                        return true ;
212                }
213        }
214
215        /**
216         * main メソッドです。
217         *
218         * @param       args    コマンド引数配列
219         */
220        public static void main ( final String[] args ) {
221                MailReceiver receiver = new MailReceiver();
222                try {
223                        logger.info( "メール受信処理を開始します  ---------------------------------------------" );
224                        receiver.start( args );
225                        logger.info( "正常に終了しました。" );
226                }
227                catch( Throwable th ) {
228                        String errMsg = "メール受信中に例外が発生しました。 "
229                                        + CR + receiver.argment
230                                        + CR + th.getMessage() ;
231                        LogWriter.log( errMsg );
232                        logger.log( Level.SEVERE,errMsg, th );
233                        throw new RuntimeException( errMsg,th );        // 4.0.0 (2005/01/31)
234                }
235        }
236}