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 }