1
2
3
4
5
6
7
8
9
10
11 package org.mule.providers.email;
12
13 import org.mule.MuleManager;
14 import org.mule.impl.MuleMessage;
15 import org.mule.providers.AbstractPollingMessageReceiver;
16 import org.mule.providers.email.i18n.EmailMessages;
17 import org.mule.umo.UMOComponent;
18 import org.mule.umo.UMOException;
19 import org.mule.umo.UMOMessage;
20 import org.mule.umo.endpoint.UMOEndpoint;
21 import org.mule.umo.lifecycle.InitialisationException;
22 import org.mule.umo.lifecycle.Startable;
23 import org.mule.umo.lifecycle.Stoppable;
24 import org.mule.umo.provider.ReceiveException;
25 import org.mule.umo.provider.UMOConnector;
26 import org.mule.umo.routing.RoutingException;
27 import org.mule.util.FileUtils;
28 import org.mule.util.StringUtils;
29 import org.mule.util.UUID;
30
31 import java.io.File;
32 import java.io.FileOutputStream;
33 import java.io.IOException;
34
35 import javax.mail.Address;
36 import javax.mail.Flags;
37 import javax.mail.Folder;
38 import javax.mail.Message;
39 import javax.mail.MessagingException;
40 import javax.mail.Store;
41 import javax.mail.event.MessageCountEvent;
42 import javax.mail.event.MessageCountListener;
43 import javax.mail.internet.InternetAddress;
44 import javax.mail.internet.MimeMessage;
45
46
47
48
49
50
51
52 public class RetrieveMessageReceiver extends AbstractPollingMessageReceiver
53 implements MessageCountListener, Startable, Stoppable
54 {
55 private Folder folder = null;
56 private boolean backupEnabled;
57 private String backupFolder = null;
58
59 public RetrieveMessageReceiver(UMOConnector connector,
60 UMOComponent component,
61 UMOEndpoint endpoint,
62 long checkFrequency,
63 boolean backupEnabled,
64 String backupFolder)
65 throws InitialisationException
66 {
67 super(connector, component, endpoint);
68 this.backupFolder = backupFolder;
69 this.backupEnabled = backupEnabled;
70 this.setFrequency(checkFrequency);
71 }
72
73 private AbstractRetrieveMailConnector castConnector()
74 {
75 return (AbstractRetrieveMailConnector) getConnector();
76 }
77
78 protected void doConnect() throws Exception
79 {
80 SessionDetails session = castConnector().getSessionDetails(endpoint);
81
82 Store store = session.newStore();
83 store.connect();
84 folder = store.getFolder(castConnector().getMailboxFolder());
85
86
87 if (StringUtils.isEmpty(backupFolder))
88 {
89 this.backupFolder =
90 MuleManager.getConfiguration().getWorkingDirectory() + "/mail/" + folder.getName();
91 }
92
93 if (backupFolder != null && !this.backupFolder.endsWith(File.separator))
94 {
95 this.backupFolder += File.separator;
96 }
97 }
98
99 protected void doDisconnect() throws Exception
100 {
101
102 }
103
104 protected void doStop()
105 {
106 if (folder != null)
107 {
108 folder.removeMessageCountListener(this);
109 }
110 }
111
112 protected void doStart() throws UMOException
113 {
114 super.doStart();
115 folder.addMessageCountListener(this);
116 }
117
118 public void messagesAdded(MessageCountEvent event)
119 {
120 Message messages[] = event.getMessages();
121 if (messages != null)
122 {
123 UMOMessage message = null;
124 for (int i = 0; i < messages.length; i++)
125 {
126 try
127 {
128 if (!messages[i].getFlags().contains(Flags.Flag.DELETED))
129 {
130 MimeMessage mimeMessage = new MimeMessage((MimeMessage) messages[i]);
131 storeMessage(mimeMessage);
132 message = new MuleMessage(castConnector().getMessageAdapter(mimeMessage));
133
134 if (castConnector().isDeleteReadMessages())
135 {
136
137 messages[i].setFlag(Flags.Flag.DELETED, true);
138 }
139 else
140 {
141 messages[i].setFlag(Flags.Flag.SEEN, true);
142 }
143 routeMessage(message, endpoint.isSynchronous());
144 }
145 }
146 catch (UMOException e)
147 {
148 handleException(e);
149 }
150 catch (Exception e)
151 {
152 Exception forwarded;
153
154 if (message != null)
155 {
156 forwarded = new RoutingException(EmailMessages.routingError(), message, endpoint, e);
157 }
158 else
159 {
160 forwarded = new ReceiveException(endpoint, -1, e);
161 }
162
163 handleException(forwarded);
164 }
165 }
166 }
167 }
168
169
170 protected UMOMessage handleUnacceptedFilter(UMOMessage message)
171 {
172 super.handleUnacceptedFilter(message);
173 if (message.getPayload() instanceof Message)
174 {
175 Message msg = (Message) message.getPayload();
176 try
177 {
178 msg.setFlag(Flags.Flag.DELETED, endpoint.isDeleteUnacceptedMessages());
179 }
180 catch (MessagingException e)
181 {
182 logger.error("failed to set message deleted: " + e.getMessage(), e);
183 }
184 }
185 return message;
186 }
187
188 public void messagesRemoved(MessageCountEvent event)
189 {
190 if (logger.isDebugEnabled())
191 {
192 Message messages[] = event.getMessages();
193 for (int i = 0; i < messages.length; i++)
194 {
195 try
196 {
197 logger.debug("Message removed: " + messages[i].getSubject());
198 }
199 catch (MessagingException ignore)
200 {
201 logger.debug("ignoring exception: " + ignore.getMessage());
202 }
203 }
204 }
205 }
206
207
208
209
210 public Folder getFolder()
211 {
212 return folder;
213 }
214
215
216
217
218 public synchronized void setFolder(Folder folder)
219 {
220 if (folder == null)
221 {
222 throw new IllegalArgumentException("Mail folder cannot be null");
223 }
224 this.folder = folder;
225 synchronized (this.folder)
226 {
227 if (!this.folder.isOpen())
228 {
229 try
230 {
231 this.folder.open(Folder.READ_WRITE);
232 }
233 catch (MessagingException e)
234 {
235 logger.warn("Failed to open folder: " + folder.getFullName(), e);
236 }
237 }
238 }
239 }
240
241
242
243
244
245
246
247
248
249 protected void storeMessage(Message msg) throws IOException, MessagingException
250 {
251 if (backupEnabled)
252 {
253 String filename = msg.getFileName();
254 if (filename == null)
255 {
256 Address[] from = msg.getFrom();
257 if (from != null && from.length > 0)
258 {
259 filename = from[0] instanceof InternetAddress
260 ? ((InternetAddress) from[0]).getAddress()
261 : from[0].toString();
262 }
263 else
264 {
265 filename = "(no from address)";
266 }
267 filename += "[" + UUID.getUUID() + "]";
268 }
269 filename = FileUtils.prepareWinFilename(filename);
270 filename = backupFolder + filename + ".msg";
271 if (logger.isDebugEnabled())
272 {
273 logger.debug("Writing message to: " + filename);
274 }
275 File f = FileUtils.createFile(filename);
276 FileOutputStream fos = new FileOutputStream(f);
277 msg.writeTo(fos);
278 }
279 }
280
281 public synchronized void poll()
282 {
283 try
284 {
285 try
286 {
287 if (!folder.isOpen())
288 {
289 folder.open(Folder.READ_WRITE);
290 }
291 }
292 catch (Exception e)
293 {
294 if (logger.isDebugEnabled())
295 {
296 logger.debug("ignoring exception: " + e.getMessage());
297 }
298 }
299
300 int count = folder.getMessageCount();
301 if (count > 0)
302 {
303 Message[] messages = folder.getMessages();
304 MessageCountEvent event = new MessageCountEvent(folder, MessageCountEvent.ADDED, true,
305 messages);
306 messagesAdded(event);
307 }
308 else if (count == -1)
309 {
310 throw new MessagingException("Cannot monitor folder: " + folder.getFullName()
311 + " as folder is closed");
312 }
313 }
314 catch (MessagingException e)
315 {
316 handleException(e);
317 }
318 finally
319 {
320 try
321 {
322 folder.close(true);
323 }
324 catch (Exception e)
325 {
326 logger.error("Failed to close pop3 inbox: " + e.getMessage());
327 }
328 }
329 }
330
331 protected void doDispose()
332 {
333 if (null != folder)
334 {
335 folder.removeMessageCountListener(this);
336 if (folder.isOpen())
337 {
338 try
339 {
340
341 folder.close(true);
342 }
343 catch (Exception e)
344 {
345 logger.debug("ignoring exception: " + e.getMessage(), e);
346 }
347 }
348 }
349 }
350
351 }