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.StringUtil ;
019 import org.opengion.fukurou.util.HybsEntry ;
020 import org.opengion.fukurou.util.LogWriter;
021
022 import java.util.Properties;
023 import java.util.List;
024 import java.util.ArrayList;
025
026 import javax.mail.Session;
027 import javax.mail.Store;
028 import javax.mail.Folder;
029 import javax.mail.Message;
030 import javax.mail.Flags;
031 import javax.mail.MessagingException;
032 import javax.mail.NoSuchProviderException;
033 import javax.mail.search.SearchTerm;
034 import javax.mail.search.SubjectTerm;
035 import javax.mail.search.FromStringTerm;
036 import javax.mail.search.BodyTerm;
037 import javax.mail.search.HeaderTerm;
038 import javax.mail.search.AndTerm;
039
040 /**
041 * MailRX は、POP3プロトコルによるメール受信プログラ?す?
042 *
043 * メールへの接続条件(host,user,passwd など)と?択条件(matchTermなど)を指定し?
044 * MailReceiveListener をセ?して、start() メソ?を呼びます?
045 * 実際のメール処??、MailReceiveListener を介して?メールずつ処?ます?
046 * 添付ファイルを??る?合?、MailAttachFiles クラスを使用します?
047 *
048 * host メールサーバ?(??)
049 * user メールを取得するログインユーザー(??)
050 * passwd メールを取得するログインパスワー???)
051 * protocol 受信サーバ?のプロトコル[imap/pop3]を指?初期値:pop3)
052 * port 受信サーバ?のポ?トを??初期値:-1)
053 * mbox 受信サーバ?のメールボックスを指?初期値:INBOX)
054 * maxRowCount 受信メールの?取り込み件数(初期値:100)(0:[無制限])
055 * charset メールの?ォルトエンコー?初期値:ISO-2022-JP)
056 * matchTerm 受信メールを選択する条件のMINEntryオブジェク?
057 * delete 検索後?メールをサーバ?から削除するかど?を?true/falseで??初期値:false)?
058 *
059 * @version 4.0
060 * @author Kazuhiko Hasegawa
061 * @since JDK5.0,
062 */
063 public class MailRX {
064
065 /** 受信メールの?取り込み件数を指定します? {@value} */
066 public static final int MAX_ROW_COUNT = 100 ;
067
068 /** 検索後?メールをサーバ?から削除するかど?を?true/falseで?します? {@value} */
069 public static final boolean DELETE_MESSAGE = false ;
070
071 /** メールサーバ?の?ォルト?ロトコル {@value} */
072 public static final String PROTOCOL = "pop3" ;
073
074 /** メールサーバ?の?ォルト?ート番号 {@value} */
075 public static final int PORT = -1 ;
076
077 /** メールサーバ?の?ォルトメールボックス {@value} */
078 public static final String MBOX = "INBOX" ;
079
080 /** メールの?ォルトエンコー?{@value}
081 * Windwos-31J , MS932 , ISO-2022-JP を指定します?
082 */
083 public static final String CHARSET = "ISO-2022-JP" ;
084
085 // メール受信毎に発生するイベントを伝えるリスナ?を登録します?
086 private MailReceiveListener listener = null;
087
088 private String host = null;
089 private String user = null;
090 private String passwd = null;
091 private String protocol = PROTOCOL;
092 private int port = PORT;
093 private String mbox = MBOX;
094 private boolean deleteFlag = DELETE_MESSAGE;
095
096 private String charset = CHARSET;
097
098 private int maxRowCount = MAX_ROW_COUNT;
099 private final List<HybsEntry> matchList = new ArrayList<HybsEntry>();
100 private boolean debug = false;
101
102 /**
103 * レシーバ?を開始します?
104 *
105 */
106 public void start() throws MessagingException,NoSuchProviderException {
107
108 // パラメータの解析?取?
109 debugMsg( "パラメータの解析?取? );
110
111 // ??条件にマッチしたメ?ージのみ抜き出す為の、SearchTerm オブジェクト?作?
112 debugMsg( "??条件にマッチしたメ?ージのみ抜き出す条件を設定します?" );
113 HybsEntry[] matchs = matchList.toArray( new HybsEntry[matchList.size()] );
114 SearchTerm[] term = new SearchTerm[matchs.length];
115 for( int i=0; i<matchs.length; i++ ) {
116 String key = matchs[i].getKey();
117 if( "Subject".equalsIgnoreCase( key ) ) {
118 term[i] = new SubjectTerm( matchs[i].getValue() );
119 }
120 else if( "From".equalsIgnoreCase( key ) ) {
121 term[i] = new FromStringTerm( matchs[i].getValue() );
122 }
123 else if( "Body".equalsIgnoreCase( key ) ) {
124 term[i] = new BodyTerm( matchs[i].getValue() );
125 }
126 else {
127 term[i] = new HeaderTerm( key,matchs[i].getValue() );
128 }
129 }
130 SearchTerm srchTerm = new AndTerm( term );
131
132 // 空の properties を設定?気休め程度に、?期?を設定しておきます?
133 debugMsg( "空の properties を設? );
134 Properties prop = new Properties();
135 prop.setProperty("mail.mime.charset", charset);
136 prop.setProperty("mail.mime.decodetext.strict", "false");
137 prop.setProperty("mail.mime.address.strict", "false");
138
139 // session を取?
140 debugMsg( "session を取? );
141 Session session = Session.getInstance(prop, null);
142
143 Store store = null;
144 Folder folder = null;
145 try {
146 // store の取?
147 debugMsg( "store の取?protocol=",protocol );
148 store = session.getStore( protocol );
149
150 // サーバ?と connect します?
151 debugMsg( "サーバ?と connect します?" );
152 store.connect(host, port, user, passwd);
153
154 // folder の取?
155 debugMsg( "folder の取? );
156 folder = store.getFolder( mbox );
157 if( deleteFlag ) {
158 folder.open(Folder.READ_WRITE);
159 }
160 else {
161 folder.open(Folder.READ_ONLY);
162 }
163
164 // メ?ージ??の取?
165 debugMsg( "メ?ージ??の取? );
166 // Message[] message = folder.getMessages();
167 Message[] message = folder.search( srchTerm );
168
169 for(int i=0, n=message.length; i<n && i<maxRowCount; i++) {
170 MailMessage mailMessage = new MailMessage( message[i],host,user );
171 debugMsg( "[" , String.valueOf(i) , "]" , mailMessage.getMessageID() , " 受信中" );
172
173 // メールの削除[true/false]:先にフラグを立てて?ので、エラーでも削除されます?
174 message[i].setFlag(Flags.Flag.DELETED, deleteFlag);
175
176 boolean okFlag = true;
177 if( listener != null ) {
178 // メール本体?処?
179 okFlag = listener.receive( mailMessage );
180 }
181
182 // 受?確認?返信メール
183 String notifyTo = mailMessage.getNotificationTo() ;
184 if( okFlag && notifyTo != null ) {
185 MailTX tx = new MailTX( host );
186 tx.setFrom( user );
187 tx.setTo( StringUtil.csv2Array( notifyTo ) );
188 tx.setSubject( "受?:" + mailMessage.getSubject() );
189 tx.setMessage( mailMessage.getContent() );
190 tx.sendmail();
191 }
192 }
193 }
194 finally {
195 // セ?ョン終?
196 debugMsg( "セ?ョン終??? );
197 if( folder != null ) {
198 folder.close(deleteFlag); // true の場合?、終?に実際に削除します?
199 }
200 if( store != null ) {
201 store.close();
202 }
203 }
204 }
205
206 /**
207 * メールサーバ?をセ?します?
208 *
209 * @param host メールサーバ?
210 * @throws IllegalArgumentException 引数?null の場合?
211 */
212 public void setHost( final String host ) {
213 if( host == null ) {
214 String errMsg = "host に null はセ?出来ません?;
215 throw new IllegalArgumentException( errMsg );
216 }
217
218 this.host = host;
219 }
220
221 /**
222 * 受信ユーザーをセ?します?
223 *
224 * @param user 受信ユーザー
225 * @throws IllegalArgumentException 引数?null の場合?
226 */
227 public void setUser( final String user ) {
228 if( user == null ) {
229 String errMsg = "user に null はセ?出来ません?;
230 throw new IllegalArgumentException( errMsg );
231 }
232 this.user = user;
233 }
234
235 /**
236 * パスワードをセ?します?
237 *
238 * @param passwd パスワー?
239 * @throws IllegalArgumentException 引数?null の場合?
240 */
241 public void setPasswd( final String passwd ) {
242 if( passwd == null ) {
243 String errMsg = "passwd に null はセ?出来ません?;
244 throw new IllegalArgumentException( errMsg );
245 }
246 this.passwd = passwd;
247 }
248
249 /**
250 * 受信プロトコルをセ?します?
251 *
252 * @param protocol 受信プロトコル?
253 * @throws IllegalArgumentException 引数?null の場合?
254 */
255 public void setProtocol( final String protocol ) {
256 if( protocol == null ) {
257 String errMsg = "protocol に null はセ?出来ません?;
258 throw new IllegalArgumentException( errMsg );
259 }
260 this.protocol = protocol;
261 }
262
263 /**
264 * ポ?ト番号をセ?します?
265 *
266 * @param port ポ?ト番号
267 */
268 public void setPort( final int port ) {
269 this.port = port;
270 }
271
272 /**
273 * 受信メイルボックスをセ?します?
274 *
275 * @param mbox 受信メイルボックス?
276 * @throws IllegalArgumentException 引数?null の場合?
277 */
278 public void setMbox( final String mbox ) {
279 if( mbox == null ) {
280 String errMsg = "mbox に null はセ?出来ません?;
281 throw new IllegalArgumentException( errMsg );
282 }
283 this.mbox = mbox;
284 }
285
286 /**
287 * メール受信毎に発生するイベントを伝えるリスナ?をセ?します?
288 *
289 * @param listener MailReceiveリスナ?
290 */
291 public void setMailReceiveListener( final MailReceiveListener listener ) {
292 this.listener = listener;
293 }
294
295 /**
296 * メ?ージをメールサーバ?から削除するかど?をセ?します?
297 *
298 * @param deleteFlag 削除するかど?[true:行う/false:行わない]
299 */
300 public void setDelete( final boolean deleteFlag ) {
301 this.deleteFlag = deleteFlag;
302 }
303
304 /**
305 * ?エンコー?ングをセ?します?
306 *
307 * ?エンコー?ングには、Windwos-31J , MS932 , ISO-2022-JP を指定できます?
308 * 初期値は、SystemResource.properties ファイルの MAIL_DEFAULT_CHARSET 属?で
309 * 設定できます?
310 *
311 * @param charset ?エンコー?ング
312 * @throws IllegalArgumentException 引数?null の場合?
313 */
314 public void setCharset( final String charset ) {
315 if( charset == null ) {
316 String errMsg = "charset に null はセ?出来ません?;
317 throw new IllegalArgumentException( errMsg );
318 }
319 this.charset = charset;
320 }
321
322 /**
323 * ?取り込み件数をセ?しま?初期値:100)(0:[無制限])?
324 *
325 * @og.rev 5.5.8.5 (2012/11/27) 0を無制限として処?ます?
326 *
327 * @param maxRowCount ?取り込み件数
328 */
329 public void setMaxRowCount( final int maxRowCount ) {
330 // this.maxRowCount = maxRowCount;
331 this.maxRowCount = ( maxRowCount > 0 ) ? maxRowCount : Integer.MAX_VALUE ;
332 }
333
334 /**
335 * メール検索する場合?マッチ条件のキーと値の HybsEntry をセ?します?
336 * Subject,From,Body,それ以外?、Header ??をキーにします?
337 *
338 * @param matchTerm HybsEntryオブジェク?
339 */
340 public void addMatchTerm( final HybsEntry matchTerm ) {
341 matchList.add( matchTerm );
342 }
343
344 /**
345 * ????の表示を行うかど?をセ?します?
346 *
347 * @param debug 有無[true/false]
348 */
349 public void setDebug( final boolean debug ) {
350 this.debug = debug;
351 }
352
353 /**
354 * ????の表示を行います?
355 * 実際の処??、debug フラグに設定?によります?
356 *
357 * @param msgs String... 可変長メ?ージ
358 */
359 private void debugMsg( final String... msgs ) {
360 if( debug ) {
361 for( String msg : msgs ) {
362 System.out.print( msg );
363 }
364 System.out.println();
365 }
366 }
367
368 /**
369 * コマンドから実行できる、テスト用の main メソ?です?
370 *
371 * java org.opengion.fukurou.mail.MailTX <from> <to> <host> <file> ....
372 * で、?の添付ファイルを?付することができます?
373 *
374 * @param args 引数配?
375 */
376 public static void main( final String[] args ) throws Exception {
377 if(args.length < 3) {
378 LogWriter.log("Usage: java org.opengion.fukurou.mail.MailRX <host> <user> <passwd> [<saveDir>]");
379 System.exit(1);
380 }
381 final String dir = (args.length == 4) ? args[3] : null;
382
383 MailRX recive = new MailRX();
384
385 recive.setHost( args[0] );
386 recive.setUser( args[1] );
387 recive.setPasswd( args[2] );
388 recive.setCharset( "ISO-2022-JP" );
389
390 MailReceiveListener listener = new MailReceiveListener() {
391 public boolean receive( final MailMessage message ) {
392 System.out.println( message.getSimpleMessage() );
393
394 if( dir != null ) {
395 message.saveSimpleMessage( dir );
396 }
397 return true ;
398 }
399 };
400 recive.setMailReceiveListener( listener );
401
402 recive.start();
403 }
404 }