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 }