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.StringUtil ; 019import org.opengion.fukurou.util.HybsEntry ; 020import org.opengion.fukurou.util.LogWriter; 021 022import java.util.Properties; 023import java.util.List; 024import java.util.ArrayList; 025 026import javax.mail.Session; 027import javax.mail.Store; 028import javax.mail.Folder; 029import javax.mail.Message; 030import javax.mail.Flags; 031import javax.mail.MessagingException; 032import javax.mail.NoSuchProviderException; 033import javax.mail.search.SearchTerm; 034import javax.mail.search.SubjectTerm; 035import javax.mail.search.FromStringTerm; 036import javax.mail.search.BodyTerm; 037import javax.mail.search.HeaderTerm; 038import javax.mail.search.AndTerm; 039 040/** 041 * MailRX は、POP3プロトコルによるメール受信プログラムです。 042 * 043 * メールへの接続条件(host,user,passwd など)と、選択条件(matchTermなど)を指定し、 044 * MailReceiveListener をセットして、start() メソッドを呼びます。 045 * 実際のメール処理は、MailReceiveListener を介して、1メールずつ処理します。 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 */ 063public 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}