1 25 package org.ofbiz.service.mail; 26 27 import java.util.Iterator ; 28 import java.util.List ; 29 import java.util.Map ; 30 import java.util.Properties ; 31 import java.util.Timer ; 32 import java.util.TimerTask ; 33 import javax.mail.*; 34 import javax.mail.internet.MimeMessage ; 35 import javax.mail.event.StoreEvent ; 36 import javax.mail.event.StoreListener ; 37 38 import org.ofbiz.base.container.Container; 39 import org.ofbiz.base.container.ContainerConfig; 40 import org.ofbiz.base.container.ContainerException; 41 import org.ofbiz.base.util.Debug; 42 import org.ofbiz.base.util.GeneralException; 43 import org.ofbiz.base.util.UtilValidate; 44 import org.ofbiz.base.util.UtilMisc; 45 import org.ofbiz.entity.GenericDelegator; 46 import org.ofbiz.entity.GenericValue; 47 import org.ofbiz.entity.GenericEntityException; 48 import org.ofbiz.service.GenericDispatcher; 49 import org.ofbiz.service.LocalDispatcher; 50 import org.ofbiz.service.GenericServiceException; 51 52 import org.apache.commons.collections.map.LinkedMap; 53 54 60 public class JavaMailContainer implements Container { 61 62 public static final String module = JavaMailContainer.class.getName(); 63 public static final String INBOX = "INBOX"; 64 65 protected GenericDelegator delegator = null; 66 protected LocalDispatcher dispatcher = null; 67 protected GenericValue userLogin = null; 68 protected long timerDelay = 300000; 69 protected Timer pollTimer = null; 70 protected boolean deleteMail = false; 72 protected String configFile = null; 73 protected Map stores = null; 74 75 83 public void init(String [] args, String configFile) throws ContainerException { 84 this.configFile = configFile; 85 this.stores = new LinkedMap(); 86 this.pollTimer = new Timer (); 87 } 88 89 96 public boolean start() throws ContainerException { 97 ContainerConfig.Container cfg = ContainerConfig.getContainer("javamail-container", configFile); 98 String dispatcherName = ContainerConfig.getPropertyValue(cfg, "dispatcher-name", "JavaMailDispatcher"); 99 String delegatorName = ContainerConfig.getPropertyValue(cfg, "delegator-name", "default"); 100 if ("true".equals(ContainerConfig.getPropertyValue(cfg, "delete-mail", "false"))) { 101 this.deleteMail = true; 102 } else { 103 this.deleteMail = false; 104 } 105 106 this.delegator = GenericDelegator.getGenericDelegator(delegatorName); 107 this.dispatcher = new GenericDispatcher(dispatcherName, delegator); 108 this.timerDelay = (long) ContainerConfig.getPropertyValue(cfg, "poll-delay", 300000); 109 110 String runAsUser = ContainerConfig.getPropertyValue(cfg, "run-as-user", "system"); 112 try { 113 this.userLogin = delegator.findByPrimaryKey("UserLogin", UtilMisc.toMap("userLoginId", runAsUser)); 114 } catch (GenericEntityException e) { 115 Debug.logError(e, "Unable to load run-as-user UserLogin; cannot start container", module); 116 return false; 117 } 118 119 ServiceMcaUtil.readConfig(); 121 122 List configs = cfg.getPropertiesWithValue("store-listener"); 124 Iterator i = configs.iterator(); 125 while (i.hasNext()) { 126 ContainerConfig.Container.Property prop = (ContainerConfig.Container.Property) i.next(); 127 Session session = this.makeSession(prop); 128 Store store = this.getStore(session); 129 if (store != null) { 130 stores.put(store, session); 131 } 132 } 133 134 if (stores != null && stores.size() > 0) { 136 pollTimer.schedule(new PollerTask(dispatcher, userLogin), timerDelay, timerDelay); 137 } else { 138 Debug.logWarning("No JavaMail Store(s) configured; poller disabled.", module); 139 } 140 141 return true; 142 } 143 144 150 public void stop() throws ContainerException { 151 this.pollTimer.cancel(); 153 Debug.logInfo("stop JavaMail poller", module); 154 } 155 156 protected Session makeSession(ContainerConfig.Container.Property client) { 158 Properties props = new Properties (); 159 Map clientProps = client.properties; 160 if (clientProps != null) { 161 Iterator i = clientProps.entrySet().iterator(); 162 while (i.hasNext()) { 163 Map.Entry e = (Map.Entry ) i.next(); 164 ContainerConfig.Container.Property p = (ContainerConfig.Container.Property) e.getValue(); 165 props.setProperty(p.name.toLowerCase(), p.value.toLowerCase()); 166 } 167 } 168 return Session.getInstance(props); 169 } 170 171 protected Store getStore(Session session) throws ContainerException { 172 Store store = null; 174 try { 175 store = session.getStore(); 176 } catch (NoSuchProviderException e) { 177 throw new ContainerException(e); 178 } 179 180 if (store != null) { 182 URLName urlName = this.updateUrlName(store.getURLName(), session.getProperties()); 183 Debug.log("URLName - " + urlName.toString(), module); 184 try { 185 store = session.getStore(urlName); 186 } catch (NoSuchProviderException e) { 187 throw new ContainerException(e); 188 } 189 } 190 191 try { 193 store.connect(); 194 store.close(); 195 } catch (MessagingException e) { 196 Debug.logError("Unable to connect to mail store : " + store.getURLName().toString(), module); 197 } 198 199 return store; 200 } 201 202 protected URLName updateUrlName(URLName urlName, Properties props) { 203 String protocol = urlName.getProtocol(); 204 String userName = urlName.getUsername(); 205 String password = urlName.getPassword(); 206 String host = urlName.getHost(); 207 String file = urlName.getFile(); 208 int port = urlName.getPort(); 209 210 if (UtilValidate.isEmpty(userName)) { 212 userName = props.getProperty("mail." + protocol + ".user"); 213 if (UtilValidate.isEmpty(userName)) { 214 userName = props.getProperty("mail.user"); 215 } 216 } 217 218 if (UtilValidate.isEmpty(password)) { 220 password = props.getProperty("mail." + protocol + ".pass"); 221 if (UtilValidate.isEmpty(password)) { 222 password = props.getProperty("mail.pass"); 223 } 224 } 225 226 if (UtilValidate.isEmpty(host)) { 228 host = props.getProperty("mail." + protocol + ".host"); 229 if (UtilValidate.isEmpty(host)) { 230 host = props.getProperty("mail.host"); 231 } 232 } 233 234 Debug.logInfo("Update URL - " + protocol + "://" + userName + "@" + host + ":" + port + "!" + password + ";" + file, module); 235 return new URLName(protocol, host, port, file, userName, password); 236 } 237 238 class LoggingStoreListener implements StoreListener { 239 240 public void notification(StoreEvent event) { 241 String typeString = ""; 242 switch(event.getMessageType()) { 243 case StoreEvent.ALERT: 244 typeString = "ALERT: "; 245 break; 246 case StoreEvent.NOTICE: 247 typeString = "NOTICE: "; 248 break; 249 } 250 251 Debug.log("JavaMail " + typeString + event.getMessage(), module); 252 } 253 } 254 255 class PollerTask extends TimerTask { 256 257 LocalDispatcher dispatcher; 258 GenericValue userLogin; 259 260 public PollerTask(LocalDispatcher dispatcher, GenericValue userLogin) { 261 this.dispatcher = dispatcher; 262 this.userLogin = userLogin; 263 } 264 265 public void run() { 266 if (stores != null && stores.size() > 0) { 267 Iterator i = stores.keySet().iterator(); 268 while (i.hasNext()) { 269 Store store = (Store) i.next(); 270 Session session = (Session) stores.get(store); 271 try { 272 checkMessages(store, session); 273 } catch (GeneralException e) { 274 Debug.logError(e, "Mail service invocation error", module); 275 } catch (MessagingException e) { 276 Debug.logError(e, "Mail message error", module); 277 } 278 } 279 } 280 } 281 282 protected void checkMessages(Store store, Session session) throws MessagingException, GeneralException { 283 store.addStoreListener(new LoggingStoreListener()); 284 store.connect(); 285 286 Folder folder = store.getDefaultFolder(); 288 if (folder == null) { 289 throw new MessagingException("No default folder available"); 290 } 291 292 folder = folder.getFolder(INBOX); 294 if (folder == null) { 295 throw new MessagingException("No INBOX folder available"); 296 } 297 298 folder.open(Folder.READ_WRITE); 300 int totalMessages = folder.getMessageCount(); 301 if (totalMessages == 0) { 302 folder.close(false); 303 store.close(); 304 return; 305 } 306 307 Message [] messages = folder.getMessages(); 309 FetchProfile profile = new FetchProfile(); 310 profile.add(FetchProfile.Item.ENVELOPE); 311 profile.add(FetchProfile.Item.FLAGS); 312 profile.add("X-Mailer"); 313 folder.fetch(messages, profile); 314 315 for (int i = 0; i < messages.length; i++) { 317 if (!messages[i].isSet(Flags.Flag.SEEN)) { 319 this.processMessage(messages[i], session); 320 Debug.logVerbose("Message from " + UtilMisc.toListArray(messages[i].getFrom()) + " with subject [" + messages[i].getSubject() + "] has been processed." , module); 321 messages[i].setFlag(Flags.Flag.SEEN, true); 322 Debug.logVerbose("Message [" + messages[i].getSubject() + "] is marked seen", module); 323 } 324 if (deleteMail) { 325 Debug.logVerbose("Message [" + messages[i].getSubject() + "] is being deleted", module); 326 messages[i].setFlag(Flags.Flag.DELETED, true); 327 } 328 } 329 330 folder.close(true); 332 store.close(); 333 } 334 335 protected void processMessage(Message message, Session session) { 336 if (message instanceof MimeMessage ) { 337 MimeMessageWrapper wrapper = new MimeMessageWrapper(session, (MimeMessage ) message); 338 try { 339 ServiceMcaUtil.evalRules(dispatcher, wrapper, userLogin); 340 } catch (GenericServiceException e) { 341 Debug.logError(e, "Problem processing message", module); 342 } 343 } 344 } 345 } 346 } 347 | Popular Tags |