Quadcap Embeddable Server

com/quadcap/pop3/client/Pop3Agent.java

Go to the documentation of this file.
00001 package com.quadcap.pop3.client; 00002 00003 /* Copyright 1997 - 2003 Quadcap Software. All rights reserved. 00004 * 00005 * This software is distributed under the Quadcap Free Software License. 00006 * This software may be used or modified for any purpose, personal or 00007 * commercial. Open Source redistributions are permitted. Commercial 00008 * redistribution of larger works derived from, or works which bundle 00009 * this software requires a "Commercial Redistribution License"; see 00010 * http://www.quadcap.com/purchase. 00011 * 00012 * Redistributions qualify as "Open Source" under one of the following terms: 00013 * 00014 * Redistributions are made at no charge beyond the reasonable cost of 00015 * materials and delivery. 00016 * 00017 * Redistributions are accompanied by a copy of the Source Code or by an 00018 * irrevocable offer to provide a copy of the Source Code for up to three 00019 * years at the cost of materials and delivery. Such redistributions 00020 * must allow further use, modification, and redistribution of the Source 00021 * Code under substantially the same terms as this license. 00022 * 00023 * Redistributions of source code must retain the copyright notices as they 00024 * appear in each source code file, these license terms, and the 00025 * disclaimer/limitation of liability set forth as paragraph 6 below. 00026 * 00027 * Redistributions in binary form must reproduce this Copyright Notice, 00028 * these license terms, and the disclaimer/limitation of liability set 00029 * forth as paragraph 6 below, in the documentation and/or other materials 00030 * provided with the distribution. 00031 * 00032 * The Software is provided on an "AS IS" basis. No warranty is 00033 * provided that the Software is free of defects, or fit for a 00034 * particular purpose. 00035 * 00036 * Limitation of Liability. Quadcap Software shall not be liable 00037 * for any damages suffered by the Licensee or any third party resulting 00038 * from use of the Software. 00039 */ 00040 00041 import java.util.ArrayList; 00042 import java.util.Date; 00043 import java.util.Enumeration; 00044 import java.util.HashMap; 00045 import java.util.Iterator; 00046 import java.util.Properties; 00047 import java.util.List; 00048 00049 import java.io.DataInputStream; 00050 import java.io.IOException; 00051 import java.io.InputStream; 00052 import java.io.OutputStream; 00053 00054 import java.net.InetAddress; 00055 00056 import com.quadcap.io.HeaderEnumeration; 00057 import com.quadcap.io.IO; 00058 00059 import com.quadcap.util.Debug; 00060 00061 /** 00062 * This simple Pop3 agent transfers all new messages in a remote Pop3 00063 * mailbox into the specified folder in the quadcap message store. 00064 * 00065 * <p>A more sophisticated agent would scan the headers first and apply 00066 * filters to certain messages without having to fetch the bodies. 00067 * 00068 * @author Stan Bailes 00069 */ 00070 public class Pop3Agent { 00071 HashMap uidlMap = new HashMap(); 00072 String hostName = null; 00073 int portNumber = 110; 00074 String login = null; 00075 String passwd = null; 00076 int daysKeep = 999999; 00077 boolean enabled = true; 00078 00079 Session pop3 = null; 00080 00081 public void write(OutputStream w) throws IOException { 00082 Iterator iter = uidlMap.keySet().iterator(); 00083 while (iter.hasNext()) { 00084 UidlEntry u = (UidlEntry)uidlMap.get(iter.next()); 00085 IO.write(w, "UIDL: " + u.toString() + "\n"); 00086 } 00087 } 00088 00089 public void read(InputStream r) throws IOException { 00090 DataInputStream d = new DataInputStream(r); 00091 String line; 00092 while ((line = d.readLine()) != null) { 00093 if (line.startsWith("UIDL: ")) { 00094 line = line.substring(6).trim(); 00095 UidlEntry uidl = new UidlEntry(line); 00096 uidlMap.put(uidl.getUidl(), uidl); 00097 } 00098 } 00099 } 00100 00101 /** 00102 * Default constructor for factory 00103 */ 00104 public Pop3Agent() { 00105 } 00106 00107 /** 00108 * Check for mail 00109 */ 00110 public void run(Properties props, MessageHook hook) { 00111 try { 00112 hostName = props.getProperty("host"); 00113 portNumber = Integer.parseInt(props.getProperty("port", "110")); 00114 login = props.getProperty("user"); 00115 passwd = props.getProperty("passwd"); 00116 daysKeep = Integer.parseInt(props.getProperty("daysKeep", "3")); 00117 enabled = "true".equalsIgnoreCase(props.getProperty("enabled", 00118 "true")); 00119 if (!enabled) return; 00120 00121 if (pop3 == null) { 00122 pop3 = new Session(hostName, portNumber); 00123 } 00124 pop3.connect(); 00125 00126 int ret = pop3.user(login); 00127 if (ret != Session.OK) { 00128 throw new IOException("login failed"); 00129 } 00130 00131 ret = pop3.pass(passwd); 00132 if (ret != Session.OK) { 00133 throw new IOException("login (passwd) failed"); 00134 } 00135 00136 getMail(hook); 00137 } catch (Throwable t) { 00138 Debug.print(t); 00139 } finally { 00140 try { 00141 if (pop3 != null) pop3.quit(); 00142 } catch (IOException e) { 00143 Debug.print(e); 00144 } 00145 // ---- we're about to "go to sleep", potentially for a long time, 00146 // ---- so allow these objects to be gc'ed. 00147 pop3 = null; 00148 } 00149 } 00150 00151 00152 /** 00153 * Figure out what's new and deliver it. Figure out what's old 00154 * and delete it. 00155 */ 00156 void getMail(MessageHook hook) throws IOException { 00157 InputStream uidls = pop3.uidl(); 00158 ArrayList newMessages = new ArrayList(); // list of uidls 00159 ArrayList delMessages = new ArrayList(); // list of msgnums 00160 int msgNum = 0; 00161 String uidl = null; 00162 StringBuffer sb = new StringBuffer(); 00163 Date now = new Date(); 00164 long ms = daysKeep * 24L * 60 * 60 * 1000; 00165 Date windowStart = new Date(now.getTime() - ms); 00166 int c = uidls.read(); 00167 while (c >= 0) { 00168 while (Character.isDigit((char)c)) { 00169 sb.append((char)c); 00170 c = uidls.read(); 00171 } 00172 if (sb.length() == 0) { 00173 if (c < 0) break; 00174 else { 00175 c = uidls.read(); 00176 continue; 00177 } 00178 } 00179 msgNum = Integer.parseInt(sb.toString()); 00180 00181 sb.setLength(0); 00182 while (Character.isWhitespace((char)c)) { 00183 c = uidls.read(); 00184 } 00185 if (c < 0) continue; 00186 while (c >= 0x21 && c <= 0x7e) { 00187 sb.append((char)c); 00188 c = uidls.read(); 00189 } 00190 uidl = sb.toString(); 00191 sb.setLength(0); 00192 UidlEntry e = getUidlEntry(uidl); 00193 if (e == null) { 00194 e = putUidlEntry(uidl, msgNum, now); 00195 newMessages.add(e); 00196 } else { 00197 e.setMessageNumber(msgNum); 00198 if (e.getFirstSeen().before(windowStart)) { 00199 if (!e.markedForDeletion) { 00200 delMessages.add(e); 00201 e.markedForDeletion = true; 00202 } 00203 } 00204 } 00205 while (c >= 0 && c != 0x0a) { 00206 c = uidls.read(); 00207 } 00208 if (c == 0x0a) c = uidls.read(); 00209 } 00210 getMessages(hook, newMessages); 00211 deleteMessages(delMessages); 00212 } 00213 00214 /** 00215 * Get the specified list of messages. 00216 * 00217 * @param v a ArrayList of UidlEntry types, specifying the messages to get. 00218 */ 00219 void getMessages(MessageHook hook, ArrayList v) throws IOException { 00220 for (int i = 0; i < v.size(); i++) { 00221 UidlEntry e = (UidlEntry)v.get(i); 00222 int msg = e.getMessageNumber(); 00223 boolean pass = hook.passAllHeaders(); 00224 if (!pass) { 00225 InputStream is = pop3.top("" + msg, 0); 00226 try { 00227 HashMap map = new HashMap(); 00228 new HeaderEnumeration(is).getHeaderMap(map); 00229 pass = hook.passHeaders(map); 00230 } finally { 00231 is.close(); 00232 } 00233 } 00234 if (pass) { 00235 InputStream body = pop3.retr("" + msg); 00236 try { 00237 if (hook.passMessage(body)) { 00238 if (!e.markedForDeletion) { 00239 pop3.dele(msg); 00240 e.markedForDeletion = true; 00241 } 00242 } 00243 } catch (IOException e1) { 00244 Debug.print(e1); 00245 throw e1; 00246 } catch (Exception e2) { 00247 //#ifdef DEBUG 00248 Debug.print(e2); 00249 //#endif 00250 throw new IOException(e2.toString()); 00251 } finally { 00252 body.close(); 00253 } 00254 } 00255 } 00256 } 00257 00258 /** 00259 * Delete the specified list of messages. 00260 * 00261 * @param v a ArrayList of UidlEntry types, specifying the 00262 * messages to delete. 00263 */ 00264 void deleteMessages(ArrayList v) throws IOException { 00265 for (int i = 0; i < v.size(); i++) { 00266 UidlEntry e = (UidlEntry)v.get(i); 00267 int msg = e.getMessageNumber(); 00268 pop3.dele(msg); 00269 uidlMap.remove(e.getUidl()); 00270 } 00271 } 00272 00273 /** 00274 * Search the map for a specified <b>UIDL</b> entry. 00275 * 00276 * @param uidl the UIDL text to search for 00277 * 00278 * @return if found, the corresponding entry in the map. Otherwise, null. 00279 */ 00280 UidlEntry getUidlEntry(String uidl) { 00281 return (UidlEntry)uidlMap.get(uidl); 00282 } 00283 00284 /** 00285 * Create and store a new UidlEntry in the map. 00286 * 00287 * @param uidl the UIDL text 00288 * @param msgNum the current POP3 session's message number. 00289 * @param d the date for this entry. 00290 * 00291 * @return the new UidlEntry 00292 */ 00293 UidlEntry putUidlEntry(String uidl, int msgNum, Date d) { 00294 UidlEntry e = new UidlEntry(uidl, msgNum, d); 00295 uidlMap.put(uidl, e); 00296 return e; 00297 } 00298 }