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 protected UMOMessage handleUnacceptedFilter(UMOMessage message)
170 {
171 super.handleUnacceptedFilter(message);
172 if (message.getPayload() instanceof Message)
173 {
174 Message msg = (Message) message.getPayload();
175 try
176 {
177 msg.setFlag(Flags.Flag.DELETED, endpoint.isDeleteUnacceptedMessages());
178 }
179 catch (MessagingException e)
180 {
181 logger.error("failled to set message deleted: " + e.getMessage(), e);
182 }
183 }
184 return null;
185 }
186
187 public void messagesRemoved(MessageCountEvent event)
188 {
189 if (logger.isDebugEnabled())
190 {
191 Message messages[] = event.getMessages();
192 for (int i = 0; i < messages.length; i++)
193 {
194 try
195 {
196 logger.debug("Message removed: " + messages[i].getSubject());
197 }
198 catch (MessagingException ignore)
199 {
200 logger.debug("ignoring exception: " + ignore.getMessage());
201 }
202 }
203 }
204 }
205
206
207
208
209 public Folder getFolder()
210 {
211 return folder;
212 }
213
214
215
216
217 public synchronized void setFolder(Folder folder)
218 {
219 if (folder == null)
220 {
221 throw new IllegalArgumentException("Mail folder cannot be null");
222 }
223 this.folder = folder;
224 synchronized (this.folder)
225 {
226 if (!this.folder.isOpen())
227 {
228 try
229 {
230 this.folder.open(Folder.READ_WRITE);
231 }
232 catch (MessagingException e)
233 {
234 logger.warn("Failed to open folder: " + folder.getFullName(), e);
235 }
236 }
237 }
238 }
239
240
241
242
243
244
245
246
247
248 protected void storeMessage(Message msg) throws IOException, MessagingException
249 {
250 if (backupEnabled)
251 {
252 String filename = msg.getFileName();
253 if (filename == null)
254 {
255 Address[] from = msg.getFrom();
256 if (from != null && from.length > 0)
257 {
258 filename = from[0] instanceof InternetAddress
259 ? ((InternetAddress) from[0]).getAddress()
260 : from[0].toString();
261 }
262 else
263 {
264 filename = "(no from address)";
265 }
266 filename += "[" + UUID.getUUID() + "]";
267 }
268 filename = FileUtils.prepareWinFilename(filename);
269 filename = backupFolder + filename + ".msg";
270 if (logger.isDebugEnabled())
271 {
272 logger.debug("Writing message to: " + filename);
273 }
274 File f = FileUtils.createFile(filename);
275 FileOutputStream fos = new FileOutputStream(f);
276 msg.writeTo(fos);
277 }
278 }
279
280 public synchronized void poll()
281 {
282 try
283 {
284 try
285 {
286 if (!folder.isOpen())
287 {
288 folder.open(Folder.READ_WRITE);
289 }
290 }
291 catch (Exception e)
292 {
293 if (logger.isDebugEnabled())
294 {
295 logger.debug("ignoring exception: " + e.getMessage());
296 }
297 }
298
299 int count = folder.getMessageCount();
300 if (count > 0)
301 {
302 Message[] messages = folder.getMessages();
303 MessageCountEvent event = new MessageCountEvent(folder, MessageCountEvent.ADDED, true,
304 messages);
305 messagesAdded(event);
306 }
307 else if (count == -1)
308 {
309 throw new MessagingException("Cannot monitor folder: " + folder.getFullName()
310 + " as folder is closed");
311 }
312 }
313 catch (MessagingException e)
314 {
315 handleException(e);
316 }
317 finally
318 {
319 try
320 {
321 folder.close(true);
322 }
323 catch (Exception e)
324 {
325 logger.error("Failed to close pop3 inbox: " + e.getMessage());
326 }
327 }
328 }
329
330 protected void doDispose()
331 {
332 if (null != folder)
333 {
334 folder.removeMessageCountListener(this);
335 if (folder.isOpen())
336 {
337 try
338 {
339
340 folder.close(true);
341 }
342 catch (Exception e)
343 {
344 logger.debug("ignoring exception: " + e.getMessage(), e);
345 }
346 }
347 }
348 }
349
350 }