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